1
0
mirror of https://github.com/samba-team/samba.git synced 2025-03-09 08:58:35 +03:00

ldb: allow ldb modules to specify LDB_MODULE(name) or LDB_BACKEND(name)

metze
(This used to be commit 1d5b714438a955d76f92f4ccd8aa2f7f89ffa5fd)
This commit is contained in:
Stefan Metzmacher 2008-06-28 10:49:49 +02:00
parent d7ac45f8b8
commit 5ccfd6a90e
4 changed files with 201 additions and 164 deletions

View File

@ -68,153 +68,6 @@ struct ldb_context *ldb_init(TALLOC_CTX *mem_ctx, struct event_context *ev_ctx)
return ldb;
}
static struct backends_list_entry {
struct ldb_backend_ops *ops;
struct backends_list_entry *prev, *next;
} *ldb_backends = NULL;
#ifndef STATIC_LIBLDB_BACKENDS
#ifdef HAVE_LDB_LDAP
#define LDAP_INIT &ldb_ldap_backend_ops, \
&ldb_ldapi_backend_ops, \
&ldb_ldaps_backend_ops,
#else
#define LDAP_INIT
#endif
#ifdef HAVE_LDB_SQLITE3
#define SQLITE3_INIT &ldb_sqlite3_backend_ops,
#else
#define SQLITE3_INIT
#endif
#define STATIC_LIBLDB_BACKENDS \
LDAP_INIT \
SQLITE3_INIT \
&ldb_tdb_backend_ops, \
NULL
#endif
const static struct ldb_backend_ops *builtin_backends[] = {
STATIC_LIBLDB_BACKENDS
};
static ldb_connect_fn ldb_find_backend(const char *url)
{
struct backends_list_entry *backend;
int i;
for (i = 0; builtin_backends[i]; i++) {
if (strncmp(builtin_backends[i]->name, url,
strlen(builtin_backends[i]->name)) == 0)
return builtin_backends[i]->connect_fn;
}
for (backend = ldb_backends; backend; backend = backend->next) {
if (strncmp(backend->ops->name, url,
strlen(backend->ops->name)) == 0) {
return backend->ops->connect_fn;
}
}
return NULL;
}
/*
register a new ldb backend
*/
int ldb_register_backend(const char *url_prefix, ldb_connect_fn connectfn)
{
struct ldb_backend_ops *backend;
struct backends_list_entry *entry;
backend = talloc(talloc_autofree_context(), struct ldb_backend_ops);
if (!backend) return LDB_ERR_OPERATIONS_ERROR;
entry = talloc(talloc_autofree_context(), struct backends_list_entry);
if (!entry) {
talloc_free(backend);
return LDB_ERR_OPERATIONS_ERROR;
}
if (ldb_find_backend(url_prefix)) {
return LDB_SUCCESS;
}
/* Maybe check for duplicity here later on? */
backend->name = talloc_strdup(backend, url_prefix);
backend->connect_fn = connectfn;
entry->ops = backend;
DLIST_ADD(ldb_backends, entry);
return LDB_SUCCESS;
}
/*
Return the ldb module form of a database.
The URL can either be one of the following forms
ldb://path
ldapi://path
flags is made up of LDB_FLG_*
the options are passed uninterpreted to the backend, and are
backend specific.
This allows modules to get at only the backend module, for example where a
module may wish to direct certain requests at a particular backend.
*/
int ldb_connect_backend(struct ldb_context *ldb,
const char *url,
const char *options[],
struct ldb_module **backend_module)
{
int ret;
char *backend;
ldb_connect_fn fn;
if (strchr(url, ':') != NULL) {
backend = talloc_strndup(ldb, url, strchr(url, ':')-url);
} else {
/* Default to tdb */
backend = talloc_strdup(ldb, "tdb");
}
fn = ldb_find_backend(backend);
if (fn == NULL) {
struct ldb_backend_ops *ops;
char *symbol_name = talloc_asprintf(ldb, "ldb_%s_backend_ops", backend);
if (symbol_name == NULL) {
return LDB_ERR_OPERATIONS_ERROR;
}
ops = ldb_dso_load_symbol(ldb, backend, symbol_name);
if (ops != NULL) {
fn = ops->connect_fn;
}
talloc_free(symbol_name);
}
talloc_free(backend);
if (fn == NULL) {
ldb_debug(ldb, LDB_DEBUG_FATAL,
"Unable to find backend for '%s'\n", url);
return LDB_ERR_OTHER;
}
ret = fn(ldb, url, ldb->flags, options, backend_module);
if (ret != LDB_SUCCESS) {
ldb_debug(ldb, LDB_DEBUG_ERROR,
"Failed to connect to '%s'\n", url);
return ret;
}
return ret;
}
/*
try to autodetect a basedn if none specified. This fixes one of my
pet hates about ldapsearch, which is that you have to get a long,

View File

@ -120,36 +120,149 @@ const char **ldb_modules_list_from_string(struct ldb_context *ldb, TALLOC_CTX *m
return m;
}
static struct backends_list_entry {
struct ldb_backend_ops *ops;
struct backends_list_entry *prev, *next;
} *ldb_backends = NULL;
static struct ops_list_entry {
const struct ldb_module_ops *ops;
struct ops_list_entry *next;
} *registered_modules = NULL;
#define LDB_MODULE(name) (&ldb_ ## name ## _module_ops)
static const struct ldb_builtins {
const struct ldb_backend_ops *backend_ops;
const struct ldb_module_ops *module_ops;
} builtins[];
#ifndef STATIC_LIBLDB_MODULES
static ldb_connect_fn ldb_find_backend(const char *url)
{
struct backends_list_entry *backend;
int i;
#define STATIC_LIBLDB_MODULES \
LDB_MODULE(operational), \
LDB_MODULE(rdn_name), \
LDB_MODULE(paged_results), \
LDB_MODULE(server_sort), \
LDB_MODULE(asq), \
NULL
#endif
for (i = 0; builtins[i].backend_ops || builtins[i].module_ops; i++) {
if (builtins[i].backend_ops == NULL) continue;
const static struct ldb_module_ops *builtin_modules[] = {
STATIC_LIBLDB_MODULES
};
if (strncmp(builtins[i].backend_ops->name, url,
strlen(builtins[i].backend_ops->name)) == 0) {
return builtins[i].backend_ops->connect_fn;
}
}
for (backend = ldb_backends; backend; backend = backend->next) {
if (strncmp(backend->ops->name, url,
strlen(backend->ops->name)) == 0) {
return backend->ops->connect_fn;
}
}
return NULL;
}
/*
register a new ldb backend
*/
int ldb_register_backend(const char *url_prefix, ldb_connect_fn connectfn)
{
struct ldb_backend_ops *backend;
struct backends_list_entry *entry;
backend = talloc(talloc_autofree_context(), struct ldb_backend_ops);
if (!backend) return LDB_ERR_OPERATIONS_ERROR;
entry = talloc(talloc_autofree_context(), struct backends_list_entry);
if (!entry) {
talloc_free(backend);
return LDB_ERR_OPERATIONS_ERROR;
}
if (ldb_find_backend(url_prefix)) {
return LDB_SUCCESS;
}
/* Maybe check for duplicity here later on? */
backend->name = talloc_strdup(backend, url_prefix);
backend->connect_fn = connectfn;
entry->ops = backend;
DLIST_ADD(ldb_backends, entry);
return LDB_SUCCESS;
}
/*
Return the ldb module form of a database.
The URL can either be one of the following forms
ldb://path
ldapi://path
flags is made up of LDB_FLG_*
the options are passed uninterpreted to the backend, and are
backend specific.
This allows modules to get at only the backend module, for example where a
module may wish to direct certain requests at a particular backend.
*/
int ldb_connect_backend(struct ldb_context *ldb,
const char *url,
const char *options[],
struct ldb_module **backend_module)
{
int ret;
char *backend;
ldb_connect_fn fn;
if (strchr(url, ':') != NULL) {
backend = talloc_strndup(ldb, url, strchr(url, ':')-url);
} else {
/* Default to tdb */
backend = talloc_strdup(ldb, "tdb");
}
fn = ldb_find_backend(backend);
if (fn == NULL) {
struct ldb_backend_ops *ops;
char *symbol_name = talloc_asprintf(ldb, "ldb_%s_backend_ops", backend);
if (symbol_name == NULL) {
return LDB_ERR_OPERATIONS_ERROR;
}
ops = ldb_dso_load_symbol(ldb, backend, symbol_name);
if (ops != NULL) {
fn = ops->connect_fn;
}
talloc_free(symbol_name);
}
talloc_free(backend);
if (fn == NULL) {
ldb_debug(ldb, LDB_DEBUG_FATAL,
"Unable to find backend for '%s'\n", url);
return LDB_ERR_OTHER;
}
ret = fn(ldb, url, ldb->flags, options, backend_module);
if (ret != LDB_SUCCESS) {
ldb_debug(ldb, LDB_DEBUG_ERROR,
"Failed to connect to '%s'\n", url);
return ret;
}
return ret;
}
static const struct ldb_module_ops *ldb_find_module_ops(const char *name)
{
struct ops_list_entry *e;
int i;
for (i = 0; builtin_modules[i]; i++) {
if (strcmp(builtin_modules[i]->name, name) == 0)
return builtin_modules[i];
for (i = 0; builtins[i].backend_ops || builtins[i].module_ops; i++) {
if (builtins[i].module_ops == NULL) continue;
if (strcmp(builtins[i].module_ops->name, name) == 0)
return builtins[i].module_ops;
}
for (e = registered_modules; e; e = e->next) {
@ -441,3 +554,72 @@ int ldb_next_del_trans(struct ldb_module *module)
FIND_OP(module, del_transaction);
return module->ops->del_transaction(module);
}
#ifndef STATIC_LIBLDB_MODULES
#ifdef HAVE_LDB_LDAP
#define LDAP_BACKEND LDB_BACKEND(ldap), LDB_BACKEND(ldapi), LDB_BACKEND(ldaps),
#else
#define LDAP_BACKEND
#endif
#ifdef HAVE_LDB_SQLITE3
#define SQLITE3_BACKEND LDB_BACKEND(sqlite3),
#else
#define SQLITE3_BACKEND
#endif
#define STATIC_LIBLDB_MODULES \
LDB_BACKEND(tdb), \
LDAP_BACKEND \
SQLITE3_BACKEND \
LDB_MODULE(operational), \
LDB_MODULE(rdn_name), \
LDB_MODULE(paged_results), \
LDB_MODULE(server_sort), \
LDB_MODULE(asq), \
NULL
#endif
/*
* this is a bit hacked, as STATIC_LIBLDB_MODULES contains ','
* between the elements and we want to autogenerate the
* extern struct declarations, so we do some hacks and let the
* ',' appear in an unused function prototype.
*/
#undef NULL
#define NULL LDB_MODULE(NULL),
#define LDB_BACKEND(name) \
int); \
extern const struct ldb_backend_ops ldb_ ## name ## _backend_ops;\
extern void ldb_noop ## name (int
#define LDB_MODULE(name) \
int); \
extern const struct ldb_module_ops ldb_ ## name ## _module_ops;\
extern void ldb_noop ## name (int
extern void ldb_start_noop(int,
STATIC_LIBLDB_MODULES
int);
#undef NULL
#define NULL { \
.backend_ops = (void *)0, \
.module_ops = (void *)0 \
}
#undef LDB_BACKEND
#define LDB_BACKEND(name) { \
.backend_ops = &ldb_ ## name ## _backend_ops, \
.module_ops = (void *)0 \
}
#undef LDB_MODULE
#define LDB_MODULE(name) { \
.backend_ops = (void *)0, \
.module_ops = &ldb_ ## name ## _module_ops \
}
static const struct ldb_builtins builtins[] = {
STATIC_LIBLDB_MODULES
};

