Complete Contents
Getting Started
Chapter 1 Understanding Server Plug-Ins
Chapter 2 Writing and Compiling Plug-Ins
Chapter 3 Calling the Front-End API Functions
Chapter 4 Quick Start
Chapter 5 Writing Database Plug-Ins
Chapter 6 Writing Pre/Post-Operation Plug-Ins
Chapter 7 Defining Functions for LDAP Operations
Chapter 8 Defining Functions for Database Operations
Chapter 9 Defining Functions for Authentication
Chapter 10 Writing Entry Store/Fetch Plug-Ins
Chapter 11 Writing Extended Operation Plug-Ins
Chapter 12 Writing Matching Rule Plug-Ins
Chapter 13 Data Type and Structure Reference
Chapter 14 Function Reference
Chapter 15 Parameter Reference
Glossary
Previous Next Contents Bookshelf


Chapter 12 Writing Matching Rule Plug-Ins

This chapter explains how to write plug-in functions that handle matching rules.

Matching rule plug-in functions are described in the following sections:


Understanding Matching Rules
A matching rule specifies how one or more attributes of a particular syntax should be compared against assertion values. For example, a matching rule that specifies a "sound-alike" comparison attempts to match values that sound like the specified value. Each matching rule is identified by a unique OID (for example, "1.2.3.4").

LDAP v3 clients can specify a matching rule as part of a search filter in a search request. This type of search filter is called an extensible match filter.

Extensible Match Filters

In an "extensible match" filter, the client specifies that it wants to use the matching rule to compare a specified value against the values of entries in the directory. (For example, an extensible match filter might find all entries in which the sn attribute "sounds like" melon.)

An "extensible match" filter contains the following information:

For example, if the OID "1.2.3.4" identifies a matching rule that performs "sounds like" matches, the following extensible match filter attempts to find entries where the mail attribute "sounds like" moxie.

(mail:1.2.3.4:=moxie)

In the search filter, the client can specify the OID (that idnetifies a matching rule) and the attribute type. This indicates that the value in the filter should be compared against the attribute using the matching rule.

For example, if the OID 1.2.3.4 specifies a "sound-alike" match and if the string representation of the search filter is:

(uid:1.2.3.4:=moxie)

the client wants to find entries in which the value of the uid attribute sounds like moxie.

Note that although the LDAP v3 standard allows clients to omit the OID or the attribute type, at this time, the Netscape Directory Server only supports extensible match filters that specify both the OID and attribute type.

The filter can also specify a preference indicating whether or not to also search the attributes in the DN. For example, if the OID 1.2.3.4 specifies a "sound-alike" match and if the string representation of the search filter is:

(sn:dn:1.2.3.4:=moxie)

the client wants to find all entries in which the value of the sn attribute or the attributes in the DN (for example, uid, cn, ou, or o) sound like moxie.

Extensible Match Filters in the Directory Server

The Netscape Directory Server 3.0 and more recent versions already include support for certain matching rules (which are used to determine the collation order and operator for searches of international data).

You can enable the Netscape Directory Server to handle your own matching rules for extensible match searches by defining your own matching rules plug-ins and registering them with the server.

You can also build indexes to improve the performance of search operations that use extended match filters.


Understanding Matching Rule Plug-Ins
A matching rule plug-in can create filters that the server can use when handling extensible search filters. A matching rule plug-in can also create indexers to index entries for extensible searches.

Functions Defined in Matching Rule Plug-Ins

The matching rule plug-in consists of the following:

When the server starts up and loads the matching rule plug-in, it calls the initialization function. In this function, you pass the server the pointers to the factory functions and the close function. The server calls these functions when needed (see "How Matching Rules Are Identified" on page  162 and "How the Server Associates Plug-Ins with OIDs" on page  163 for details).

How Matching Rules Are Identified

Matching rules are identified by OID. When the server encounters an OID in the following situations, it attempts to find the matching rule plug-in that handles the matching rule with that OID.

