summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--source4/dsdb/samdb/ldb_modules/rootdse.c11
-rw-r--r--source4/lib/ldb/common/ldb.c70
-rw-r--r--source4/lib/ldb/common/ldb_modules.c3
-rw-r--r--source4/lib/ldb/include/ldb.h14
-rw-r--r--source4/lib/ldb/include/ldb_private.h4
-rw-r--r--source4/lib/ldb/ldb_ildap/ldb_ildap.c19
-rw-r--r--source4/lib/ldb/ldb_ldap/ldb_ldap.c22
-rw-r--r--source4/lib/ldb/ldb_sqlite3/ldb_sqlite3.c24
-rw-r--r--source4/lib/ldb/ldb_tdb/ldb_tdb.c52
9 files changed, 159 insertions, 60 deletions
diff --git a/source4/dsdb/samdb/ldb_modules/rootdse.c b/source4/dsdb/samdb/ldb_modules/rootdse.c
index e96da829eb..49d93be7f2 100644
--- a/source4/dsdb/samdb/ldb_modules/rootdse.c
+++ b/source4/dsdb/samdb/ldb_modules/rootdse.c
@@ -102,10 +102,13 @@ static int rootdse_add_dynamic(struct ldb_module *module, struct ldb_message *ms
}
if (do_attribute(attrs, "highestCommittedUSN")) {
- if (module->ldb->sequence_number != NULL &&
- ldb_msg_add_fmt(msg, "highestCommittedUSN",
- "%llu", module->ldb->sequence_number(module->ldb)) != 0) {
- goto failed;
+ uint64_t seq_num;
+ int ret = ldb_sequence_number(module->ldb, &seq_num);
+ if (ret == LDB_SUCCESS) {
+ if (ldb_msg_add_fmt(msg, "highestCommittedUSN",
+ "%llu", seq_num) != 0) {
+ goto failed;
+ }
}
}
diff --git a/source4/lib/ldb/common/ldb.c b/source4/lib/ldb/common/ldb.c
index 1fdbeb55d2..ff5d2a2e8b 100644
--- a/source4/lib/ldb/common/ldb.c
+++ b/source4/lib/ldb/common/ldb.c
@@ -91,16 +91,20 @@ static ldb_connect_fn ldb_find_backend(const char *url)
}
/*
- connect to a database. The URL can either be one of the following forms
+ 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
+ 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(struct ldb_context *ldb, const char *url, unsigned int flags, const char *options[])
+int ldb_connect_backend(struct ldb_context *ldb, const char *url, unsigned int flags, const char *options[],
+ struct ldb_module **backend_module)
{
int ret;
char *backend;
@@ -128,12 +132,34 @@ int ldb_connect(struct ldb_context *ldb, const char *url, unsigned int flags, co
return LDB_ERR_OTHER;
}
- ret = fn(ldb, url, flags, options);
+ ret = fn(ldb, url, 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;
+}
+
+
+/*
+ connect to 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
+*/
+int ldb_connect(struct ldb_context *ldb, const char *url, unsigned int flags, const char *options[])
+{
+ int ret;
+
+ ret = ldb_connect_backend(ldb, url, flags, options, &ldb->modules);
+ if (ret != LDB_SUCCESS) {
+ return ret;
+ }
if (ldb_load_modules(ldb, options) != LDB_SUCCESS) {
ldb_debug(ldb, LDB_DEBUG_FATAL, "Unable to load modules for '%s'\n", url);
@@ -395,6 +421,10 @@ int ldb_request(struct ldb_context *ldb, struct ldb_request *req)
FIRST_OP(ldb, rename);
ret = module->ops->rename(module, req);
break;
+ case LDB_SEQUENCE_NUMBER:
+ FIRST_OP(ldb, sequence_number);
+ ret = module->ops->sequence_number(module, req);
+ break;
default:
FIRST_OP(ldb, request);
ret = module->ops->request(module, req);
@@ -655,6 +685,38 @@ int ldb_rename(struct ldb_context *ldb, const struct ldb_dn *olddn, const struct
}
+/*
+ rename a record in the database
+*/
+int ldb_sequence_number(struct ldb_context *ldb, uint64_t *seq_num)
+{
+ struct ldb_request *req;
+ int ret;
+
+ req = talloc(ldb, struct ldb_request);
+ if (req == NULL) {
+ ldb_set_errstring(ldb, talloc_strdup(ldb, "Out of memory!"));
+ return LDB_ERR_OPERATIONS_ERROR;
+ }
+
+ req->operation = LDB_SEQUENCE_NUMBER;
+ req->controls = NULL;
+ req->async.context = NULL;
+ req->async.callback = NULL;
+ ldb_set_timeout(ldb, req, 0); /* use default timeout */
+
+ /* do request and autostart a transaction */
+ ret = ldb_request(ldb, req);
+
+ if (ret == LDB_SUCCESS) {
+ *seq_num = req->op.seq_num.seq_num;
+ }
+
+ talloc_free(req);
+ return ret;
+}
+
+
/*
return extended error information
diff --git a/source4/lib/ldb/common/ldb_modules.c b/source4/lib/ldb/common/ldb_modules.c
index 6f36bdc5e9..d09579510e 100644
--- a/source4/lib/ldb/common/ldb_modules.c
+++ b/source4/lib/ldb/common/ldb_modules.c
@@ -366,6 +366,9 @@ int ldb_next_request(struct ldb_module *module, struct ldb_request *request)
case LDB_RENAME:
FIND_OP(module, rename);
return module->ops->rename(module, request);
+ case LDB_SEQUENCE_NUMBER:
+ FIND_OP(module, sequence_number);
+ return module->ops->sequence_number(module, request);
default:
FIND_OP(module, request);
return module->ops->request(module, request);
diff --git a/source4/lib/ldb/include/ldb.h b/source4/lib/ldb/include/ldb.h
index 644f74385f..033a9c1f39 100644
--- a/source4/lib/ldb/include/ldb.h
+++ b/source4/lib/ldb/include/ldb.h
@@ -567,8 +567,8 @@ enum ldb_request_type {
LDB_MODIFY,
LDB_DELETE,
LDB_RENAME,
-
- LDB_REQ_REGISTER
+ LDB_REQ_REGISTER,
+ LDB_SEQUENCE_NUMBER
};
enum ldb_reply_type {
@@ -638,6 +638,10 @@ struct ldb_register_control {
const char *oid;
};
+struct ldb_sequence_number {
+ uint64_t seq_num;
+};
+
struct ldb_request {
enum ldb_request_type operation;
@@ -649,6 +653,7 @@ struct ldb_request {
struct ldb_delete del;
struct ldb_rename rename;
struct ldb_register_control reg;
+ struct ldb_sequence_number seq_num;
} op;
struct ldb_control **controls;
@@ -811,6 +816,11 @@ int ldb_rename(struct ldb_context *ldb, const struct ldb_dn *olddn, const struct
int ldb_delete(struct ldb_context *ldb, const struct ldb_dn *dn);
/**
+ Obtain current database sequence number
+*/
+int ldb_sequence_number(struct ldb_context *ldb, uint64_t *seq_num);
+
+/**
start a transaction
*/
int ldb_transaction_start(struct ldb_context *ldb);
diff --git a/source4/lib/ldb/include/ldb_private.h b/source4/lib/ldb/include/ldb_private.h
index 14f0403697..6d017d5cc1 100644
--- a/source4/lib/ldb/include/ldb_private.h
+++ b/source4/lib/ldb/include/ldb_private.h
@@ -67,9 +67,11 @@ struct ldb_module_ops {
int (*end_transaction)(struct ldb_module *);
int (*del_transaction)(struct ldb_module *);
int (*async_wait)(struct ldb_async_handle *, enum ldb_async_wait_type);
+ int (*sequence_number)(struct ldb_module *, struct ldb_request *);
};
-typedef int (*ldb_connect_fn) (struct ldb_context *ldb, const char *url, unsigned int flags, const char *options[]);
+typedef int (*ldb_connect_fn) (struct ldb_context *ldb, const char *url, unsigned int flags, const char *options[],
+ struct ldb_module **module);
/*
schema related information needed for matching rules
diff --git a/source4/lib/ldb/ldb_ildap/ldb_ildap.c b/source4/lib/ldb/ldb_ildap/ldb_ildap.c
index 4fc34ccdcf..340f89e48f 100644
--- a/source4/lib/ldb/ldb_ildap/ldb_ildap.c
+++ b/source4/lib/ldb/ldb_ildap/ldb_ildap.c
@@ -792,7 +792,8 @@ static const struct ldb_module_ops ildb_ops = {
connect to the database
*/
static int ildb_connect(struct ldb_context *ldb, const char *url,
- unsigned int flags, const char *options[])
+ unsigned int flags, const char *options[],
+ struct ldb_module **module)
{
struct ildb_private *ildb = NULL;
NTSTATUS status;
@@ -824,15 +825,17 @@ static int ildb_connect(struct ldb_context *ldb, const char *url,
goto failed;
}
- ldb->modules = talloc(ldb, struct ldb_module);
- if (!ldb->modules) {
+
+ *module = talloc(ldb, struct ldb_module);
+ if (!module) {
ldb_oom(ldb);
- goto failed;
+ talloc_free(ildb);
+ return -1;
}
- ldb->modules->ldb = ldb;
- ldb->modules->prev = ldb->modules->next = NULL;
- ldb->modules->private_data = ildb;
- ldb->modules->ops = &ildb_ops;
+ (*module)->ldb = ldb;
+ (*module)->prev = ldb->modules->next = NULL;
+ (*module)->private_data = ildb;
+ (*module)->ops = &ildb_ops;
/* caller can optionally setup credentials using the opaque token 'credentials' */
creds = talloc_get_type(ldb_get_opaque(ldb, "credentials"), struct cli_credentials);
diff --git a/source4/lib/ldb/ldb_ldap/ldb_ldap.c b/source4/lib/ldb/ldb_ldap/ldb_ldap.c
index 4132fa6c15..c74be37108 100644
--- a/source4/lib/ldb/ldb_ldap/ldb_ldap.c
+++ b/source4/lib/ldb/ldb_ldap/ldb_ldap.c
@@ -771,9 +771,10 @@ static int lldb_destructor(struct lldb_private *lldb)
connect to the database
*/
static int lldb_connect(struct ldb_context *ldb,
- const char *url,
- unsigned int flags,
- const char *options[])
+ const char *url,
+ unsigned int flags,
+ const char *options[],
+ struct ldb_module **module)
{
struct lldb_private *lldb = NULL;
int version = 3;
@@ -803,15 +804,16 @@ static int lldb_connect(struct ldb_context *ldb,
goto failed;
}
- ldb->modules = talloc(ldb, struct ldb_module);
- if (!ldb->modules) {
+ *module = talloc(ldb, struct ldb_module);
+ if (!module) {
ldb_oom(ldb);
- goto failed;
+ talloc_free(lldb);
+ return -1;
}
- ldb->modules->ldb = ldb;
- ldb->modules->prev = ldb->modules->next = NULL;
- ldb->modules->private_data = lldb;
- ldb->modules->ops = &lldb_ops;
+ (*module)->ldb = ldb;
+ (*module)->prev = ldb->modules->next = NULL;
+ (*module)->private_data = lldb;
+ (*module)->ops = &lldb_ops;
return 0;
diff --git a/source4/lib/ldb/ldb_sqlite3/ldb_sqlite3.c b/source4/lib/ldb/ldb_sqlite3/ldb_sqlite3.c
index 06b76e812d..053ccd1b21 100644
--- a/source4/lib/ldb/ldb_sqlite3/ldb_sqlite3.c
+++ b/source4/lib/ldb/ldb_sqlite3/ldb_sqlite3.c
@@ -2073,9 +2073,10 @@ static const struct ldb_module_ops lsqlite3_ops = {
* connect to the database
*/
static int lsqlite3_connect(struct ldb_context *ldb,
- const char *url,
- unsigned int flags,
- const char *options[])
+ const char *url,
+ unsigned int flags,
+ const char *options[],
+ struct ldb_module **module)
{
int i;
int ret;
@@ -2097,15 +2098,18 @@ static int lsqlite3_connect(struct ldb_context *ldb,
talloc_set_destructor(lsqlite3, destructor);
- ldb->modules = talloc(ldb, struct ldb_module);
- if (!ldb->modules) {
+
+
+ *module = talloc(ldb, struct ldb_module);
+ if (!module) {
+ ldb_oom(ldb);
goto failed;
}
- ldb->modules->ldb = ldb;
- ldb->modules->prev = ldb->modules->next = NULL;
- ldb->modules->private_data = lsqlite3;
- ldb->modules->ops = &lsqlite3_ops;
-
+ (*module)->ldb = ldb;
+ (*module)->prev = ldb->modules->next = NULL;
+ (*module)->private_data = lsqlite3;
+ (*module)->ops = &lsqlite3_ops;
+
if (options) {
/*
* take a copy of the options array, so we don't have to rely
diff --git a/source4/lib/ldb/ldb_tdb/ldb_tdb.c b/source4/lib/ldb/ldb_tdb/ldb_tdb.c
index b8f4a024d2..224c25891c 100644
--- a/source4/lib/ldb/ldb_tdb/ldb_tdb.c
+++ b/source4/lib/ldb/ldb_tdb/ldb_tdb.c
@@ -923,26 +923,35 @@ static int ltdb_request(struct ldb_module *module, struct ldb_request *req)
/*
return sequenceNumber from @BASEINFO
*/
-static uint64_t ltdb_sequence_number(struct ldb_context *ldb)
+static int ltdb_sequence_number(struct ldb_module *module, struct ldb_request *req)
{
- TALLOC_CTX *tmp_ctx = talloc_new(ldb);
- const char *attrs[] = { "sequenceNumber", NULL };
- struct ldb_result *res = NULL;
+ TALLOC_CTX *tmp_ctx = talloc_new(req);
+ struct ldb_message *msg = NULL;
struct ldb_dn *dn = ldb_dn_explode(tmp_ctx, "@BASEINFO");
- int ret;
- uint64_t seq_num;
+ int tret;
+
+ if (tmp_ctx == NULL) {
+ talloc_free(tmp_ctx);
+ return LDB_ERR_OPERATIONS_ERROR;
+ }
+
+ msg = talloc(tmp_ctx, struct ldb_message);
+ if (msg == NULL) {
+ talloc_free(tmp_ctx);
+ return LDB_ERR_OPERATIONS_ERROR;
+ }
- ret = ldb_search(ldb, dn, LDB_SCOPE_BASE, NULL, attrs, &res);
- talloc_steal(tmp_ctx, res);
- if (ret != LDB_SUCCESS || res->count != 1) {
+ tret = ltdb_search_dn1(module, dn, msg);
+ if (tret != 1) {
talloc_free(tmp_ctx);
+ req->op.seq_num.seq_num = 0;
/* zero is as good as anything when we don't know */
- return 0;
+ return LDB_SUCCESS;
}
- seq_num = ldb_msg_find_uint64(res->msgs[0], "sequenceNumber", 0);
+ req->op.seq_num.seq_num = ldb_msg_find_uint64(msg, "sequenceNumber", 0);
talloc_free(tmp_ctx);
- return seq_num;
+ return LDB_SUCCESS;
}
static const struct ldb_module_ops ltdb_ops = {
@@ -956,7 +965,8 @@ static const struct ldb_module_ops ltdb_ops = {
.start_transaction = ltdb_start_trans,
.end_transaction = ltdb_end_trans,
.del_transaction = ltdb_del_trans,
- .async_wait = ltdb_async_wait
+ .async_wait = ltdb_async_wait,
+ .sequence_number = ltdb_sequence_number
};
@@ -964,7 +974,8 @@ static const struct ldb_module_ops ltdb_ops = {
connect to the database
*/
static int ltdb_connect(struct ldb_context *ldb, const char *url,
- unsigned int flags, const char *options[])
+ unsigned int flags, const char *options[],
+ struct ldb_module **module)
{
const char *path;
int tdb_flags, open_flags;
@@ -1010,17 +1021,16 @@ static int ltdb_connect(struct ldb_context *ldb, const char *url,
ltdb->sequence_number = 0;
- ldb->modules = talloc(ldb, struct ldb_module);
- if (!ldb->modules) {
+ *module = talloc(ldb, struct ldb_module);
+ if (!module) {
ldb_oom(ldb);
talloc_free(ltdb);
return -1;
}
- ldb->modules->ldb = ldb;
- ldb->modules->prev = ldb->modules->next = NULL;
- ldb->modules->private_data = ltdb;
- ldb->modules->ops = &ltdb_ops;
- ldb->sequence_number = ltdb_sequence_number;
+ (*module)->ldb = ldb;
+ (*module)->prev = ldb->modules->next = NULL;
+ (*module)->private_data = ltdb;
+ (*module)->ops = &ltdb_ops;
return 0;
}