Here's a quick overview of the steps you should follow to create a new backend for slapd.
1. Choose a name for your backend (we'll call it foo) and create a new directory in the slapd source area (servers/slapd/) called back-foo. This directory will contain the backend routines you are about to write. You should also create a Make-template file in this directory. See the other Make-template files in the various back-*/ directories for examples.
2. Write backend routines for each function you want your backend to provide. See the next section for details on how to do this and the API your routines should export. You should prefix your backend routines with "foo_" to ensure uniqueness. Your backend will undoubtedly want to call some of the utility routines described in section A.2.
3. Edit the file servers/slapd/backend.c to add declarations for the backend routines you wrote in step 2, and to initialize a backend structure. Take a look at the existing definitions in that file for other backends.
Backend *be /* info about this backend */The other parameters depend on the call itself.
Connection *conn /* info about this connection */
Operation *op /* info about this operation */
foo_bind(The first three parameters are as defined above. The remaining parameters are
Backend *be,
Connection *conn,
Operation *op,
char *dn,
int method,
struct berval *cred
)
- dn
- The distinguished name to bind as.
- method
- The authentication method to use. It should be one of the ldap.h constants
LDAP_AUTH_SIMPLE
LDAP_AUTH_KRBV41
LDAP_ATH_KRBV42
The bind routine should return a value of 0 if the bind is successful, nonzero otherwise. This is important, as a return of 0 will cause the front end to consider the connection authenticated, and it will base subsequent access control decisions assuming the DN supplied is authentic.
- cred
- The credentials for the bind (either a password or Kerberos credentials).
Things to note:
* If the length of the credentials supplied for simple authentication is zero, a NULL bind is being requested. This should succeed.
* If a client sends a NULL dn, a NULL bind is also requested. This situation is handled by the front end, so you will never see it.
foo_unbind(The only three parameters are the common parameters defined above. The connection will be dropped by the front end. The unbind backend routine is provided so the backend can do any clean-up of local information it has pertaining to the connection.
Backend *be,
Connection *conn,
Operation *op
)
foo_compare(The first three parameters are the common ones described above. The other parameters are
Backend *be,
Connection *conn,
Operation *op,
char *dn,
Ava *ava
)
The AVA structure is defined as follows.
- dn
- The distinguished name of the entry on which to perform the compare.
- ava
- The attribute value assertion to test against the entry.
typedef struct ava {The type to compare is given in the ava_type field, and the value to compare is given in the ava_value field.
char *ava_type;
struct berval ava_value;
} Ava;
foo_search(The first three parameters are the common ones described above. The rest of the parameters are
Backend *be,
Connection *conn,
Operation *op,
char *base,
int scope,
int sizelimit,
int timelimit,
Filter *filter,
char *filterstr,
char **attrs,
int attrsonly
)
- base
- The DN of the base object at which to start the search.
- scope
- The scope of the search. One of the ldap.h constants
LDAP_SCOPE_BASEOBJECT
LDAP_SCOPE_ONELEVELLDAP_SCOPE_SUBTREE
The Filter structure is used to represent an LDAP search filter. The search filter is described in ASN.1 as the following.
- sizelimit
- A client-supplied limit on the number of entries to return. A value of zero implies no limit.
- timelimit
- A client-supplied limit on the number of seconds to spend on the search. A value of zero implies no limit.
- filter
- A data structure representing the search filter. A backend would normally use either this parameter or the filterstr parameter, not both. See below for a description of this structure.
- filterstr
- A string representation of the search filter. A backend would normally use either this parameter or the filter parameter, not both. The format of this string is as defined in RFC 1588.
- attrs
- An array of char *'s indicating the attributes to return from the search. A NULL value for attrs implies all attributes.
- attrsonly
- A Boolean parameter indicating whether only attribute types should be returned (non-zero) or if attribute types and values should be returned (zero).
Filter ::= CHOICE {The C language Filter structure definition used to represent this via the filter parameter is defined as follows in the slap.h header file.
and [0] SET OF Filter,
or [1] SET OF Filter,
not [2] Filter,
equalityMatch [3] AttributeValueAssertion,
substrings [4] SubstringFilter,
greaterOrEqual [5] AttributeValueAssertion,
lessOrEqual [6] AttributeValueAssertion,
present [7] AttributeType,
approxMatch [8] AttributeValueAssertion
}
typedef struct filter {The f_choice field will have one of the following values, defined in the ldap.h header file.
unsigned long f_choice; /* from ldap.h */
union {
char *f_un_type /* present */
Ava f_un_ava; /* eq,approx,le,ge */
struct filter *f_un_complex;/* and,or,not */
struct sub { /* substrings */
char *f_un_sub_type;
char *f_un_sub_initial;
char **f_un_sub_any;
char *f_un_sub_final;
} f_un_sub;
} f_un;
#define f_type f_un.f_un_type
#define f_ava f_un.f_un_ava
#define f_avtype f_un.f_un_ava.ava_type
#define f_avvalue f_un.f_un_ava.ava_value
#define f_and f_un.f_un_complex
#define f_or f_un.f_un_complex
#define f_not f_un.f_un_complex
#define f_list f_un.f_un_complex
#define f_sub f_un.f_un_sub
#define f_sub_type f_un.f_un_sub.f_un_sub_type
#define f_sub_initial f_un.f_un_sub.f_un_sub_initial
#define f_sub_any f_un.f_un_sub.f_un_sub_any
#define f_sub_final f_un.f_un_sub.f_un_sub_final
struct filter *f_next; /* in and/or chain */
} Filter;
LDAP_FILTER_AND
LDAP_FILTER_OR
LDAP_FILTR_NOT
LDAP_FILTER_EQUALITY
LDAP_FILTER_SUBSTRINGS
LDAP_FILTER_GE
LDAP_FILTER_LE
LDAP_FILTER_PRESENT
LDAP_FILTER_APPROX
foo_modify(The first three parameters are the common ones described above. The other parameters are
Backend *be,
Connection *conn,
Operation *op,
char *dn,
LDAPMod *mods
)
The LDAPMod structure is defined as follows in the ldap.h header file.
- dn
- The distinguished name of the entry to modify.
- mods
- The list of modifications to make to the entry.
typedef struct ldapmod {The mod_op field identifies the type of modification and will have one of the following values, defined in the ldap.h header file.
int mod_op;
char *mod_type;
union {
char **modv_strvals;
struct berval **modv_bvals;
} mod_vals;
#define mod_values mod_vals.modv_strvals
#define mod_bvalues mod_vals.modv_bvals
struct ldapmod *mod_next;
} LDAPMod;
LDAP_MOD_ADDNote that the mod_bvalues form of representing values is always used, but that the mod_op field is not ORed with LDAP_MOD_BVALUES, as LDAP clients must do to use the mod_bvalues field.
LDAP_MOD_DELETE
LDAP_MOD_RELACE
foo_modifyrdn(The first three parameters are the common ones described above. The other parameters are
Backend *be,
Connection *conn,
Operation *op,
char *dn,
char *newrdn,
int deleteoldrdn
)
- dn
- The distinguished name of the entry whose name is to be changed.
- newrdn
- The new RDN to give the entry.
- deleteoldrdn
- A Boolean flag indicating whether the old RDN is to be deleted from the entry (non-zero) or kept as a non-distinguished attribute value in the entry (zero).
foo_add(The first three parameters are the common ones described above. The additional parameter is
Backend *be,
Connection *conn,
Operation *op,
Entry *e
)
The Entry structure is defined in the slap.h header file as follows.
- e
- A pointer to an Entry structure specifying the entry to add.
typedef struct entry {The e_dn field contains the DN of the entry.
char *e_dn;
Attribute *e_attrs;
/* other things you should not mess with */
} Entry;
The e_attrs field is a linked list of the entry's attributes. Each element of this list has the following definition, as given in slap.h.
typedef struct attr {The a_syntax field identifies the syntax of the attribute and will have one of the following values, defined in slap.h.
char *a_type;
struct berval **a_vals;
int a_syntax;
struct attr *a_next;
} Attribute;
SYNTAX_CIS /* case insensitive string */The syntax values may be additive in some cases. For example, an attribute of type telephoneNumber will have syntax (SYNTAX_CIS | SYNTAX_TEL).
SYNTAX_CES /* case sensitive string */
SYNTAX_BIN /* binary data */
SYNTAX_TEL /* telephone number string */
SYNTAX_DN /* dn string */
foo_delete(The first three parameters are the common ones described above. The additional parameter is
Backend *be,
Connection *conn,
Operation *op,
char *dn
)
- dn
- The distinguished name of the entry to delete.
foo_abandon(The first three parameters are the common ones defined above. The additional parameters is
Backend *be,
Connection *conn,
Operation *op,
int id
)
In addition, the front end will set the o_abandoned flag in the operation's Operation structure. Backends may check this flag periodically to see if the operation has been abandoned.
- id
- the message identifier of the request to be abandoned.
foo_init(The sole parameter is
Backend *be
)
The be parameter is used to hold backend-specific information. It is as defined in the beginning of this section in the slap.h header file. If your backend needs to keep any information specific to a backend instance, it should put it in the be_private field of the be parameter.
- be
- The backend-specific data structure.
foo_config(The parameters are
Backend *be,
int lineno,
int argc,
char **argv
)
- be
- The backend-specific data structure defined above.
- lineno
- The current line number in the configuration file. This is useful if an error message has to be printed.
- argc
- The number of arguments from the configuration file line.
- argv
- The list of arguments from the configuration file line.
foo_close(The sole parameter is
Backend *be
)
- be
- The backend-specific data described above.
send_search_entry(The first three parameters are the common ones passed to the backend routines. The entry to send back is given in e. An array of attribute types to include from the entry (subject to access control) is given in attrs. The attrsonly parameter determines whether attributes only or attributes and values should be sent back.
Backend *be,
Connection *conn,
Operation *op,
Entry *e,
char **attrs,
int attrsonly
)
send_ldap_result(The first two parameters are two of the three common parameters passed to the backend. The err parameter is the LDAP error code to pass back. It should be one of the codes defined ldap.h. The matched parameter should only be non-NULL if err is set to LDAP_NO_SUCH_OBJECT. In this case, matched gives the DN prefix of the request that was resolved successfully. The final parameter, text, is an arbitrary string sent back to the client. It is meant to contain a helpful error message.
Connection *conn,
Operation *op,
int err,
char *matched,
char *text
)
test_filter(The first three parameters are the common ones. The e parameter is the entry to match against the filter, given in the filter parameter. test_filter() returns zero if the entry matches the filter, non-zero otherwise.
Backend *be,
Connection *conn,
Operation *op,
Entry *e,
Filter *filter
)
str2entry(where s is the string containing the LDIF entry; and
char *s
)
char *where len will contain the length of the string returned, and printid indicates whether the entry ID should be printed in the LDIF format. The string returned should be considered a pointer to static storage that is overwritten on each call.
entry2str(
Entry *e,
int *len,
int printid
)
Send comments about this page to: ldap-support@umich.edu