diff options
-rw-r--r-- | source4/dsdb/samdb/ldb_modules/rootdse.c | 9 | ||||
-rw-r--r-- | source4/lib/ldb/include/ldb_private.h | 3 | ||||
-rw-r--r-- | source4/lib/ldb/ldb_tdb/ldb_tdb.c | 26 | ||||
-rw-r--r-- | source4/lib/ldb/modules/operational.c | 43 |
4 files changed, 81 insertions, 0 deletions
diff --git a/source4/dsdb/samdb/ldb_modules/rootdse.c b/source4/dsdb/samdb/ldb_modules/rootdse.c index 07e34f1841..987fd7a7f1 100644 --- a/source4/dsdb/samdb/ldb_modules/rootdse.c +++ b/source4/dsdb/samdb/ldb_modules/rootdse.c @@ -43,6 +43,7 @@ static int do_attribute(const char * const *attrs, const char *name) ldb_attr_in_list(attrs, "*"); } + /* add dynamically generated attributes to rootDSE result */ @@ -106,6 +107,14 @@ static int rootdse_add_dynamic(struct ldb_module *module, struct ldb_request *re } } } + + if (do_attribute(s->attrs, "highestCommittedUSN")) { + if (module->ldb->sequence_number != NULL && + ldb_msg_add_fmt(msg, "highestCommittedUSN", + "%llu", module->ldb->sequence_number(module->ldb)) != 0) { + goto failed; + } + } /* TODO: lots more dynamic attributes should be added here */ diff --git a/source4/lib/ldb/include/ldb_private.h b/source4/lib/ldb/include/ldb_private.h index 24967faeea..3f9be357a7 100644 --- a/source4/lib/ldb/include/ldb_private.h +++ b/source4/lib/ldb/include/ldb_private.h @@ -107,6 +107,9 @@ struct ldb_context { int transaction_active; int (*async_wait)(struct ldb_async_handle *, enum ldb_async_wait_type); + + /* a backend supplied highestCommittedUSN function */ + uint64_t (*sequence_number)(struct ldb_context *); }; /* the modules init function */ diff --git a/source4/lib/ldb/ldb_tdb/ldb_tdb.c b/source4/lib/ldb/ldb_tdb/ldb_tdb.c index 8d8c01278d..b58b03f221 100644 --- a/source4/lib/ldb/ldb_tdb/ldb_tdb.c +++ b/source4/lib/ldb/ldb_tdb/ldb_tdb.c @@ -772,6 +772,31 @@ 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) +{ + TALLOC_CTX *tmp_ctx = talloc_new(ldb); + const char *attrs[] = { "sequenceNumber", NULL }; + struct ldb_result *res = NULL; + struct ldb_dn *dn = ldb_dn_explode(tmp_ctx, "@BASEINFO"); + int ret; + uint64_t seq_num; + + ret = ldb_search(ldb, dn, LDB_SCOPE_BASE, NULL, attrs, &res); + talloc_steal(tmp_ctx, res); + if (ret != LDB_SUCCESS || res->count != 1) { + talloc_free(tmp_ctx); + /* zero is as good as anything when we don't know */ + return 0; + } + + seq_num = ldb_msg_find_uint64(res->msgs[0], "sequenceNumber", 0); + talloc_free(tmp_ctx); + return seq_num; +} + static int ltdb_init_2(struct ldb_module *module) { return LDB_SUCCESS; @@ -847,6 +872,7 @@ int ltdb_connect(struct ldb_context *ldb, const char *url, ldb->modules->prev = ldb->modules->next = NULL; ldb->modules->private_data = ltdb; ldb->modules->ops = <db_ops; + ldb->sequence_number = ltdb_sequence_number; return 0; } diff --git a/source4/lib/ldb/modules/operational.c b/source4/lib/ldb/modules/operational.c index 8b7d6b3518..51f0ce25e4 100644 --- a/source4/lib/ldb/modules/operational.c +++ b/source4/lib/ldb/modules/operational.c @@ -267,6 +267,29 @@ static int add_time_element(struct ldb_message *msg, const char *attr, time_t t) return 0; } +/* + add a uint64_t element to a record +*/ +static int add_uint64_element(struct ldb_message *msg, const char *attr, uint64_t v) +{ + struct ldb_message_element *el; + + if (ldb_msg_find_element(msg, attr) != NULL) { + return 0; + } + + if (ldb_msg_add_fmt(msg, attr, "%llu", v) != 0) { + return -1; + } + + el = ldb_msg_find_element(msg, attr); + /* always set as replace. This works because on add ops, the flag + is ignored */ + el->flags = LDB_FLAG_MOD_REPLACE; + + return 0; +} + /* hook add record ops @@ -292,6 +315,17 @@ static int operational_add(struct ldb_module *module, struct ldb_request *req) talloc_free(msg2); return -1; } + + /* see if the backend can give us the USN */ + if (module->ldb->sequence_number != NULL) { + uint64_t seq_num = module->ldb->sequence_number(module->ldb); + if (add_uint64_element(msg2, "uSNCreated", seq_num) != 0 || + add_uint64_element(msg2, "uSNChanged", seq_num) != 0) { + talloc_free(msg2); + return -1; + } + } + /* use the new structure for the call chain below this point */ req->op.add.message = msg2; /* go on with the call chain */ @@ -326,6 +360,15 @@ static int operational_modify(struct ldb_module *module, struct ldb_request *req talloc_free(msg2); return -1; } + + /* update the records USN if possible */ + if (module->ldb->sequence_number != NULL && + add_uint64_element(msg2, "uSNChanged", + module->ldb->sequence_number(module->ldb)) != 0) { + talloc_free(msg2); + return -1; + } + /* use the new structure for the call chain below this point */ req->op.mod.message = msg2; /* go on with the call chain */ |