This chapter provides a few simple examples of server plug-ins that you can compile and implement. Essentially, these examples demonstrate the different types of data available to your plug-in.
The test_preop_search() function logs information about the search, including the base DN of the search, the search scope, and the type of filter used.
The test_preop_init() function is the initialization function that registers test_preop_search() as a SLAPI_PLUGIN_PRE_SEARCH_FN pre-operation plug-in function for LDAP search operations.
Writing the Plug-In Example
The following section of code includes the sample pre-operation search function and the sample initialization function.
#include <stdio.h> #include <string.h> #include "slapi-plugin.h" /* function prototypes */ int test_preop_init( Slapi_PBlock *pb ); int test_preop_search( Slapi_PBlock *pb ); /* Description of the plug-in */ Slapi_PluginDesc srchpdesc = { "test-search", "Airius.com", "0.5", "sample pre-operation search plugin" }; /* Initialization function This function registers your plug-in function as a pre-operation search function in the Directory Server. You need to specify this initialization function in the server configuration file so that the server calls this initialization function on startup. */ #ifdef _WIN32 __declspec(dllexport) #endif int test_preop_init( Slapi_PBlock *pb ) { /* Specify the version of the plug-in ("01" in this release ) */ if ( slapi_pblock_set( pb, SLAPI_PLUGIN_VERSION, SLAPI_PLUGIN_VERSION_01 ) != 0 || /* Specify the description of the plug-in */ slapi_pblock_set( pb, SLAPI_PLUGIN_DESCRIPTION, (void *)&srchpdesc ) != 0 || /* Set test_preop_search() as the function to call before executing LDAP search operations. */ slapi_pblock_set( pb, SLAPI_PLUGIN_PRE_SEARCH_FN, (void *) test_preop_search ) !=0 ) { /* Log an error message and return -1 if a problem occurred */ slapi_log_error( SLAPI_LOG_PLUGIN, "test_preop_init", "Error registering the plug-in.\n" ); return( -1 ); } /* If successful, log a message and return 0 */ slapi_log_error( SLAPI_LOG_PLUGIN, "test_preop_init", "Plug-in successfully registered.\n" ); return( 0 ); } /* Pre-operation plug-in function for LDAP search operations This function is called by the server before processing an LDAP search operation. The function gets data about the search request from the parameter block and prints the data to the error log. */ int test_preop_search( Slapi_PBlock *pb ) { char *base, *filter_str, *attr_type, *substr_init, *substr_final; char **substr_any; int scope, deref, filter_type, i; Slapi_Filter *filter; struct berval *bval; /* Log a message to indicate when the plug-in function starts */ slapi_log_error( SLAPI_LOG_PLUGIN, "test_preop_search", "*** PREOPERATION SEARCH PLUGIN ***\n"); /* Get and log the base DN of the search criteria */ if ( slapi_pblock_get( pb, SLAPI_SEARCH_TARGET, &base ) == 0 ) slapi_log_error( SLAPI_LOG_PLUGIN, "SLAPI_SEARCH_TARGET", "%s\n", base ); /* Get and log the search scope */ if ( slapi_pblock_get( pb, SLAPI_SEARCH_SCOPE, &scope ) == 0 ) { switch( scope ) { case LDAP_SCOPE_BASE: slapi_log_error( SLAPI_LOG_PLUGIN, "SLAPI_SEARCH_SCOPE", "LDAP_SCOPE_BASE\n" ); break; case LDAP_SCOPE_ONELEVEL: slapi_log_error( SLAPI_LOG_PLUGIN, "SLAPI_SEARCH_SCOPE", "LDAP_SCOPE_ONELEVEL\n" ); break; case LDAP_SCOPE_SUBTREE: slapi_log_error( SLAPI_LOG_PLUGIN, "SLAPI_SEARCH_SCOPE", "LDAP_SCOPE_SUBTREE\n" ); break; default: slapi_log_error( SLAPI_LOG_PLUGIN, "SLAPI_SEARCH_SCOPE", "unknown value specified: %d\n", scope ); break; } } /* Get and log the alias dereferencing setting */ if ( slapi_pblock_get( pb, SLAPI_SEARCH_DEREF, &deref ) == 0 ) { switch( deref ) { case LDAP_DEREF_NEVER: slapi_log_error( SLAPI_LOG_PLUGIN, "SLAPI_SEARCH_DEREF", "LDAP_DEREF_NEVER\n" ); break; case LDAP_DEREF_SEARCHING: slapi_log_error( SLAPI_LOG_PLUGIN, "SLAPI_SEARCH_DEREF", "LDAP_DEREF_SEARCHING\n" ); break; case LDAP_DEREF_FINDING: slapi_log_error( SLAPI_LOG_PLUGIN, "SLAPI_SEARCH_DEREF", "LDAP_DEREF_FINDING\n" ); break; case LDAP_DEREF_ALWAYS: slapi_log_error( SLAPI_LOG_PLUGIN, "SLAPI_SEARCH_DEREF", "LDAP_DEREF_ALWAYS\n" ); break; default: slapi_log_error( SLAPI_LOG_PLUGIN, "SLAPI_SEARCH_DEREF", "unknown value specified: %d\n", deref ); break; } } /* Get and log the search filter information */ if ( slapi_pblock_get( pb, SLAPI_SEARCH_FILTER, &filter ) == 0 ) { /* Get and log the filter type */ filter_type = slapi_filter_get_choice( filter ); switch( filter_type ) { case LDAP_FILTER_AND: case LDAP_FILTER_OR: case LDAP_FILTER_NOT: slapi_log_error( SLAPI_LOG_PLUGIN, "SLAPI_SEARCH_FILTER", "Complex search filter. See value of SLAPI_SEARCH_STRFILTER.\n" ); break; case LDAP_FILTER_EQUALITY: slapi_log_error( SLAPI_LOG_PLUGIN, "SLAPI_SEARCH_FILTER", "LDAP_FILTER_EQUALITY\n" ); break; case LDAP_FILTER_GE: slapi_log_error( SLAPI_LOG_PLUGIN, "SLAPI_SEARCH_FILTER", "LDAP_FILTER_GE\n" ); break; case LDAP_FILTER_LE: slapi_log_error( SLAPI_LOG_PLUGIN, "SLAPI_SEARCH_FILTER", "LDAP_FILTER_LE\n" ); break; case LDAP_FILTER_APPROX: slapi_log_error( SLAPI_LOG_PLUGIN, "SLAPI_SEARCH_FILTER", "LDAP_FILTER_APPROX\n" ); break; case LDAP_FILTER_SUBSTRINGS: slapi_log_error( SLAPI_LOG_PLUGIN, "SLAPI_SEARCH_FILTER", "LDAP_FILTER_SUBSTRINGS\n" ); /* For substring filters, get and log the attribute type and the substrings in the filter */ slapi_filter_get_subfilt( filter, &attr_type, &substr_init, &substr_any, &substr_final ); if ( attr_type != NULL ) slapi_log_error( SLAPI_LOG_PLUGIN, "\tAttribute type", "%s\n", attr_type ); if ( substr_init != NULL ) slapi_log_error( SLAPI_LOG_PLUGIN, "\tInitial substring", "%s\n", substr_init ); if ( substr_any != NULL ) { for ( i = 0; substr_any[i] != NULL; i++ ) { slapi_log_error( SLAPI_LOG_PLUGIN, "\tSubstring", "# %d: %s\n", i, substr_any[i] ); } } if ( substr_final != NULL ) slapi_log_error( SLAPI_LOG_PLUGIN, "\tFinal substring", "%s\n", substr_final ); break; case LDAP_FILTER_PRESENT: slapi_log_error( SLAPI_LOG_PLUGIN, "SLAPI_SEARCH_FILTER", "LDAP_FILTER_PRESENT\n" ); /* For presence filters, get and log the attribute type */ slapi_filter_get_type( filter, &attr_type ); if ( attr_type != NULL ) slapi_log_error( SLAPI_LOG_PLUGIN, "\tSearch for presence of attr", "%s\n", attr_type ); break; case LDAP_FILTER_EXTENDED: slapi_log_error( SLAPI_LOG_PLUGIN, "SLAPI_SEARCH_FILTER", "LDAP_FILTER_EXTENDED\n" ); break; default: slapi_log_error( SLAPI_LOG_PLUGIN, "SLAPI_SEARCH_FILTER", "Unknown filter type: slapi_filter_get_choice returned %d\n", filter_type ); break; } } /* For comparison filters, get and log the attribute type */ if ( filter_type == LDAP_FILTER_EQUALITY || LDAP_FILTER_GE || LDAP_FILTER_LE || LDAP_FILTER_APPROX ) { slapi_filter_get_ava( filter, &attr_type, &bval ); if ( ( attr_type != NULL ) && ( bval->bv_val != NULL ) ) { slapi_log_error( SLAPI_LOG_PLUGIN, "\tAttribute type", "%s\n", attr_type ); slapi_log_error( SLAPI_LOG_PLUGIN, "\tAttribute value", "%s\n", bval->bv_val ); } } /* Get and log the string representation of the filter */ if ( slapi_pblock_get(pb, SLAPI_SEARCH_STRFILTER, &filter_str) == 0 ) slapi_log_error( SLAPI_LOG_PLUGIN, "SLAPI_SEARCH_STRFILTER", "%s\n", filter_str ); slapi_log_error( SLAPI_LOG_PLUGIN, "test_preop_search", "*** DONE ***\n\n" ); return( 0 ); } Compling the Plug-In Example
#include <stdio.h>
#include <string.h>
#include "slapi-plugin.h"
/* function prototypes */
int test_preop_init( Slapi_PBlock *pb );
int test_preop_search( Slapi_PBlock *pb );
/* Description of the plug-in */
Slapi_PluginDesc srchpdesc = { "test-search", "Airius.com", "0.5",
"sample pre-operation search plugin" };
/* Initialization function
This function registers your plug-in function as a
pre-operation search function in the Directory Server.
You need to specify this initialization function in the
server configuration file so that the server calls
this initialization function on startup. */
#ifdef _WIN32
__declspec(dllexport)
#endif
int
test_preop_init( Slapi_PBlock *pb )
{
/* Specify the version of the plug-in ("01" in this release ) */
if ( slapi_pblock_set( pb, SLAPI_PLUGIN_VERSION,
SLAPI_PLUGIN_VERSION_01 ) != 0 ||
/* Specify the description of the plug-in */
slapi_pblock_set( pb, SLAPI_PLUGIN_DESCRIPTION,
(void *)&srchpdesc ) != 0 ||
/* Set test_preop_search() as the function to call before
executing LDAP search operations. */
slapi_pblock_set( pb, SLAPI_PLUGIN_PRE_SEARCH_FN,
(void *) test_preop_search ) !=0 ) {
/* Log an error message and return -1 if a problem occurred */
slapi_log_error( SLAPI_LOG_PLUGIN, "test_preop_init",
"Error registering the plug-in.\n" );
return( -1 );
}
/* If successful, log a message and return 0 */
"Plug-in successfully registered.\n" );
return( 0 );
/* Pre-operation plug-in function for LDAP search operations
This function is called by the server before processing an LDAP
search operation. The function gets data about the search request
from the parameter block and prints the data to the error log. */
test_preop_search( Slapi_PBlock *pb )
char *base, *filter_str, *attr_type, *substr_init, *substr_final;
char **substr_any;
int scope, deref, filter_type, i;
Slapi_Filter *filter;
struct berval *bval;
/* Log a message to indicate when the plug-in function starts */
slapi_log_error( SLAPI_LOG_PLUGIN, "test_preop_search",
"*** PREOPERATION SEARCH PLUGIN ***\n");
/* Get and log the base DN of the search criteria */
if ( slapi_pblock_get( pb, SLAPI_SEARCH_TARGET, &base ) == 0 )
slapi_log_error( SLAPI_LOG_PLUGIN, "SLAPI_SEARCH_TARGET",
"%s\n", base );
/* Get and log the search scope */
if ( slapi_pblock_get( pb, SLAPI_SEARCH_SCOPE, &scope ) == 0 ) {
switch( scope ) {
case LDAP_SCOPE_BASE:
slapi_log_error( SLAPI_LOG_PLUGIN, "SLAPI_SEARCH_SCOPE",
"LDAP_SCOPE_BASE\n" );
break;
case LDAP_SCOPE_ONELEVEL:
"LDAP_SCOPE_ONELEVEL\n" );
case LDAP_SCOPE_SUBTREE:
"LDAP_SCOPE_SUBTREE\n" );
default:
"unknown value specified: %d\n", scope );
/* Get and log the alias dereferencing setting */
if ( slapi_pblock_get( pb, SLAPI_SEARCH_DEREF, &deref ) == 0 ) {
switch( deref ) {
case LDAP_DEREF_NEVER:
slapi_log_error( SLAPI_LOG_PLUGIN, "SLAPI_SEARCH_DEREF",
"LDAP_DEREF_NEVER\n" );
case LDAP_DEREF_SEARCHING:
"LDAP_DEREF_SEARCHING\n" );
case LDAP_DEREF_FINDING:
"LDAP_DEREF_FINDING\n" );
case LDAP_DEREF_ALWAYS:
"LDAP_DEREF_ALWAYS\n" );
"unknown value specified: %d\n", deref );
/* Get and log the search filter information */
if ( slapi_pblock_get( pb, SLAPI_SEARCH_FILTER, &filter ) == 0 ) {
/* Get and log the filter type */
filter_type = slapi_filter_get_choice( filter );
switch( filter_type ) {
case LDAP_FILTER_AND:
case LDAP_FILTER_OR:
case LDAP_FILTER_NOT:
slapi_log_error( SLAPI_LOG_PLUGIN, "SLAPI_SEARCH_FILTER",
"Complex search filter. See value of SLAPI_SEARCH_STRFILTER.\n" );
case LDAP_FILTER_EQUALITY:
"LDAP_FILTER_EQUALITY\n" );
case LDAP_FILTER_GE:
"LDAP_FILTER_GE\n" );
case LDAP_FILTER_LE:
"LDAP_FILTER_LE\n" );
case LDAP_FILTER_APPROX:
"LDAP_FILTER_APPROX\n" );
case LDAP_FILTER_SUBSTRINGS:
"LDAP_FILTER_SUBSTRINGS\n" );
/* For substring filters, get and log the attribute type and
the substrings in the filter */
slapi_filter_get_subfilt( filter, &attr_type, &substr_init,
&substr_any, &substr_final );
if ( attr_type != NULL )
slapi_log_error( SLAPI_LOG_PLUGIN, "\tAttribute type",
"%s\n", attr_type );
if ( substr_init != NULL )
slapi_log_error( SLAPI_LOG_PLUGIN, "\tInitial substring",
"%s\n", substr_init );
if ( substr_any != NULL ) {
for ( i = 0; substr_any[i] != NULL; i++ ) {
slapi_log_error( SLAPI_LOG_PLUGIN, "\tSubstring",
"# %d: %s\n", i, substr_any[i] );
if ( substr_final != NULL )
slapi_log_error( SLAPI_LOG_PLUGIN, "\tFinal substring",
"%s\n", substr_final );
case LDAP_FILTER_PRESENT:
"LDAP_FILTER_PRESENT\n" );
/* For presence filters, get and log the attribute type */
slapi_filter_get_type( filter, &attr_type );
slapi_log_error( SLAPI_LOG_PLUGIN, "\tSearch for presence of attr",
case LDAP_FILTER_EXTENDED:
"LDAP_FILTER_EXTENDED\n" );
"Unknown filter type: slapi_filter_get_choice returned %d\n",
filter_type );
/* For comparison filters, get and log the attribute type */
if ( filter_type == LDAP_FILTER_EQUALITY || LDAP_FILTER_GE || LDAP_FILTER_LE ||
LDAP_FILTER_APPROX ) {
slapi_filter_get_ava( filter, &attr_type, &bval );
if ( ( attr_type != NULL ) && ( bval->bv_val != NULL ) ) {
slapi_log_error( SLAPI_LOG_PLUGIN, "\tAttribute value",
"%s\n", bval->bv_val );
/* Get and log the string representation of the filter */
if ( slapi_pblock_get(pb, SLAPI_SEARCH_STRFILTER, &filter_str) == 0 )
slapi_log_error( SLAPI_LOG_PLUGIN, "SLAPI_SEARCH_STRFILTER",
"%s\n", filter_str );
"*** DONE ***\n\n" );
On Solaris, you can use the following makefile to compile the example. (This sample makefile assumes that the source code is stored in srchxmpl.c and that you are compiling a plug-in named srchxmpl.so.)
# SOLARIS Makefile for Directory Server plug-in examples # CC = cc LD = ld INCLUDE_FLAGS = -I../include CFLAGS = $(INCLUDE_FLAGS) -D_REENTRANT -KPIC LDFLAGS = -G OBJS = srchxmpl.o all: srchxmpl.so srchxmpl.so: $(OBJS) $(LD) $(LDFLAGS) -o $@ $(OBJS) .c.o: $(CC) $(CFLAGS) -c $< clean: -rm -f $(OBJS) srchxmpl.so On Windows NT, make sure to link to the libslapd.lib import library (located under the <server_root>\plugins\slapd\slapi\lib directory).
# SOLARIS Makefile for Directory Server plug-in examples
#
CC = cc
LD = ld
INCLUDE_FLAGS = -I../include
CFLAGS = $(INCLUDE_FLAGS) -D_REENTRANT -KPIC
LDFLAGS = -G
OBJS = srchxmpl.o
all: srchxmpl.so
srchxmpl.so: $(OBJS)
$(LD) $(LDFLAGS) -o $@ $(OBJS)
.c.o:
$(CC) $(CFLAGS) -c $<
clean:
-rm -f $(OBJS) srchxmpl.so
Registering the Plug-In Example
To register this example plug-in, you should do the following:
Edit the server configuration file (slapd.conf in Netscape Directory Server 3.x, slapd.ldbm.conf in Netscape Directory Server 4.0) in a text editor, and add a plugin directive after the database directive: plugin preoperation <path_to_library> test_preop_init (Each pre-operation plug-in is associated with a back-end. The directive that registers the plug-in must fall within the database-specific section for that database in the appropriate server configuration file.)
plugin preoperation <path_to_library> test_preop_init
(Each pre-operation plug-in is associated with a back-end. The directive that registers the plug-in must fall within the database-specific section for that database in the appropriate server configuration file.)
If you are using the Netscape Directory Server 3.x, in the Administration Server, click the Apply button in the top frame to save and apply your changes.
Verify that the Plugins log level is selected. (The sample source code logs messages to the error log with the Plugins severity level.)
Restart the Directory Server and check the error log. Perform a few searches against the directory. The pre-operation search plug-in function should write data about the search to the error log.