The server can encounter a matching rule OID in the following situations:

In all of these situations, the server uses the matching rule OID to find the plug-in responsible for handling the rule (see "How the Server Associates Plug-Ins with OIDs" on page  163 for details).

How the Server Associates Plug-Ins with OIDs

When the server encounters the OID for a matching rule, it attempts to find the plug-in associated with that matching rule.

If no plug-in is associated with the matching rule, the server calls each matching rule plug-in to find one that handles the specified matching rule.

When the server finds a plug-in that handles the matching rule, the server creates an association between the plug-in and the matching rule OID for future reference.

If no matching rule plug-in supports the specified OID, the server returns an LDAP_UNAVAILABLE_CRITICAL_EXTENSION error back to the client.

Finding a Plug-In for Indexing

To determine which matching rule plug-in is responsible for indexing an attribute with a given matching rule (based on its OID), the server does the following for each plug-in:

  1. In a new Slapi_PBlock parameter block, the server sets the OID in the SLAPI_PLUGIN_MR_OID parameter.
  2. Next, the server calls the indexer factory function (specified in the SLAPI_PLUGIN_MR_INDEXER_CREATE_FN parameter) for the plug-in.
  3. The server checks the SLAPI_PLUGIN_MR_INDEX_FN parameter.
  4. Finally, the server frees the parameter block from memory.
At some point in time, the server may also call the indexer destructor function (specified in the SLAPI_PLUGIN_MR_DESTROY_FN parameter) to free the indexer object that was created by the indexer factory function.

Finding a Plug-In for Searching

To determine which matching rule plug-in is responsible for handling an extensible match filter for a given matching rule (based on its OID), the server does the following for each plug-in:

  1. In a new Slapi_PBlock parameter block, the server sets the following parameters:
  2. Next, the server calls the filter factory function (specified in the SLAPI_PLUGIN_MR_FILTER_CREATE_FN parameter) for the plug-in.
  3. The server checks the SLAPI_PLUGIN_MR_FILTER_MATCH_FN parameter.
  4. Finally, the server gets the following information from the plug-in for future use:
Information specified in the filter object is used by both the filter index function and the filter matching function.

How the Server Uses Parameter Blocks

The server uses parameter blocks as a means to pass information to and from your plug-in functions.

When calling your matching rule plug-in functions, the server will create a new Slapi_PBlock parameter block, set some input parameters, and pass the parameter block to your function. After retrieving output paramters from the block, the server typically frees the parameter block from memory.

In general, you should not expect a parameter block to be passed from plug-in function to plug-in function. For example, the value of a parameter set by one plug-in function may not necessarily be accessible to other plug-in functions, since each function is usually passed a new and different parameter block.


Indexing Based on Matching Rules
This section explains how to set up the server to index entries using a matching rule. The following topics are covered:

Note that you also need to define an initialization function to register your indexer factory function.

How the Server Sets Up the Index

When the server encounters a matching rule OID in an index directive in the slapd.dynamic-ldbm.conf configuration file, the server determines which plug-in supports the matching rule identified by the OID. See "How the Server Associates Plug-Ins with OIDs" on page  163 for details.

The server gets the OID returned in the SLAPI_PLUGIN_MR_OID parameter and associates this OID with the rest of the attribute indexing information (such as the attribute type and the type of index) for future reference.

When adding, modifying, or deleting the values of an attribute, the server will check this information to determine if the attribute is indexed. See "How the Server Updates the Index" on page  167 for information on how attributes are indexed.

How the Server Updates the Index

When a value is added, modified, or removed from an attribute in an entry (or when the RDN of an entry is changed), the server does the following if that attribute has an index that uses matching rules:

  1. In a new Slapi_PBlock parameter block, the server sets the following parameters:
  2. Next, the server calls the indexer factory function (specified in the SLAPI_PLUGIN_MR_INDEXER_CREATE_FN parameter) for the plug-in to create the indexer object.
  3. The server generates the index keys for the values to be added or deleted:
  4. The server inserts or deletes the keys and values in the index for that attribute.
  5. The server calls the indexer destructor function (specified in the SLAPI_PLUGIN_MR_DESTROY_FN parameter) to free the indexer object.
