diff options
-rw-r--r-- | source4/dsdb/samdb/ldb_modules/rootdse.c | 11 | ||||
-rw-r--r-- | source4/lib/ldb/common/ldb.c | 70 | ||||
-rw-r--r-- | source4/lib/ldb/common/ldb_modules.c | 3 | ||||
-rw-r--r-- | source4/lib/ldb/include/ldb.h | 14 | ||||
-rw-r--r-- | source4/lib/ldb/include/ldb_private.h | 4 | ||||
-rw-r--r-- | source4/lib/ldb/ldb_ildap/ldb_ildap.c | 19 | ||||
-rw-r--r-- | source4/lib/ldb/ldb_ldap/ldb_ldap.c | 22 | ||||
-rw-r--r-- | source4/lib/ldb/ldb_sqlite3/ldb_sqlite3.c | 24 | ||||
-rw-r--r-- | source4/lib/ldb/ldb_tdb/ldb_tdb.c | 52 |
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 = <db_ops; - ldb->sequence_number = ltdb_sequence_number; + (*module)->ldb = ldb; + (*module)->prev = ldb->modules->next = NULL; + (*module)->private_data = ltdb; + (*module)->ops = <db_ops; return 0; } |