View File

@ -92,6 +92,7 @@ ldb_skel_OBJ_FILES = $(ldbsrcdir)/modules/skel.o
SUBSYSTEM = LIBLDB
CFLAGS = -I$(ldbsrcdir)/include
PRIVATE_DEPENDENCIES = LIBTALLOC SQLITE3 LIBEVENTS
INIT_FUNCTION = LDB_BACKEND(sqlite3)
# End MODULE ldb_sqlite3
################################################
@ -104,6 +105,7 @@ SUBSYSTEM = LIBLDB
CFLAGS = -I$(ldbsrcdir)/include -I$(ldbsrcdir)/ldb_tdb
PRIVATE_DEPENDENCIES = \
LIBTDB LIBTALLOC LIBEVENTS
INIT_FUNCTION = LDB_BACKEND(tdb)
# End MODULE ldb_tdb
################################################
@ -114,7 +116,6 @@ ldb_tdb_OBJ_FILES = $(addprefix $(ldbsrcdir)/ldb_tdb/, ldb_tdb.o ldb_search.o ld
# Start SUBSYSTEM ldb
[LIBRARY::LIBLDB]
CFLAGS = -I$(ldbsrcdir)/include
INIT_FUNCTION_TYPE = extern const struct ldb_module_ops
PUBLIC_DEPENDENCIES = \
LIBTALLOC LIBEVENTS
PRIVATE_DEPENDENCIES = \

View File

@ -5,6 +5,7 @@ SUBSYSTEM = LIBLDB
CFLAGS = -I$(ldbsrcdir)/include
OUTPUT_TYPE = SHARED_LIBRARY
PRIVATE_DEPENDENCIES = LIBTALLOC LIBCLI_LDAP CREDENTIALS
INIT_FUNCTION = LDB_BACKEND(ldapi),LDB_BACKEND(ldaps),LDB_BACKEND(ldap)
ALIASES = ldapi ldaps ldap
# End MODULE ldb_ildap
################################################