When the server is done, it frees any parameter blocks that were allocated during this process.

Writing the Indexer Factory Function

The indexer factory function takes a single Slapi_PBlock argument. This function should be thread-safe. The server may call this function concurrently.

The indexer factory function should do the following:

  1. Get the OID from the SLAPI_PLUGIN_MR_OID parameter and determine whether or not that OID is supported by your plug-in.
  2. Get the value of the SLAPI_PLUGIN_MR_USAGE parameter. This parameter should have one of the following values:
  3. You can use this information to set different information in the indexer object or to set a different indexer function, based on whether the function is being called to index or to sort.

  4. You can also get any data that you set in the SLAPI_PLUGIN_PRIVATE parameter during initialization. (See "Writing an Initialization Function" on page  182.)
  5. Create an indexer object containing any information that you want passed to the indexer function.
  6. Set the following parameters:
  7. Return 0 (or the result code LDAP_SUCCESS) if everything completed successfully.
Getting and Setting Parameters in Indexer Factory Functions

The following table summarizes the different parameters that the indexer factory function should get and set in the parameter block that is passed in:

Table 12.1 Input and output parameters available to a indexer factory function

Parameter Name
Data Type
Description
SLAPI_PLUGIN_MR_OID

char *

(Input parameter) Matching rule OID (if any) specified in the index directive.
SLAPI_PLUGIN_MR_TYPE

char *

(Input parameter) Attribute type (if any) specified in the index directive.
SLAPI_PLUGIN_MR_USAGE

unsigned int

(Input parameter) Specifies the intended use of the indexer object. This parameter can have one of the following values:
You can use this to specify different information in the indexer object or different indexer functions, based on whether the plug-in is used for indexing or sorting.
For information on sorting search results, see "Handing Sorting by Matching Rules" on page  181.
SLAPI_PLUGIN_PRIVATE

void *

(Input parameter) Pointer to any private data originally specified in the initialization function. (See "Writing an Initialization Function" on page  182 for details.)
SLAPI_PLUGIN_MR_OID

char *

(Output parameter) Official matching rule OID of the index.
SLAPI_PLUGIN_MR_INDEX_FN

void *

(function pointer)

(Output parameter) Name of the function called by the server to generate a list of keys used for indexing a set of values.
SLAPI_PLUGIN_DESTROY_FN

void *

(function pointer)

(Output parameter) Name of the function to be called to free the indexer object.
SLAPI_PLUGIN_OBJECT

void *

(Output parameter) Pointer to the indexer object created by your factory function.

Writing the Indexer Function

The indexer function takes a single Slapi_PBlock argument. This function will never be called for the same indexer object concurrently. (If you plan to manipulate global variables, keep in mind that the server can call this function concurrently for different indexer objects.)

The indexer function should do the following:

  1. Get the values of the following parameters:
  2. Generate index keys for these values, and set the SLAPI_PLUGIN_MR_KEYS parameter to the array of these keys.
  3. Return 0 (or the result code LDAP_SUCCESS) if everything completed successfully.
The server adds or removes the keys and the corresponding values from the appropriate indexes.

Getting and Setting Parameters in Indexer Functions

The following table summarizes the different parameters that the indexer function should get and set in the parameter block that is passed in:

Table 12.2 Input and output parameters available to an indexer function

Parameter Name
Data Type
Description
SLAPI_PLUGIN_MR_VALUES

struct berval **

(Input parameter) Pointer to an array of berval structures containing the values of the entry's attributes that need to be indexed.
SLAPI_PLUGIN_OBJECT

void *

(Input parameter) Pointer to the indexer object created by the indexer factory function. (See "Writing the Indexer Factory Function" on page  168 for details.)
SLAPI_PLUGIN_MR_KEYS

