summaryrefslogtreecommitdiff
path: root/source4
diff options
context:
space:
mode:
Diffstat (limited to 'source4')
-rw-r--r--source4/dsdb/samdb/ldb_modules/objectguid.c2
-rw-r--r--source4/dsdb/samdb/ldb_modules/partition.c246
-rw-r--r--source4/dsdb/samdb/ldb_modules/simple_ldap_map.c68
-rw-r--r--source4/lib/ldb/common/ldb.c50
-rw-r--r--source4/lib/ldb/common/ldb_modules.c4
-rw-r--r--source4/lib/ldb/include/ldb.h37
-rw-r--r--source4/lib/ldb/ldb.i20
-rw-r--r--source4/lib/ldb/ldb_tdb/ldb_search.c24
-rw-r--r--source4/lib/ldb/ldb_tdb/ldb_tdb.c144
-rw-r--r--source4/lib/ldb/ldb_tdb/ldb_tdb.h2
-rw-r--r--source4/lib/ldb/ldb_wrap.c20
-rw-r--r--source4/setup/schema_samba4.ldif2
12 files changed, 412 insertions, 207 deletions
diff --git a/source4/dsdb/samdb/ldb_modules/objectguid.c b/source4/dsdb/samdb/ldb_modules/objectguid.c
index 054905992d..3d725686e7 100644
--- a/source4/dsdb/samdb/ldb_modules/objectguid.c
+++ b/source4/dsdb/samdb/ldb_modules/objectguid.c
@@ -194,7 +194,7 @@ static int objectguid_add(struct ldb_module *module, struct ldb_request *req)
}
/* Get a sequence number from the backend */
- /* FIXME: ldb_sequence_number is still SYNC now, when this changes,
+ /* FIXME: ldb_sequence_number is a semi-async call,
* make sure this function is split and a callback is used */
ret = ldb_sequence_number(module->ldb, LDB_SEQ_NEXT, &seq_num);
if (ret == LDB_SUCCESS) {
diff --git a/source4/dsdb/samdb/ldb_modules/partition.c b/source4/dsdb/samdb/ldb_modules/partition.c
index b452b66d56..b4a7a47a23 100644
--- a/source4/dsdb/samdb/ldb_modules/partition.c
+++ b/source4/dsdb/samdb/ldb_modules/partition.c
@@ -115,10 +115,6 @@ int partition_request(struct ldb_module *module, struct ldb_request *request)
PARTITION_FIND_OP(module, extended);
ret = module->ops->extended(module, request);
break;
- case LDB_SEQUENCE_NUMBER:
- PARTITION_FIND_OP(module, sequence_number);
- ret = module->ops->sequence_number(module, request);
- break;
default:
PARTITION_FIND_OP(module, request);
ret = module->ops->request(module, request);
@@ -716,9 +712,8 @@ static int partition_del_trans(struct ldb_module *module)
return ret2;
}
-/* NOTE: ldb_sequence_number is still a completely SYNCHRONOUS call
- * implemented only in ldb_rdb. It does not require ldb_wait() to be
- * called after a request is made */
+
+/* FIXME: This function is still semi-async */
static int partition_sequence_number(struct ldb_module *module, struct ldb_request *req)
{
int i, ret;
@@ -727,113 +722,241 @@ static int partition_sequence_number(struct ldb_module *module, struct ldb_reque
uint64_t timestamp = 0;
struct partition_private_data *data = talloc_get_type(module->private_data,
struct partition_private_data);
+ struct ldb_seqnum_request *seq;
+ struct ldb_seqnum_result *seqr;
+ struct ldb_request *treq;
+ struct ldb_seqnum_request *tseq;
+ struct ldb_seqnum_result *tseqr;
+ struct ldb_extended *ext;
+ struct ldb_result *res;
- switch (req->op.seq_num.type) {
+ seq = talloc_get_type(req->op.extended.data, struct ldb_seqnum_request);
+
+ switch (seq->type) {
case LDB_SEQ_NEXT:
case LDB_SEQ_HIGHEST_SEQ:
- ret = ldb_next_request(module, req);
- if (ret != LDB_SUCCESS) {
- return ret;
+ res = talloc_zero(req, struct ldb_result);
+ if (res == NULL) {
+ return LDB_ERR_OPERATIONS_ERROR;
}
- if (req->op.seq_num.flags & LDB_SEQ_TIMESTAMP_SEQUENCE) {
- timestamp_sequence = req->op.seq_num.seq_num;
- } else {
- seq_number = seq_number + req->op.seq_num.seq_num;
+ tseq = talloc_zero(res, struct ldb_seqnum_request);
+ if (tseq == NULL) {
+ talloc_free(res);
+ return LDB_ERR_OPERATIONS_ERROR;
+ }
+ tseq->type = seq->type;
+
+ ret = ldb_build_extended_req(&treq, module->ldb, res,
+ LDB_EXTENDED_SEQUENCE_NUMBER,
+ tseq,
+ NULL,
+ res,
+ ldb_extended_default_callback,
+ NULL);
+ ret = ldb_next_request(module, treq);
+ if (ret == LDB_SUCCESS) {
+ ret = ldb_wait(treq->handle, LDB_WAIT_ALL);
}
-
- /* gross hack part1 */
- ret = ldb_request_add_control(req,
- DSDB_CONTROL_CURRENT_PARTITION_OID,
- false, NULL);
if (ret != LDB_SUCCESS) {
+ talloc_free(res);
return ret;
}
+ seqr = talloc_get_type(res->extended->data,
+ struct ldb_seqnum_result);
+ if (seqr->flags & LDB_SEQ_TIMESTAMP_SEQUENCE) {
+ timestamp_sequence = seqr->seq_num;
+ } else {
+ seq_number += seqr->seq_num;
+ }
+ talloc_free(res);
- /* Look at base DN */
- /* Figure out which partition it is under */
/* Skip the lot if 'data' isn't here yet (initialistion) */
for (i=0; data && data->partitions && data->partitions[i]; i++) {
- /* gross hack part2 */
- int j;
- for (j=0; req->controls[j]; j++) {
- if (strcmp(req->controls[j]->oid, DSDB_CONTROL_CURRENT_PARTITION_OID) == 0) {
- req->controls[j]->data = data->partitions[i];
- break;
- }
+ res = talloc_zero(req, struct ldb_result);
+ if (res == NULL) {
+ return LDB_ERR_OPERATIONS_ERROR;
+ }
+ tseq = talloc_zero(res, struct ldb_seqnum_request);
+ if (tseq == NULL) {
+ talloc_free(res);
+ return LDB_ERR_OPERATIONS_ERROR;
+ }
+ tseq->type = seq->type;
+
+ ret = ldb_build_extended_req(&treq, module->ldb, res,
+ LDB_EXTENDED_SEQUENCE_NUMBER,
+ tseq,
+ NULL,
+ res,
+ ldb_extended_default_callback,
+ NULL);
+ if (ret != LDB_SUCCESS) {
+ talloc_free(res);
+ return ret;
}
- ret = partition_request(data->partitions[i]->module, req);
+ ret = ldb_request_add_control(treq,
+ DSDB_CONTROL_CURRENT_PARTITION_OID,
+ false, data->partitions[i]);
if (ret != LDB_SUCCESS) {
+ talloc_free(res);
return ret;
}
- if (req->op.seq_num.flags & LDB_SEQ_TIMESTAMP_SEQUENCE) {
- timestamp_sequence = MAX(timestamp_sequence, req->op.seq_num.seq_num);
+
+ ret = partition_request(data->partitions[i]->module, treq);
+ if (ret != LDB_SUCCESS) {
+ talloc_free(res);
+ return ret;
+ }
+ ret = ldb_wait(treq->handle, LDB_WAIT_ALL);
+ if (ret != LDB_SUCCESS) {
+ talloc_free(res);
+ return ret;
+ }
+ tseqr = talloc_get_type(res->extended->data,
+ struct ldb_seqnum_result);
+ if (tseqr->flags & LDB_SEQ_TIMESTAMP_SEQUENCE) {
+ timestamp_sequence = MAX(timestamp_sequence,
+ tseqr->seq_num);
} else {
- seq_number = seq_number + req->op.seq_num.seq_num;
+ seq_number += tseqr->seq_num;
}
+ talloc_free(res);
}
- /* fall though */
+ /* fall through */
case LDB_SEQ_HIGHEST_TIMESTAMP:
- {
- struct ldb_request *date_req = talloc(req, struct ldb_request);
- if (!date_req) {
+
+ res = talloc_zero(req, struct ldb_result);
+ if (res == NULL) {
return LDB_ERR_OPERATIONS_ERROR;
}
- *date_req = *req;
- date_req->op.seq_num.flags = LDB_SEQ_HIGHEST_TIMESTAMP;
- ret = ldb_next_request(module, date_req);
+ tseq = talloc_zero(res, struct ldb_seqnum_request);
+ if (tseq == NULL) {
+ talloc_free(res);
+ return LDB_ERR_OPERATIONS_ERROR;
+ }
+ tseq->type = LDB_SEQ_HIGHEST_TIMESTAMP;
+
+ ret = ldb_build_extended_req(&treq, module->ldb, res,
+ LDB_EXTENDED_SEQUENCE_NUMBER,
+ tseq,
+ NULL,
+ res,
+ ldb_extended_default_callback,
+ NULL);
if (ret != LDB_SUCCESS) {
+ talloc_free(res);
return ret;
}
- timestamp = date_req->op.seq_num.seq_num;
- /* Look at base DN */
- /* Figure out which partition it is under */
+ ret = ldb_next_request(module, treq);
+ if (ret != LDB_SUCCESS) {
+ talloc_free(res);
+ return ret;
+ }
+ ret = ldb_wait(treq->handle, LDB_WAIT_ALL);
+ if (ret != LDB_SUCCESS) {
+ talloc_free(res);
+ return ret;
+ }
+
+ tseqr = talloc_get_type(res->extended->data,
+ struct ldb_seqnum_result);
+ timestamp = tseqr->seq_num;
+
+ talloc_free(res);
+
/* Skip the lot if 'data' isn't here yet (initialistion) */
for (i=0; data && data->partitions && data->partitions[i]; i++) {
- ret = partition_request(data->partitions[i]->module, req);
+ res = talloc_zero(req, struct ldb_result);
+ if (res == NULL) {
+ return LDB_ERR_OPERATIONS_ERROR;
+ }
+
+ tseq = talloc_zero(res, struct ldb_seqnum_request);
+ if (tseq == NULL) {
+ talloc_free(res);
+ return LDB_ERR_OPERATIONS_ERROR;
+ }
+ tseq->type = LDB_SEQ_HIGHEST_TIMESTAMP;
+
+ ret = ldb_build_extended_req(&treq, module->ldb, res,
+ LDB_EXTENDED_SEQUENCE_NUMBER,
+ tseq,
+ NULL,
+ res,
+ ldb_extended_default_callback,
+ NULL);
+ if (ret != LDB_SUCCESS) {
+ talloc_free(res);
+ return ret;
+ }
+
+ ret = partition_request(data->partitions[i]->module, treq);
if (ret != LDB_SUCCESS) {
+ talloc_free(res);
return ret;
}
- timestamp = MAX(timestamp, date_req->op.seq_num.seq_num);
+ ret = ldb_wait(treq->handle, LDB_WAIT_ALL);
+ if (ret != LDB_SUCCESS) {
+ talloc_free(res);
+ return ret;
+ }
+
+ tseqr = talloc_get_type(res->extended->data,
+ struct ldb_seqnum_result);
+ timestamp = MAX(timestamp, tseqr->seq_num);
+
+ talloc_free(res);
}
+
break;
}
+
+ ext = talloc_zero(req, struct ldb_extended);
+ if (!ext) {
+ return LDB_ERR_OPERATIONS_ERROR;
}
+ seqr = talloc_zero(ext, struct ldb_seqnum_result);
+ if (seqr == NULL) {
+ talloc_free(ext);
+ return LDB_ERR_OPERATIONS_ERROR;
+ }
+ ext->oid = LDB_EXTENDED_SEQUENCE_NUMBER;
+ ext->data = seqr;
- switch (req->op.seq_num.flags) {
+ switch (seq->type) {
case LDB_SEQ_NEXT:
case LDB_SEQ_HIGHEST_SEQ:
- req->op.seq_num.flags = 0;
-
/* Has someone above set a timebase sequence? */
if (timestamp_sequence) {
- req->op.seq_num.seq_num = (((unsigned long long)timestamp << 24) | (seq_number & 0xFFFFFF));
+ seqr->seq_num = (((unsigned long long)timestamp << 24) | (seq_number & 0xFFFFFF));
} else {
- req->op.seq_num.seq_num = seq_number;
+ seqr->seq_num = seq_number;
}
- if (timestamp_sequence > req->op.seq_num.seq_num) {
- req->op.seq_num.seq_num = timestamp_sequence;
- req->op.seq_num.flags |= LDB_SEQ_TIMESTAMP_SEQUENCE;
+ if (timestamp_sequence > seqr->seq_num) {
+ seqr->seq_num = timestamp_sequence;
+ seqr->flags |= LDB_SEQ_TIMESTAMP_SEQUENCE;
}
- req->op.seq_num.flags |= LDB_SEQ_GLOBAL_SEQUENCE;
+ seqr->flags |= LDB_SEQ_GLOBAL_SEQUENCE;
break;
case LDB_SEQ_HIGHEST_TIMESTAMP:
- req->op.seq_num.seq_num = timestamp;
+ seqr->seq_num = timestamp;
break;
}
- switch (req->op.seq_num.flags) {
- case LDB_SEQ_NEXT:
- req->op.seq_num.seq_num++;
+ if (seq->type == LDB_SEQ_NEXT) {
+ seqr->seq_num++;
}
- return LDB_SUCCESS;
+
+ /* send request done */
+ return ldb_module_done(req, NULL, ext, LDB_SUCCESS);
}
static int partition_extended_replicated_objects(struct ldb_module *module, struct ldb_request *req)
@@ -906,6 +1029,10 @@ static int partition_extended(struct ldb_module *module, struct ldb_request *req
return ldb_next_request(module, req);
}
+ if (strcmp(req->op.extended.oid, LDB_EXTENDED_SEQUENCE_NUMBER) == 0) {
+ return partition_sequence_number(module, req);
+ }
+
if (strcmp(req->op.extended.oid, DSDB_EXTENDED_REPLICATED_OBJECTS_OID) == 0) {
return partition_extended_replicated_objects(module, req);
}
@@ -1204,7 +1331,6 @@ _PUBLIC_ const struct ldb_module_ops ldb_partition_module_ops = {
.del = partition_delete,
.rename = partition_rename,
.extended = partition_extended,
- .sequence_number = partition_sequence_number,
.start_transaction = partition_start_trans,
.end_transaction = partition_end_trans,
.del_transaction = partition_del_trans,
diff --git a/source4/dsdb/samdb/ldb_modules/simple_ldap_map.c b/source4/dsdb/samdb/ldb_modules/simple_ldap_map.c
index d15e85ad41..c353914e2c 100644
--- a/source4/dsdb/samdb/ldb_modules/simple_ldap_map.c
+++ b/source4/dsdb/samdb/ldb_modules/simple_ldap_map.c
@@ -603,10 +603,18 @@ static int nsuniqueid_init(struct ldb_module *module)
return ldb_next_init(module);
}
-static int get_seq(struct ldb_request *req,
- struct ldb_reply *ares)
+static int get_seq_callback(struct ldb_request *req,
+ struct ldb_reply *ares)
{
unsigned long long *seq = (unsigned long long *)req->context;
+
+ if (!ares) {
+ return ldb_request_done(req, LDB_ERR_OPERATIONS_ERROR);
+ }
+ if (ares->error != LDB_SUCCESS) {
+ return ldb_request_done(req, ares->error);
+ }
+
if (ares->type == LDB_REPLY_ENTRY) {
struct ldb_message_element *el = ldb_msg_find_element(ares->message, "contextCSN");
if (el) {
@@ -618,6 +626,7 @@ static int get_seq(struct ldb_request *req,
return ldb_request_done(req, LDB_SUCCESS);
}
+ talloc_free(ares);
return LDB_SUCCESS;
}
@@ -626,7 +635,7 @@ static int entryuuid_sequence_number(struct ldb_module *module, struct ldb_reque
int ret;
struct map_private *map_private;
struct entryuuid_private *entryuuid_private;
- unsigned long long seq = 0;
+ unsigned long long seq_num = 0;
struct ldb_request *search_req;
const struct ldb_control *partition_ctrl;
@@ -636,6 +645,12 @@ static int entryuuid_sequence_number(struct ldb_module *module, struct ldb_reque
"contextCSN", NULL
};
+ struct ldb_seqnum_request *seq;
+ struct ldb_seqnum_result *seqr;
+ struct ldb_extended *ext;
+
+ seq = talloc_get_type(req->op.extended.data, struct ldb_seqnum_request);
+
map_private = talloc_get_type(module->private_data, struct map_private);
entryuuid_private = talloc_get_type(map_private->caller_private, struct entryuuid_private);
@@ -655,7 +670,7 @@ static int entryuuid_sequence_number(struct ldb_module *module, struct ldb_reque
ret = ldb_build_search_req(&search_req, module->ldb, req,
partition->dn, LDB_SCOPE_BASE,
NULL, contextCSN_attr, NULL,
- &seq, get_seq,
+ &seq_num, get_seq_callback,
NULL);
if (ret != LDB_SUCCESS) {
return ret;
@@ -672,36 +687,59 @@ static int entryuuid_sequence_number(struct ldb_module *module, struct ldb_reque
return ret;
}
- switch (req->op.seq_num.type) {
+ ext = talloc_zero(req, struct ldb_extended);
+ if (!ext) {
+ return LDB_ERR_OPERATIONS_ERROR;
+ }
+ seqr = talloc_zero(req, struct ldb_seqnum_result);
+ if (seqr == NULL) {
+ talloc_free(ext);
+ return LDB_ERR_OPERATIONS_ERROR;
+ }
+ ext->oid = LDB_EXTENDED_SEQUENCE_NUMBER;
+ ext->data = seqr;
+
+ switch (seq->type) {
case LDB_SEQ_HIGHEST_SEQ:
- req->op.seq_num.seq_num = seq;
+ seqr->seq_num = seq_num;
break;
case LDB_SEQ_NEXT:
- req->op.seq_num.seq_num = seq;
- req->op.seq_num.seq_num++;
+ seqr->seq_num = seq_num;
+ seqr->seq_num++;
break;
case LDB_SEQ_HIGHEST_TIMESTAMP:
{
- req->op.seq_num.seq_num = (seq >> 24);
+ seqr->seq_num = (seq_num >> 24);
break;
}
}
- req->op.seq_num.flags = 0;
- req->op.seq_num.flags |= LDB_SEQ_TIMESTAMP_SEQUENCE;
- req->op.seq_num.flags |= LDB_SEQ_GLOBAL_SEQUENCE;
- return LDB_SUCCESS;
+ seqr->flags = 0;
+ seqr->flags |= LDB_SEQ_TIMESTAMP_SEQUENCE;
+ seqr->flags |= LDB_SEQ_GLOBAL_SEQUENCE;
+
+ /* send request done */
+ return ldb_module_done(req, NULL, ext, LDB_SUCCESS);
+}
+
+static int entryuuid_extended(struct ldb_module *module, struct ldb_request *req)
+{
+ if (strcmp(req->op.extended.oid, LDB_EXTENDED_SEQUENCE_NUMBER) == 0) {
+ return entryuuid_sequence_number(module, req);
+ }
+
+ return ldb_next_request(module, req);
}
_PUBLIC_ const struct ldb_module_ops ldb_entryuuid_module_ops = {
.name = "entryuuid",
.init_context = entryuuid_init,
- .sequence_number = entryuuid_sequence_number,
+ .extended = entryuuid_extended,
LDB_MAP_OPS
};
_PUBLIC_ const struct ldb_module_ops ldb_nsuniqueid_module_ops = {
.name = "nsuniqueid",
.init_context = nsuniqueid_init,
- .sequence_number = entryuuid_sequence_number,
+ .extended = entryuuid_extended,
LDB_MAP_OPS
};
diff --git a/source4/lib/ldb/common/ldb.c b/source4/lib/ldb/common/ldb.c
index 75c8109042..c013565da0 100644
--- a/source4/lib/ldb/common/ldb.c
+++ b/source4/lib/ldb/common/ldb.c
@@ -527,10 +527,6 @@ int ldb_request(struct ldb_context *ldb, struct ldb_request *req)
FIRST_OP(ldb, extended);
ret = module->ops->extended(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);
@@ -1172,35 +1168,47 @@ int ldb_rename(struct ldb_context *ldb,
int ldb_sequence_number(struct ldb_context *ldb,
enum ldb_sequence_type type, uint64_t *seq_num)
{
- struct ldb_request *req;
+ struct ldb_seqnum_request *seq;
+ struct ldb_seqnum_result *seqr;
+ struct ldb_result *res;
+ TALLOC_CTX *tmp_ctx;
int ret;
- req = talloc_zero(ldb, struct ldb_request);
- if (req == NULL) {
+ *seq_num = 0;
+
+ tmp_ctx = talloc_zero(ldb, struct ldb_request);
+ if (tmp_ctx == NULL) {
ldb_set_errstring(ldb, "Out of Memory");
return LDB_ERR_OPERATIONS_ERROR;
}
+ seq = talloc_zero(tmp_ctx, struct ldb_seqnum_request);
+ if (seq == NULL) {
+ ldb_set_errstring(ldb, "Out of Memory");
+ ret = LDB_ERR_OPERATIONS_ERROR;
+ goto done;
+ }
+ seq->type = type;
- req->operation = LDB_SEQUENCE_NUMBER;
- req->controls = NULL;
- req->context = NULL;
- req->callback = ldb_op_default_callback;
- ldb_set_timeout(ldb, req, 0); /* use default timeout */
-
- req->op.seq_num.type = type;
- /* do request and autostart a transaction */
- ret = ldb_request(ldb, req);
+ ret = ldb_extended(ldb, LDB_EXTENDED_SEQUENCE_NUMBER, seq, &res);
+ if (ret != LDB_SUCCESS) {
+ goto done;
+ }
+ talloc_steal(tmp_ctx, res);
- if (ret == LDB_SUCCESS) {
- *seq_num = req->op.seq_num.seq_num;
+ if (strcmp(LDB_EXTENDED_SEQUENCE_NUMBER, res->extended->oid) != 0) {
+ ldb_set_errstring(ldb, "Invalid OID in reply");
+ ret = LDB_ERR_OPERATIONS_ERROR;
+ goto done;
}
+ seqr = talloc_get_type(res->extended->data,
+ struct ldb_seqnum_result);
+ *seq_num = seqr->seq_num;
- talloc_free(req);
+done:
+ talloc_free(tmp_ctx);
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 5cc8de29b4..2b453bb0c3 100644
--- a/source4/lib/ldb/common/ldb_modules.c
+++ b/source4/lib/ldb/common/ldb_modules.c
@@ -517,10 +517,6 @@ int ldb_next_request(struct ldb_module *module, struct ldb_request *request)
FIND_OP(module, extended);
ret = module->ops->extended(module, request);
break;
- case LDB_SEQUENCE_NUMBER:
- FIND_OP(module, sequence_number);
- ret = module->ops->sequence_number(module, request);
- break;
default:
FIND_OP(module, request);
ret = module->ops->request(module, request);
diff --git a/source4/lib/ldb/include/ldb.h b/source4/lib/ldb/include/ldb.h
index b1ce3ef70b..9bc5c183d8 100644
--- a/source4/lib/ldb/include/ldb.h
+++ b/source4/lib/ldb/include/ldb.h
@@ -652,7 +652,6 @@ enum ldb_request_type {
LDB_DELETE,
LDB_RENAME,
LDB_EXTENDED,
- LDB_SEQUENCE_NUMBER,
LDB_REQ_REGISTER_CONTROL,
LDB_REQ_REGISTER_PARTITION
};
@@ -679,21 +678,38 @@ struct ldb_extended {
void *data; /* NULL or a valid talloc pointer! talloc_get_type() will be used on it */
};
+#define LDB_EXTENDED_SEQUENCE_NUMBER "1.3.6.1.4.1.7165.4.4.3"
+
+enum ldb_sequence_type {
+ LDB_SEQ_HIGHEST_SEQ,
+ LDB_SEQ_HIGHEST_TIMESTAMP,
+ LDB_SEQ_NEXT
+};
+
+struct ldb_seqnum_request {
+ enum ldb_sequence_type type;
+};
+
+struct ldb_seqnum_result {
+ uint64_t seq_num;
+ uint32_t flags;
+};
+
struct ldb_result {
unsigned int count;
struct ldb_message **msgs;
- char **refs;
struct ldb_extended *extended;
struct ldb_control **controls;
+ char **refs;
};
struct ldb_reply {
+ int error;
enum ldb_reply_type type;
struct ldb_message *message;
struct ldb_extended *response;
- char *referral;
struct ldb_control **controls;
- int error;
+ char *referral;
};
struct ldb_request;
@@ -732,18 +748,6 @@ struct ldb_register_partition {
struct ldb_dn *dn;
};
-enum ldb_sequence_type {
- LDB_SEQ_HIGHEST_SEQ,
- LDB_SEQ_HIGHEST_TIMESTAMP,
- LDB_SEQ_NEXT
-};
-
-struct ldb_sequence_number {
- enum ldb_sequence_type type;
- uint64_t seq_num;
- uint32_t flags;
-};
-
typedef int (*ldb_request_callback_t)(struct ldb_request *, struct ldb_reply *);
struct ldb_request {
@@ -757,7 +761,6 @@ struct ldb_request {
struct ldb_delete del;
struct ldb_rename rename;
struct ldb_extended extended;
- struct ldb_sequence_number seq_num;
struct ldb_register_control reg_control;
struct ldb_register_partition reg_partition;
} op;
diff --git a/source4/lib/ldb/ldb.i b/source4/lib/ldb/ldb.i
index 024ba1959a..6013462225 100644
--- a/source4/lib/ldb/ldb.i
+++ b/source4/lib/ldb/ldb.i
@@ -1219,25 +1219,6 @@ int py_module_del_transaction(struct ldb_module *mod)
return LDB_SUCCESS;
}
-int py_module_sequence_number(struct ldb_module *mod, struct ldb_request *req)
-{
- PyObject *py_ldb = mod->private_data;
- PyObject *py_result;
- int ret;
-
- py_result = PyObject_CallMethod(py_ldb, "sequence_number", "ili", req->op.seq_num.type, req->op.seq_num.seq_num, req->op.seq_num.flags);
-
- if (py_result == NULL) {
- return LDB_ERR_OPERATIONS_ERROR;
- }
-
- ret = PyInt_AsLong(py_result);
-
- Py_DECREF(py_result);
-
- return ret;
-}
-
static int py_module_destructor(void *_mod)
{
struct ldb_module *mod = _mod;
@@ -1292,7 +1273,6 @@ int py_module_init (struct ldb_module *mod)
$1->start_transaction = py_module_start_transaction;
$1->end_transaction = py_module_end_transaction;
$1->del_transaction = py_module_del_transaction;
- $1->sequence_number = py_module_sequence_number;
}
%feature("docstring") ldb_register_module "S.register_module(module) -> None\n"
diff --git a/source4/lib/ldb/ldb_tdb/ldb_search.c b/source4/lib/ldb/ldb_tdb/ldb_search.c
index a220b4a628..1c76411db2 100644
--- a/source4/lib/ldb/ldb_tdb/ldb_search.c
+++ b/source4/lib/ldb/ldb_tdb/ldb_search.c
@@ -277,30 +277,6 @@ int ltdb_search_dn1(struct ldb_module *module, struct ldb_dn *dn, struct ldb_mes
}
/*
- lock the database for read - use by ltdb_search
-*/
-static int ltdb_lock_read(struct ldb_module *module)
-{
- struct ltdb_private *ltdb = (struct ltdb_private *)module->private_data;
- if (ltdb->in_transaction == 0) {
- return tdb_lockall_read(ltdb->tdb);
- }
- return 0;
-}
-
-/*
- unlock the database after a ltdb_lock_read()
-*/
-static int ltdb_unlock_read(struct ldb_module *module)
-{
- struct ltdb_private *ltdb = (struct ltdb_private *)module->private_data;
- if (ltdb->in_transaction == 0) {
- return tdb_unlockall_read(ltdb->tdb);
- }
- return 0;
-}
-
-/*
add a set of attributes from a record to a set of results
return 0 on success, -1 on failure
*/
diff --git a/source4/lib/ldb/ldb_tdb/ldb_tdb.c b/source4/lib/ldb/ldb_tdb/ldb_tdb.c
index 0087f6c44d..2282f61d47 100644
--- a/source4/lib/ldb/ldb_tdb/ldb_tdb.c
+++ b/source4/lib/ldb/ldb_tdb/ldb_tdb.c
@@ -79,6 +79,30 @@ static int ltdb_err_map(enum TDB_ERROR tdb_code)
return LDB_ERR_OTHER;
}
+/*
+ lock the database for read - use by ltdb_search and ltdb_sequence_number
+*/
+int ltdb_lock_read(struct ldb_module *module)
+{
+ struct ltdb_private *ltdb = (struct ltdb_private *)module->private_data;
+ if (ltdb->in_transaction == 0) {
+ return tdb_lockall_read(ltdb->tdb);
+ }
+ return 0;
+}
+
+/*
+ unlock the database after a ltdb_lock_read()
+*/
+int ltdb_unlock_read(struct ldb_module *module)
+{
+ struct ltdb_private *ltdb = (struct ltdb_private *)module->private_data;
+ if (ltdb->in_transaction == 0) {
+ return tdb_unlockall_read(ltdb->tdb);
+ }
+ return 0;
+}
+
/*
form a TDB_DATA for a record key
@@ -860,61 +884,88 @@ static int ltdb_del_trans(struct ldb_module *module)
/*
return sequenceNumber from @BASEINFO
*/
-static int ltdb_sequence_number(struct ldb_module *module,
- struct ldb_request *req)
+static int ltdb_sequence_number(struct ltdb_context *ctx,
+ struct ldb_extended **ext)
{
+ struct ldb_module *module = ctx->module;
+ struct ldb_request *req = ctx->req;
TALLOC_CTX *tmp_ctx;
+ struct ldb_seqnum_request *seq;
+ struct ldb_seqnum_result *res;
struct ldb_message *msg = NULL;
struct ldb_dn *dn;
const char *date;
- int tret;
+ int ret;
+ seq = talloc_get_type(req->op.extended.data,
+ struct ldb_seqnum_request);
+ if (seq == NULL) {
+ return LDB_ERR_OPERATIONS_ERROR;
+ }
+
+ req->handle->state = LDB_ASYNC_PENDING;
+
+ if (ltdb_lock_read(module) != 0) {
+ return LDB_ERR_OPERATIONS_ERROR;
+ }
+
+ res = talloc_zero(req, struct ldb_seqnum_result);
+ if (res == NULL) {
+ ret = LDB_ERR_OPERATIONS_ERROR;
+ goto done;
+ }
tmp_ctx = talloc_new(req);
if (tmp_ctx == NULL) {
- talloc_free(tmp_ctx);
- return LDB_ERR_OPERATIONS_ERROR;
+ ret = LDB_ERR_OPERATIONS_ERROR;
+ goto done;
}
dn = ldb_dn_new(tmp_ctx, module->ldb, LTDB_BASEINFO);
msg = talloc(tmp_ctx, struct ldb_message);
if (msg == NULL) {
- talloc_free(tmp_ctx);
- return LDB_ERR_OPERATIONS_ERROR;
+ ret = LDB_ERR_OPERATIONS_ERROR;
+ goto done;
}
- req->op.seq_num.flags = 0;
-
- tret = ltdb_search_dn1(module, dn, msg);
- if (tret != LDB_SUCCESS) {
- talloc_free(tmp_ctx);
- /* zero is as good as anything when we don't know */
- req->op.seq_num.seq_num = 0;
- return tret;
+ ret = ltdb_search_dn1(module, dn, msg);
+ if (ret != LDB_SUCCESS) {
+ goto done;
}
- switch (req->op.seq_num.type) {
+ switch (seq->type) {
case LDB_SEQ_HIGHEST_SEQ:
- req->op.seq_num.seq_num = ldb_msg_find_attr_as_uint64(msg, LTDB_SEQUENCE_NUMBER, 0);
+ res->seq_num = ldb_msg_find_attr_as_uint64(msg, LTDB_SEQUENCE_NUMBER, 0);
break;
case LDB_SEQ_NEXT:
- req->op.seq_num.seq_num = ldb_msg_find_attr_as_uint64(msg, LTDB_SEQUENCE_NUMBER, 0);
- req->op.seq_num.seq_num++;
+ res->seq_num = ldb_msg_find_attr_as_uint64(msg, LTDB_SEQUENCE_NUMBER, 0);
+ res->seq_num++;
break;
case LDB_SEQ_HIGHEST_TIMESTAMP:
date = ldb_msg_find_attr_as_string(msg, LTDB_MOD_TIMESTAMP, NULL);
if (date) {
- req->op.seq_num.seq_num = ldb_string_to_time(date);
+ res->seq_num = ldb_string_to_time(date);
} else {
- req->op.seq_num.seq_num = 0;
+ res->seq_num = 0;
/* zero is as good as anything when we don't know */
}
break;
}
- talloc_free(tmp_ctx);
+ *ext = talloc_zero(req, struct ldb_extended);
+ if (*ext == NULL) {
+ ret = LDB_ERR_OPERATIONS_ERROR;
+ goto done;
+ }
+ (*ext)->oid = LDB_EXTENDED_SEQUENCE_NUMBER;
+ (*ext)->data = talloc_steal(*ext, res);
- return LDB_SUCCESS;
+ ret = LDB_SUCCESS;
+
+done:
+ talloc_free(tmp_ctx);
+ ltdb_unlock_read(module);
+ return ret;
}
void ltdb_request_done(struct ldb_request *req, int error)
@@ -949,6 +1000,47 @@ static void ltdb_timeout(struct event_context *ev,
ltdb_request_done(ctx->req, LDB_ERR_TIME_LIMIT_EXCEEDED);
}
+static void ltdb_request_extended_done(struct ldb_request *req,
+ struct ldb_extended *ext,
+ int error)
+{
+ struct ldb_reply *ares;
+
+ /* if we already returned an error just return */
+ if (req->handle->status != LDB_SUCCESS) {
+ return;
+ }
+
+ ares = talloc_zero(req, struct ldb_reply);
+ if (!ares) {
+ ldb_oom(req->handle->ldb);
+ req->callback(req, NULL);
+ return;
+ }
+ ares->type = LDB_REPLY_DONE;
+ ares->response = ext;
+ ares->error = error;
+
+ req->callback(req, ares);
+}
+
+static void ltdb_handle_extended(struct ltdb_context *ctx)
+{
+ struct ldb_extended *ext = NULL;
+ int ret;
+
+ if (strcmp(ctx->req->op.extended.oid,
+ LDB_EXTENDED_SEQUENCE_NUMBER) == 0) {
+ /* get sequence number */
+ ret = ltdb_sequence_number(ctx, &ext);
+ } else {
+ /* not recognized */
+ ret = LDB_ERR_UNSUPPORTED_CRITICAL_EXTENSION;
+ }
+
+ ltdb_request_extended_done(ctx->req, ext, ret);
+}
+
static void ltdb_callback(struct event_context *ev,
struct timed_event *te,
struct timeval t,
@@ -975,6 +1067,9 @@ static void ltdb_callback(struct event_context *ev,
case LDB_RENAME:
ret = ltdb_rename(ctx);
break;
+ case LDB_EXTENDED:
+ ltdb_handle_extended(ctx);
+ return;
default:
/* no other op supported */
ret = LDB_ERR_UNWILLING_TO_PERFORM;
@@ -1037,11 +1132,10 @@ static const struct ldb_module_ops ltdb_ops = {
.modify = ltdb_handle_request,
.del = ltdb_handle_request,
.rename = ltdb_handle_request,
-/* .request = ltdb_handle_request, */
+ .extended = ltdb_handle_request,
.start_transaction = ltdb_start_trans,
.end_transaction = ltdb_end_trans,
.del_transaction = ltdb_del_trans,
- .sequence_number = ltdb_sequence_number
};
/*
diff --git a/source4/lib/ldb/ldb_tdb/ldb_tdb.h b/source4/lib/ldb/ldb_tdb/ldb_tdb.h
index 223181ca0b..61e90bccc6 100644
--- a/source4/lib/ldb/ldb_tdb/ldb_tdb.h
+++ b/source4/lib/ldb/ldb_tdb/ldb_tdb.h
@@ -112,6 +112,8 @@ int ltdb_filter_attrs(struct ldb_message *msg, const char * const *attrs);
int ltdb_search(struct ltdb_context *ctx);
/* The following definitions come from lib/ldb/ldb_tdb/ldb_tdb.c */
+int ltdb_lock_read(struct ldb_module *module);
+int ltdb_unlock_read(struct ldb_module *module);
struct TDB_DATA ltdb_key(struct ldb_module *module, struct ldb_dn *dn);
int ltdb_store(struct ldb_module *module, const struct ldb_message *msg, int flgs);
int ltdb_delete_noindex(struct ldb_module *module, struct ldb_dn *dn);
diff --git a/source4/lib/ldb/ldb_wrap.c b/source4/lib/ldb/ldb_wrap.c
index cc8099f27f..bc9266a306 100644
--- a/source4/lib/ldb/ldb_wrap.c
+++ b/source4/lib/ldb/ldb_wrap.c
@@ -3505,25 +3505,6 @@ int py_module_del_transaction(struct ldb_module *mod)
return LDB_SUCCESS;
}
-int py_module_sequence_number(struct ldb_module *mod, struct ldb_request *req)
-{
- PyObject *py_ldb = mod->private_data;
- PyObject *py_result;
- int ret;
-
- py_result = PyObject_CallMethod(py_ldb, "sequence_number", "ili", req->op.seq_num.type, req->op.seq_num.seq_num, req->op.seq_num.flags);
-
- if (py_result == NULL) {
- return LDB_ERR_OPERATIONS_ERROR;
- }
-
- ret = PyInt_AsLong(py_result);
-
- Py_DECREF(py_result);
-
- return ret;
-}
-
static int py_module_destructor(void *_mod)
{
struct ldb_module *mod = _mod;
@@ -6648,7 +6629,6 @@ SWIGINTERN PyObject *_wrap_register_module(PyObject *SWIGUNUSEDPARM(self), PyObj
arg1->start_transaction = py_module_start_transaction;
arg1->end_transaction = py_module_end_transaction;
arg1->del_transaction = py_module_del_transaction;
- arg1->sequence_number = py_module_sequence_number;
result = ldb_register_module((struct ldb_module_ops const *)arg1);
if (result != 0) {
PyErr_SetObject(PyExc_LdbError, Py_BuildValue((char *)"(i,s)", result, ldb_strerror(result)));
diff --git a/source4/setup/schema_samba4.ldif b/source4/setup/schema_samba4.ldif
index 2c007395fb..c27157d713 100644
--- a/source4/setup/schema_samba4.ldif
+++ b/source4/setup/schema_samba4.ldif
@@ -177,6 +177,8 @@ oMSyntax: 20
#Allocated: DSDB_CONTROL_REPLICATED_UPDATE_OID 1.3.6.1.4.1.7165.4.3.3
#Allocated: DSDB_EXTENDED_REPLICATED_OBJECTS_OID 1.3.6.1.4.1.7165.4.4.1
+#Allocated: DSDB_EXTENDED_SCHEMA_UPDATE_NOW_OID 1.3.6.1.4.1.7165.4.4.2
+#Allocated: LDB_EXTENDED_SEQUENCE_NUMBER 1.3.6.1.4.1.7165.4.4.3
#Allocated: (middleName) attributeID: 1.3.6.1.4.1.7165.4.255.1