Plug-in Programmer’s Guide
Red Hat Directory Server                                                            

Previous
Contents
Index
Next

Chapter 4

A Quick Example


This chapter provides an example of a pre-operation Red Hat Directory Server (Directory Server) server plug-in that you can compile and run. Along with the source code to the example, the chapter provides a Solaris Makefile that you can use to build the plug-in.

You may not understand some of the functionality contained in the example program; however, all the concepts contained in the example code are explained in detail in chapters that follow.

An Example Pre-Operation Plug-in

The example shows how to create a pre-operation plug-in for the LDAP search operation. In other words, the Directory Server will process the registered plug-in functions before it processes each LDAP search operation. The example contains two primary functions:

These functions illustrate the data in the parameter block that is available to your function. You can get and manipulate the parameter block data by calling various front-end API functions.

Writing the Plug-in Example

The following example code includes the sample pre-operation search function and the sample initialization function.

Code Example 4-1 Sample Pre-Operation Search and Initialization Functions  
 
#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", "example.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 );
}

Compiling the Plug-in Example

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

Code Example 4-2 Example Solaris Makefile  
 
# 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:

  1. Create an LDIF configuration file in an ASCII text editor; see "Creating a Plug-in Configuration File," on page 47.
  2. Load the plug-in configuration file; see "Loading the Plug-in Configuration File," on page 52.
  3. Shut down the Directory Server.
  4. Restart the Directory Server.
When you restart the Directory Server, it will read the entries in the dse.ldif file, which contain the entry for you new plug-in. If all is done correctly, your plug-in will now be loaded. (You may want to check the plug-ins list in the Directory Server Console.)

Running the Plug-in Example

After compiling the plug-in and registering it with the Directory Server, you're ready to make calls that are processed by the plug-in functions.

The first step is to restart the Directory Server and check the error log to see that the plug-in is properly registered. You should see the following line in the error log:

Error log messsage here!
 

Verify that the Plugins log level is selected. (The sample source code logs messages to the error log with the Plugins severity level.)

If the plug-in is properly registered, you can then perform a few searches against the directory. The pre-operation search plug-in function should write data about each search to the error log.




Previous
Contents
Index
Next

© 2001 Sun Microsystems, Inc. Used by permission. © 2005 Red Hat, Inc. All rights reserved.
Read the Full Copyright and Third-Party Acknowledgments.

last updated May 26, 2005