struct berval **

(Output parameter) Keys generated for the values specified in the SLAPI_PLUGIN_MR_VALUES parameter. The server creates indexes using these keys.


Handling Extensible Match Filters
This section explains how to set up the server to process searches that use extensible match filters (matching rules). The following topics are covered:

Note that you also need to define an initialization function to register your filter factory function.

How the Server Handles the Filter

When the server processes a search request that has an extensible match filter, the server does the following:

  1. First, the server finds the plug-in associated with this OID, if an association between the OID and plug-in has already been made.
  2. If no association has been made yet, the server attempts to find a matching rule plug-in that handles the OID. (See "How the Server Associates Plug-Ins with OIDs" on page  163 for details.)

  3. Next, the server attempts to generate a list of search result candidate from the indexes. In a new Slapi_PBlock parameter block, the server does the following:
  4. The server considers all entries to be potential candidates if at least one of the following is true:

  5. For each candidate entry, the server checks to see if the entry matches the search filter by doing the following:
  6. The server checks the value returned by the filter matching function:

  7. If the entry matches the filter, the server verifies that the entry is in the scope of the search before returning the entry to the LDAP client as a search result.
Query Operators in Matching Rules

As mentioned in "How the Server Handles the Filter" on page  173, the server uses a query operator when searching the index for possible candidates.

Note that this applies to the ldbm default back-end database. If you are using your own back-end or if you have not set up indexing by matching rules, the server does not make use of the query operator.

The server checks the value of the SLAPI_PLUGIN_MR_QUERY_OPERATOR parameter to determine which operator is specified. The following table lists the possible values for this parameter.

Table 12.3 Query operators in extensible match filters

Operator
Description
SLAPI_OP_LESS

<
SLAPI_OP_LESS_OR_EQUAL

<=
SLAPI_OP_EQUAL

=
SLAPI_OP_GREATER_OR_EQUAL

>=
SLAPI_OP_GREATER

>

If the query operator is SLAPI_OP_EQUAL, the server attempts to find the keys in the index that match the value specified in the search filter. In the case of the other query operators, the server attempts to find ranges of keys that match the value.

Writing a Filter Factory Function

The filter factory function takes a single Slapi_PBlock argument. This function should be thread-safe. The server may call this function concurrently. (Each incoming LDAP request is handled by a separate thread. Multiple threads may call this function if processing multiple requests that have extensible match filters.)

The filter factory function should do the following:

  1. Get the OID from the SLAPI_PLUGIN_MR_OID parameter and determine whether or not that OID is supported by your plug-in.
  2. Get and check the values of the SLAPI_PLUGIN_MR_TYPE and SLAPI_PLUGIN_MR_VALUE parameters.
  3. The values of these parameters are the attribute type and value specified in the extensible match filter.

  4. You can also get any data that you set in the SLAPI_PLUGIN_PRIVATE parameter during initialization. (See "Writing an Initialization Function" on page  182.)
  5. Create a filter object, putting the following information in the object:
  6. The server will call your filter index function at a later time to extract this information from the filter object.

  7. Set the following parameters:
  8. Return 0 (or the result code LDAP_SUCCESS) if everything completed successfully.
Getting and Setting Parameters in Filter Factory Functions

The following table summarizes the different parameters that the filter factory function should get and set in the parameter block that is passed in:

Table 12.4 Input and output parameters available to a filter factory function

Parameter Name
Data Type
Description
SLAPI_PLUGIN_MR_OID

char *

(Input parameter) Matching rule OID (if any) specified in the extensible match filter.
SLAPI_PLUGIN_MR_TYPE

char *

(Input parameter) Attribute type (if any) specified in the extensible match filter.
SLAPI_PLUGIN_MR_VALUE

struct berval *

(Input parameter) Value specified in the extensible match filter.
SLAPI_PLUGIN_PRIVATE

void *

