|Plug-in Programmerís Guide
Red Hat Directory Server
After you compile your server plug-in, you need to configure the Red Hat Directory Server (Directory Server) so that it properly loads your plug-in. The following sections in this chapter show how this is done:
- Creating a Plug-in Configuration File (page 47)
- Loading the Plug-in Configuration File (page 52)
- Passing Extra Arguments to Plug-ins (page 52)
- Setting the Log Level of the Server (page 54)
Creating a Plug-in Configuration File
To add your plug-in to the Directory Server configuration, you need to create an LDIF representation of your plug-in entry, add the plug-in entry to the Directory Server configuration, and reload the server configuration. This section illustrates how to create your plug-in entry. The section "Loading the Plug-in Configuration File," on page 52, explains how to add the plug-in entry to the Directory Server configuration and reload the server configuration.
The plug-in configuration file must be an LDIF file written in ASCII format. Code Example 3-1 shows the contents of an example plug-in configuration file. Line numbers have been added for ease of reference; do not number the lines in your own LDIF file.
This example plug-in configuration file defines an example plug-in as follows:
- dn: cn=Example Plug-in,cn=plugins,cn=config
- Here, the common name of the plug-in is set to Example Plug-in. The rest of the DN entry (cn=plugins,cn=config) places the entry in the database tree that contains the configuration settings for plug-ins.
- Lines 2-4 declare the object classes of the plug-in.
- Line 5 sets the common name of the plug-in to Example Plug-in.
- Line 6 defines the absolute path to the library that implements the plug-in:
- nsslapd-pluginpath: /servers/lib/test-plugin.so
- Line 7 identifies the initialization function that the server calls to register the plug-in. In this example, the initialization is set to searchdn_preop_init. For information on implementing initialization functions, see "Writing Plug-in Initialization Functions," on page 42.
- Line 8 sets the type of plug-in. In this case, it is a pre-operation plug-in. For a complete list of the types of plug-in you can declare, refer to the "Summary of Plug-in Directives," on page 51.
- Line 9 specifies whether the plug-in is active by default. The nsslapd-pluginenabled attribute can have a value of either on or off. The following line specifies that the plug-in is active by default:
- nsslapd-pluginenabled: on
- You can also use the Directory Server Console to activate or deactivate the plug-in once the plug-in is loaded.
- Line 10 uses the nsslapd-pluginid attribute to set the name of the plug-in. The name that you specify here will show up in the Directory Server Console. In this example, the plug-in identification is set to Example Pre-operation Plug-in.
- Line 11 sets the version number of the plug-in. This version number will also show up in the Directory Server Console and is used to track the version of the distributed plug-in; it does not indicate the Directory Server compatibility, as is defined by the plug-in version number described in "Specifying Directory Server Compatibility," on page 42.
- Line 12 identifies the vendor/author of the plug-in. In the following line, the vendor is set to Example Corporation:
- nsslapd-pluginvendor: Example Corporation
- Finally, Line 13 sets the description of the plug-in. The description you set will be the plug-in description that is visible through the Directory Server Console.
You can specify that your plug-in is dependent on one or more different plug-ins. If you do specify any plug-in dependencies, those plug-ins that you specify must properly start before your associated plug-in will start.
There are two attributes that you can use in the plug-in configuration file to specify the dependencies of your plug-in:
Each of these attributes can take multiple values, meaning that your plug-in depends on one or more other plug-ins.
Specific Plug-in Dependencies
If you specify the nsslapd-plugin-depends-on-name attribute in your plug-in configuration file, set its value to the names of one or more plug-ins. For example, in your plug-in configuration file, you could specify the following:
In this example, the plug-in depends on two specifically named plug-ins: my_pluginA and vendor_plugin. This configuration line indicates that before your plug-in can be loaded, the two specifically named plug-ins must be loaded. If either of these two plug-ins fail to load, the Directory Server will exit with a -1 error code.
Plug-in Type Dependencies
If you specify the nsslapd-plugin-depends-on-type attribute in your plug-in configuration file, set its value to one or more plug-in types. For example, in your plug-in configuration file, you could specify the following:
This configuration line indicates that your plug-in depends on any plug-in of the type syntax. If there is a configured plug-in of type syntax, it must be successfully loaded before your plug-in can be loaded; otherwise, the Directory Server will exit with a -1 error code.
If you specify a plug-in type dependency, the Directory Server will search for any and all plug-ins of the type(s) specified. If none are found, processing will continue without errors. However, the Directory Server must load all plug-ins of the type(s) specified before it can load your plug-in. For a complete list of the supported plug-in types, refer to the "Summary of Plug-in Directives," on page 51.
Specifying the Order of Plug-in Directives
You cannot in general rely on plug-ins being called in a certain order. For example, you cannot rely on a particular pre-operation plug-in to be called before another. You should ensure that your plug-in is written in such a way as to make it independent of the order in which it will be called.
If you must use ordering, you can make use of alphabetical order. The server loads the plug-ins in alphabetical order-that is, the loading order is determined by standard ASCII ordering of the cn value of the plug-in entry, which appears under cn=plugins,cn=config in the dse.ldif file. Because this feature may be deprecated in a future version of the product, it is recommended that you write your plug-in not to rely on any specific loading order.
Summary of Plug-in Directives
The following table summarizes the different types of plug-ins that you can specify in the plug-in configuration file.
Directive Description Declares an entry fetch plug-in, which is called by the server after retrieving an entry from the default backend database.Example of use: If you encrypt data with an entry store plug-in function before saving the data to the database, you can define an entry fetch function that decrypts data after reading it from the database. Declares an entry store plug-in, which is called by the server before saving an entry to the default backend database. (If you are writing your own database plug-in, you do not need to use this plug-in.)Example of use: You can define an entry store function to encrypt data before saving the data to the database. Declares an extended operation plug-in, which is called by the server when receiving a request for an extended operation from a client. Declares a matching rule plug-in, which is called by the server when receiving a search request with an extensible matching search filter from a client.This type of plug-in is also called by the server when indexing attributes for the backend database. Declares a post-operation/data notification plug-in, which is called by the server after performing an LDAP operation.Example of use: You can define a data notification function to send notification to the administrator if certain data have changed. Declares a pre-operation/data validation plug-in, which is called by the server before performing an LDAP operation.Example of use: You can define a data validation function to check new entries before they are added to the directory. Declares a syntax plug-in, which is called by the server when getting a list of possible candidates for a search, when determining how to compare values in searches, and when adding or deleting values from certain attribute indexes.Example of use: You can define a function that specifies how the "equals" comparison works for case-insensitive strings. Declares an object plug-in. Object plug-ins can install SLAPI_PLUGIN_START_FN, SLAPI_PLUGIN_CLOSE_FN, and SLAPI_PLUGIN_POSTSTART_FN functions. They can also use the slapi_register_plugin() call to register any kind of plug-in they like. Object plug-ins are typically used to simplify configuration of a group of related plug-ins (one entry under cn=config instead of many).Example of use: You can use this type when your plug-in doesn't fit in any of the other types listed in this table. For example, if your plug-in does more than one thing, then you should use this directive. This type of plug-in will typically register the types of operations it wants to handle using the internal API. This directive will be supported in the future.
Loading the Plug-in Configuration File
After you have written the plug-in configuration file, you must load it into the dse.ldif file, which is located in the server_root /slapd-instance_id /config directory. You can do this either by using an LDAP utility, such as ldapmodify, or by editing the file directly. If you choose to edit the file directly, be sure to shut down the Directory Server first.
The following line shows an example of an LDAP command that loads the plug-in defined in the configuration file example-plugin.ldif:
ldapmodify -h my_host -p 389 -a -D "cn= Directory Manager" \
-w adminadmin -f example-plugin.ldif
Once the plug-in configuration is loaded, you must shut down the Directory Server and then restart it before you can make calls to your plug-in. There are various ways to shut down and restart the Directory Server; you can either use the Directory Server Console or use the stop-slapd and start-slapd scripts.
Passing Extra Arguments to Plug-ins
In the Directory Server 4.x version, you could specify additional arguments at the end of the plugin directive. For example:plugin preoperation /usr/lib/myplugin.so my_init_fn \ arg1 arg2
From the initialization function and the plug-in functions, you can get these arguments by getting the following parameters from the parameter block.
- SLAPI_PLUGIN_ARGC is an int that specifies the number of additional arguments in the directive.
- SLAPI_PLUGIN_ARGV is an array of char* that specifies each additional argument in the directive.
However, plug-ins in later releases of Directory Server must not start up in the init function. They must start up in the start function. The preferred method of communicating plug-in specific configuration is through custom attribute-value pairs in the plug-in entry (in the dse.ldif file). Two examples are shown below:
Example 1:dn: cn=Test ExtendedOp,cn=plugins,cn=config objectClass: top objectClass: nsSlapdPlugin objectClass: extensibleObject cn: Test ExtendedOp nsslapd-pluginPath: /opt/redhat-ds/servers/plugins/slapd/slapi/ examples/libtest-plugin.so nsslapd-pluginInitfunc: testexop_init nsslapd-pluginType: extendedop nsslapd-pluginEnabled: on nsslapd-plugin-depends-on-type: database nsslapd-pluginId: test-extendedop nsslapd-pluginarg0: 184.108.40.206
Example 2:dn: cn=Internationalization Plugin,cn=plugins,cn=config objectClass: top objectClass: nsSlapdPlugin objectClass: extensibleObject cn: Internationalization Plugin nsslapd-pluginPath: d:/redhat/servers/lib/liblcoll.sl nsslapd-pluginInitfunc: orderingRule_init nsslapd-pluginType: matchingRule nsslapd-pluginEnabled: on nsslapd-pluginarg0: d:/redhat/servers/slapd-host/config/slapd-collations.conf nsslapd-pluginId: orderingrule nsslapd-pluginVersion: 7.1 nsslapd-pluginVendor: Red Hat, Inc. nsslapd-pluginDescription: internationalized ordering rule plugin
This method allows for more descriptive configuration, which is easier to maintain. To find the plug-in entry DN, retrieve SLAPI_TARGET_DN from the pblock passed to your start function. Once the DN is known, the normal plug-in API functions for entry retrieval and manipulation can be used for configuration retrieval.
For additional information, check the code samples provided here:server_root /plugins/slapd/slapi/examples
Setting the Log Level of the Server
If your functions call the slapi_new_condvar() function to write messages to the error log, you need to make sure that the Directory Server is configured to log messages with the severity level you've specified. The available severity levels are fully documented in the Reference section on page 545.
For example, suppose you call this function in your plug-in:slapi_log_error( SLAPI_LOG_PLUGIN, "searchdn_preop_init", "Plug-in successfully registered.\n" );
You need to make sure that the Directory Server is configured to log messages with the severity level SLAPI_LOG_PLUGIN.