(Input parameter) Pointer to any private data originally specified in the initialization function. (See "Writing an Initialization Function" on page  182 for details.)
SLAPI_PLUGIN_MR_FILTER_MATCH_FN

mrFilterMatchFn

(function pointer)

(Output parameter) Name of the function called by the server to match an entry's attribute values against the value in the extensible search filter.
SLAPI_PLUGIN_MR_FILTER_INDEX_FN

void *

(function pointer)

(Output parameter) Name of the function called by the server to generate a list of keys used for indexing a set of values.
SLAPI_PLUGIN_DESTROY_FN

void *

(function pointer)

(Output parameter) Name of the function to be called to free the filter object.
SLAPI_PLUGIN_OBJECT

void *

(Output parameter) Pointer to the filter object created by your factory function.

Writing a Filter Index Function

The filter index function takes a single Slapi_PBlock argument. This function will never be called for the same filter object concurrently. (If you plan to manipulate global variables, keep in mind that the server can call this function concurrently for different filter objects.)

The filter index function should do the following:

  1. Get the filter object from the SLAPI_PLUGIN_OBJECT parameter (if the parameter is set).
  2. Using data from the object, determine and set the values of the following parameters:
  3. Return 0 (or the result code LDAP_SUCCESS) if everything completed successfully.
Getting and Setting Parameters in Filter Index Functions

The following table summarizes the different parameters that the filter index function should get and set in the parameter block that is passed in:

Table 12.5 Input and output parameters available to a filter index function

Parameter Name
Data Type
Description
SLAPI_PLUGIN_OBJECT

void *

(Input and output parameter) Pointer to the filter object created by the factory function. (For details, see "Writing a Filter Factory Function" on page  175.)
SLAPI_PLUGIN_MR_QUERY_OPERATOR

int

(Output parameter) Query operator used by the server to determine how to compare the keys generated from SLAPI_PLUGIN_MR_VALUES and SLAPI_PLUGIN_MR_INDEX_FN against keys in the index.
For a list of possible values for this parameter, see "Query Operators in Matching Rules" on page  174.
SLAPI_PLUGIN_MR_OID

char *

(Output parameter) Official matching rule OID (if any) specified in the extensible match filter.
SLAPI_PLUGIN_MR_TYPE

char *

(Output parameter) Attribute type (if any) specified in the extensible match filter.
SLAPI_PLUGIN_MR_VALUES

struct berval **

(Output parameter) Pointer to an array of berval structures containing the values specified in the extensible match filter.
SLAPI_PLUGIN_MR_INDEX_FN

void *

(function pointer)

(Output parameter) Name of the function called by the server to generate a list of keys used for indexing a set of values.

Writing a Filter Matching Function

The filter matching function has the following prototype:

#include "slapi-plugin.h"
typedef int (*mrFilterMatchFn) (void* filter,
Slapi_Entry* entry, Slapi_Attr* attrs);

This function passes the following arguments:

This function will never be called for the same filter object concurrently. (If you plan to manipulate global variables, keep in mind that the server can call this function concurrently for different filter objects.)

The filter matching function should do the following:

  1. From the filter object, get the attribute type, the values, and the query operator.
  2. Find the corresponding attribute in the attributes passed into the function. Make sure to check for subtypes of an attribute (for example, "cn;lang-ja") in the filter and in the attributes specified by attrs.
  3. You can call the slapi_attr_type_cmp() function to compare the attribute in the filter against the attributes passed in as arguments.

  4. Using the query operator to determine how the values should be compared, compare the values from the filter against the values from the values in the attribute.
  5. Return one of the following values:

Handing Sorting by Matching Rules
If you have set up indexing by a matching rule, you can also sort search results by that matching rule. The server can use the keys in the index to sort the search results.

When processing a request to sort by a matching rule, the server does the following:

  1. In a new Slapi_PBlock parameter block, the server sets the following parameters:
  2. Next, the server calls the indexer factory function (specified in the SLAPI_PLUGIN_MR_INDEXER_CREATE_FN parameter) for the plug-in.
  3. The server generates the index keys for the values to be sorted:
  4. The server compares the keys to sort the results.

Writing a Destructor Function
The server calls the destructor function to free any memory that you've allocated (for example, the indexer object or the filter object).

The destructor function takes a single Slapi_PBlock argument. The following table summarizes the different parameters that the destructor function should get and set in the parameter block that is passed in:

Table 12.6 Input and output parameters available to a destructor function

Parameter Name
Data Type
Description
SLAPI_PLUGIN_OBJECT

void *

(Input parameter) Pointer to the filter object or indexer object created by your factory function.

For example, your destructor function can get the indexer object from the SLAPI_PLUGIN_OBJECT parameter and free the object from memory.

This function will never be called for the same indexer or filter object concurrently. (If you plan to manipulate global variables, keep in mind that the server can call this function concurrently for different filter or indexer objects.)


Writing an Initialization Function
Internally, the server keeps a list of matching rule plug-ins. When dealing with matching rules, the server attempts to find the matching rule plug-in to handle the given matching rule. (See "How the Server Associates Plug-Ins with OIDs" on page  163 for details.)

In order to add your plug-in to that internal list, you need to write an initialization function. The initialization function takes a single Slapi_PBlock argument. The function should set the following parameters:

You need to register the initialization function (see "Registering Matching Rule Functions" on page  184) so that the server runs the function when starting up.

The following table summarizes the different parameters that the initialization function should get and set in the parameter block that is passed in:

Table 12.7 Input and output parameters available to a matching rule plug-in initialization function

Parameter Name
Data Type
Description
SLAPI_PLUGIN_ARGC

int

(Input parameter) Number of arguments in the plugin directive (not including the library name and initialization function name).
SLAPI_PLUGIN_ARGV

char **

(Input parameter) Array of string arguments in the plugin directive (not including the library name and initialization function name).
SLAPI_PLUGIN_MR_FILTER_CREATE_FN

void *

(function pointer)

(Output parameter) The factory function used for creating filters.
SLAPI_PLUGIN_MR_INDEXER_CREATE_FN

void *

(function pointer)

(Output parameter) The factory function used for creating indexers.
SLAPI_PLUGIN_CLOSE_FN

void *

(function pointer)

(Output parameter) The "close" function, which the server calls before shutting down.
SLAPI_PLUGIN_PRIVATE

void *

(Output parameter) Pointer to any private data you want passed to your plug-in functions.


Registering Matching Rule Functions
To register your matching rule plug-in, add the following directive to the slapd.conf configuration file:

plugin matchingrule <library_name> <init_fn_name> [<arguments>...]

<init_fn_name> is the name of your initialization function and <library_name> is the name and path of the library where the function is defined. For example, the following directive registers the initialization function named my_init_fn(), which is defined in the library /usr/ns/myplugin.so:

plugin matchingrule /usr/ns/myplugin.so my_init_fn


Example of a Matching Rule Plug-In
[??? I need to put one together. ???]


Specifying Start and Close Functions
For each matching rule operation plug-in, you can specify the name of a function to be called after the server starts and before the server is shut down. These functions take a single Slapi_PBlock argument.

The following table summarizes the different parameters that the initialization function should get and set in the parameter block that is passed in:

Table 12.8 Input and output parameters available to a matching rule plug-in initialization function

Parameter Name
Data Type
Description
SLAPI_PLUGIN_START_FN

void *

(function pointer)

(Output parameter) The function called after the Directory Server starts up.
SLAPI_PLUGIN_CLOSE_FN

void *

(function pointer)

(Output parameter) The function called before the Directory Server shuts down.

If you register multiple plug-ins with different start and close functions, the functions are called in the order that the plug-ins are registered (in other words, in the order that the plugin directives appear in the slapd.conf file).

 

© Copyright 1998 Netscape Communications Corporation