4 LDAP semantics mapping module
6 Copyright (C) Jelmer Vernooij 2005
7 Copyright (C) Andrew Bartlett <abartlet@samba.org> 2006
9 This program is free software; you can redistribute it and/or modify
10 it under the terms of the GNU General Public License as published by
11 the Free Software Foundation; either version 2 of the License, or
12 (at your option) any later version.
14 This program is distributed in the hope that it will be useful,
15 but WITHOUT ANY WARRANTY; without even the implied warranty of
16 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17 GNU General Public License for more details.
19 You should have received a copy of the GNU General Public License
20 along with this program; if not, write to the Free Software
21 Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
25 This module relies on ldb_map to do all the real work, but performs
26 some of the trivial mappings between AD semantics and that provided
27 by OpenLDAP and similar servers.
31 #include "ldb/include/ldb.h"
32 #include "ldb/include/ldb_private.h"
33 #include "ldb/include/ldb_errors.h"
34 #include "ldb/modules/ldb_map.h"
36 #include "librpc/gen_ndr/ndr_misc.h"
37 #include "librpc/ndr/libndr.h"
39 struct entryUUID_private
{
40 struct ldb_result
*objectclass_res
;
41 struct ldb_dn
**base_dns
;
44 static struct ldb_val
encode_guid(struct ldb_module
*module
, TALLOC_CTX
*ctx
, const struct ldb_val
*val
)
47 NTSTATUS status
= GUID_from_string((char *)val
->data
, &guid
);
48 struct ldb_val out
= data_blob(NULL
, 0);
50 if (!NT_STATUS_IS_OK(status
)) {
53 status
= ndr_push_struct_blob(&out
, ctx
, &guid
,
54 (ndr_push_flags_fn_t
)ndr_push_GUID
);
55 if (!NT_STATUS_IS_OK(status
)) {
62 static struct ldb_val
guid_always_string(struct ldb_module
*module
, TALLOC_CTX
*ctx
, const struct ldb_val
*val
)
66 struct ldb_val out
= data_blob(NULL
, 0);
67 if (val
->length
>= 32 && val
->data
[val
->length
] == '\0') {
68 ldb_handler_copy(module
->ldb
, ctx
, val
, &out
);
70 guid
= talloc(ctx
, struct GUID
);
74 status
= ndr_pull_struct_blob(val
, guid
, guid
,
75 (ndr_pull_flags_fn_t
)ndr_pull_GUID
);
76 if (!NT_STATUS_IS_OK(status
)) {
80 out
= data_blob_string_const(GUID_string(ctx
, guid
));
86 static struct ldb_val
encode_ns_guid(struct ldb_module
*module
, TALLOC_CTX
*ctx
, const struct ldb_val
*val
)
89 NTSTATUS status
= NS_GUID_from_string((char *)val
->data
, &guid
);
90 struct ldb_val out
= data_blob(NULL
, 0);
92 if (!NT_STATUS_IS_OK(status
)) {
95 status
= ndr_push_struct_blob(&out
, ctx
, &guid
,
96 (ndr_push_flags_fn_t
)ndr_push_GUID
);
97 if (!NT_STATUS_IS_OK(status
)) {
104 static struct ldb_val
guid_ns_string(struct ldb_module
*module
, TALLOC_CTX
*ctx
, const struct ldb_val
*val
)
107 struct ldb_val out
= data_blob(NULL
, 0);
108 if (val
->length
>= 32 && val
->data
[val
->length
] == '\0') {
110 GUID_from_string((char *)val
->data
, &guid
);
111 out
= data_blob_string_const(NS_GUID_string(ctx
, &guid
));
114 guid_p
= talloc(ctx
, struct GUID
);
115 if (guid_p
== NULL
) {
118 status
= ndr_pull_struct_blob(val
, guid_p
, guid_p
,
119 (ndr_pull_flags_fn_t
)ndr_pull_GUID
);
120 if (!NT_STATUS_IS_OK(status
)) {
124 out
= data_blob_string_const(NS_GUID_string(ctx
, guid_p
));
130 /* The backend holds binary sids, so just copy them back */
131 static struct ldb_val
val_copy(struct ldb_module
*module
, TALLOC_CTX
*ctx
, const struct ldb_val
*val
)
133 struct ldb_val out
= data_blob(NULL
, 0);
134 ldb_handler_copy(module
->ldb
, ctx
, val
, &out
);
139 /* Ensure we always convert sids into binary, so the backend doesn't have to know about both forms */
140 static struct ldb_val
sid_always_binary(struct ldb_module
*module
, TALLOC_CTX
*ctx
, const struct ldb_val
*val
)
142 struct ldb_val out
= data_blob(NULL
, 0);
143 const struct ldb_schema_attribute
*a
= ldb_schema_attribute_by_name(module
->ldb
, "objectSid");
145 if (a
->syntax
->canonicalise_fn(module
->ldb
, ctx
, val
, &out
) != LDB_SUCCESS
) {
146 return data_blob(NULL
, 0);
152 static struct ldb_val
objectCategory_always_dn(struct ldb_module
*module
, TALLOC_CTX
*ctx
, const struct ldb_val
*val
)
155 struct map_private
*map_private
;
156 struct entryUUID_private
*entryUUID_private
;
157 struct ldb_result
*list
;
159 if (ldb_dn_validate(ldb_dn_new(ctx
, module
->ldb
, (const char *)val
->data
))) {
162 map_private
= talloc_get_type(module
->private_data
, struct map_private
);
164 entryUUID_private
= talloc_get_type(map_private
->caller_private
, struct entryUUID_private
);
165 list
= entryUUID_private
->objectclass_res
;
167 for (i
=0; list
&& (i
< list
->count
); i
++) {
168 if (ldb_attr_cmp((const char *)val
->data
, ldb_msg_find_attr_as_string(list
->msgs
[i
], "lDAPDisplayName", NULL
)) == 0) {
169 char *dn
= ldb_dn_alloc_linearized(ctx
, list
->msgs
[i
]->dn
);
170 return data_blob_string_const(dn
);
176 static struct ldb_val
class_to_oid(struct ldb_module
*module
, TALLOC_CTX
*ctx
, const struct ldb_val
*val
)
179 struct map_private
*map_private
;
180 struct entryUUID_private
*entryUUID_private
;
181 struct ldb_result
*list
;
183 map_private
= talloc_get_type(module
->private_data
, struct map_private
);
185 entryUUID_private
= talloc_get_type(map_private
->caller_private
, struct entryUUID_private
);
186 list
= entryUUID_private
->objectclass_res
;
188 for (i
=0; list
&& (i
< list
->count
); i
++) {
189 if (ldb_attr_cmp((const char *)val
->data
, ldb_msg_find_attr_as_string(list
->msgs
[i
], "lDAPDisplayName", NULL
)) == 0) {
190 const char *oid
= ldb_msg_find_attr_as_string(list
->msgs
[i
], "governsID", NULL
);
191 return data_blob_string_const(oid
);
197 static struct ldb_val
class_from_oid(struct ldb_module
*module
, TALLOC_CTX
*ctx
, const struct ldb_val
*val
)
200 struct map_private
*map_private
;
201 struct entryUUID_private
*entryUUID_private
;
202 struct ldb_result
*list
;
204 map_private
= talloc_get_type(module
->private_data
, struct map_private
);
206 entryUUID_private
= talloc_get_type(map_private
->caller_private
, struct entryUUID_private
);
207 list
= entryUUID_private
->objectclass_res
;
209 for (i
=0; list
&& (i
< list
->count
); i
++) {
210 if (ldb_attr_cmp((const char *)val
->data
, ldb_msg_find_attr_as_string(list
->msgs
[i
], "governsID", NULL
)) == 0) {
211 const char *oc
= ldb_msg_find_attr_as_string(list
->msgs
[i
], "lDAPDisplayName", NULL
);
212 return data_blob_string_const(oc
);
219 static struct ldb_val
normalise_to_signed32(struct ldb_module
*module
, TALLOC_CTX
*ctx
, const struct ldb_val
*val
)
221 long long int signed_ll
= strtoll((const char *)val
->data
, NULL
, 10);
222 if (signed_ll
>= 0x80000000LL
) {
225 uint32_t unsigned_int
;
227 .unsigned_int
= strtoul((const char *)val
->data
, NULL
, 10)
230 struct ldb_val out
= data_blob_string_const(talloc_asprintf(ctx
, "%d", u
.signed_int
));
233 return val_copy(module
, ctx
, val
);
236 static struct ldb_val
usn_to_entryCSN(struct ldb_module
*module
, TALLOC_CTX
*ctx
, const struct ldb_val
*val
)
239 unsigned long long usn
= strtoull((const char *)val
->data
, NULL
, 10);
240 time_t t
= (usn
>> 24);
241 out
= data_blob_string_const(talloc_asprintf(ctx
, "%s#%06x#00#000000", ldb_timestring(ctx
, t
), (unsigned int)(usn
& 0xFFFFFF)));
245 static unsigned long long entryCSN_to_usn_int(TALLOC_CTX
*ctx
, const struct ldb_val
*val
)
247 char *entryCSN
= talloc_strdup(ctx
, (const char *)val
->data
);
250 unsigned long long usn
;
255 p
= strchr(entryCSN
, '#');
270 usn
= strtol(mod_per_sec
, NULL
, 16);
272 t
= ldb_string_to_time(entryCSN
);
274 usn
= usn
| ((unsigned long long)t
<<24);
278 static struct ldb_val
entryCSN_to_usn(struct ldb_module
*module
, TALLOC_CTX
*ctx
, const struct ldb_val
*val
)
281 unsigned long long usn
= entryCSN_to_usn_int(ctx
, val
);
282 out
= data_blob_string_const(talloc_asprintf(ctx
, "%lld", usn
));
286 static struct ldb_val
usn_to_timestamp(struct ldb_module
*module
, TALLOC_CTX
*ctx
, const struct ldb_val
*val
)
289 unsigned long long usn
= strtoull((const char *)val
->data
, NULL
, 10);
290 time_t t
= (usn
>> 24);
291 out
= data_blob_string_const(ldb_timestring(ctx
, t
));
295 static struct ldb_val
timestamp_to_usn(struct ldb_module
*module
, TALLOC_CTX
*ctx
, const struct ldb_val
*val
)
299 unsigned long long usn
;
301 t
= ldb_string_to_time((const char *)val
->data
);
303 usn
= ((unsigned long long)t
<<24);
305 out
= data_blob_string_const(talloc_asprintf(ctx
, "%lld", usn
));
310 const struct ldb_map_attribute entryUUID_attributes
[] =
314 .local_name
= "objectGUID",
318 .remote_name
= "entryUUID",
319 .convert_local
= guid_always_string
,
320 .convert_remote
= encode_guid
,
326 .local_name
= "objectSid",
330 .remote_name
= "objectSid",
331 .convert_local
= sid_always_binary
,
332 .convert_remote
= val_copy
,
337 .local_name
= "whenCreated",
341 .remote_name
= "createTimestamp"
346 .local_name
= "whenChanged",
350 .remote_name
= "modifyTimestamp"
355 .local_name
= "objectClasses",
359 .remote_name
= "samba4ObjectClasses"
364 .local_name
= "dITContentRules",
368 .remote_name
= "samba4DITContentRules"
373 .local_name
= "attributeTypes",
377 .remote_name
= "samba4AttributeTypes"
382 .local_name
= "sambaPassword",
386 .remote_name
= "userPassword"
392 .local_name
= "allowedChildClassesEffective",
396 .remote_name
= "allowedChildClassesEffective",
397 .convert_local
= class_to_oid
,
398 .convert_remote
= class_from_oid
,
404 .local_name
= "objectCategory",
408 .remote_name
= "objectCategory",
409 .convert_local
= objectCategory_always_dn
,
410 .convert_remote
= val_copy
,
415 .local_name
= "distinguishedName",
419 .remote_name
= "entryDN"
424 .local_name
= "groupType",
428 .remote_name
= "groupType",
429 .convert_local
= normalise_to_signed32
,
430 .convert_remote
= val_copy
,
435 .local_name
= "sAMAccountType",
439 .remote_name
= "sAMAccountType",
440 .convert_local
= normalise_to_signed32
,
441 .convert_remote
= val_copy
,
446 .local_name
= "usnChanged",
450 .remote_name
= "entryCSN",
451 .convert_local
= usn_to_entryCSN
,
452 .convert_remote
= entryCSN_to_usn
457 .local_name
= "usnCreated",
461 .remote_name
= "createTimestamp",
462 .convert_local
= usn_to_timestamp
,
463 .convert_remote
= timestamp_to_usn
,
476 /* This objectClass conflicts with builtin classes on OpenLDAP */
477 const struct ldb_map_objectclass entryUUID_objectclasses
[] =
480 .local_name
= "subSchema",
481 .remote_name
= "samba4SubSchema"
488 /* These things do not show up in wildcard searches in OpenLDAP, but
489 * we need them to show up in the AD-like view */
490 const char * const entryUUID_wildcard_attributes
[] = {
499 const struct ldb_map_attribute nsuniqueid_attributes
[] =
503 .local_name
= "objectGUID",
507 .remote_name
= "nsuniqueid",
508 .convert_local
= guid_ns_string
,
509 .convert_remote
= encode_ns_guid
,
515 .local_name
= "objectSid",
519 .remote_name
= "objectSid",
520 .convert_local
= sid_always_binary
,
521 .convert_remote
= val_copy
,
526 .local_name
= "whenCreated",
530 .remote_name
= "createTimestamp"
535 .local_name
= "whenChanged",
539 .remote_name
= "modifyTimestamp"
544 .local_name
= "sambaPassword",
548 .remote_name
= "userPassword"
554 .local_name
= "allowedChildClassesEffective",
558 .remote_name
= "allowedChildClassesEffective",
559 .convert_local
= class_to_oid
,
560 .convert_remote
= class_from_oid
,
566 .local_name
= "objectCategory",
570 .remote_name
= "objectCategory",
571 .convert_local
= objectCategory_always_dn
,
572 .convert_remote
= val_copy
,
577 .local_name
= "distinguishedName",
581 .remote_name
= "entryDN"
586 .local_name
= "groupType",
590 .remote_name
= "groupType",
591 .convert_local
= normalise_to_signed32
,
592 .convert_remote
= val_copy
,
597 .local_name
= "sAMAccountType",
601 .remote_name
= "sAMAccountType",
602 .convert_local
= normalise_to_signed32
,
603 .convert_remote
= val_copy
,
608 .local_name
= "usnChanged",
612 .remote_name
= "modifyTimestamp",
613 .convert_local
= usn_to_timestamp
,
614 .convert_remote
= timestamp_to_usn
,
619 .local_name
= "usnCreated",
623 .remote_name
= "createTimestamp",
624 .convert_local
= usn_to_timestamp
,
625 .convert_remote
= timestamp_to_usn
,
638 /* These things do not show up in wildcard searches in OpenLDAP, but
639 * we need them to show up in the AD-like view */
640 const char * const nsuniqueid_wildcard_attributes
[] = {
649 static struct ldb_dn
*find_schema_dn(struct ldb_context
*ldb
, TALLOC_CTX
*mem_ctx
)
651 const char *rootdse_attrs
[] = {"schemaNamingContext", NULL
};
652 struct ldb_dn
*schema_dn
;
653 struct ldb_dn
*basedn
= ldb_dn_new(mem_ctx
, ldb
, NULL
);
654 struct ldb_result
*rootdse_res
;
660 /* Search for rootdse */
661 ldb_ret
= ldb_search(ldb
, basedn
, LDB_SCOPE_BASE
, NULL
, rootdse_attrs
, &rootdse_res
);
662 if (ldb_ret
!= LDB_SUCCESS
) {
666 talloc_steal(mem_ctx
, rootdse_res
);
668 if (rootdse_res
->count
!= 1) {
669 ldb_asprintf_errstring(ldb
, "Failed to find rootDSE: count %d", rootdse_res
->count
);
674 schema_dn
= ldb_msg_find_attr_as_dn(ldb
, mem_ctx
, rootdse_res
->msgs
[0], "schemaNamingContext");
679 talloc_free(rootdse_res
);
683 static int fetch_objectclass_schema(struct ldb_context
*ldb
, struct ldb_dn
*schemadn
,
685 struct ldb_result
**objectclass_res
)
687 TALLOC_CTX
*local_ctx
= talloc_new(mem_ctx
);
689 const char *attrs
[] = {
696 return LDB_ERR_OPERATIONS_ERROR
;
699 /* Downlaod schema */
700 ret
= ldb_search(ldb
, schemadn
, LDB_SCOPE_SUBTREE
,
701 "objectClass=classSchema",
702 attrs
, objectclass_res
);
703 if (ret
!= LDB_SUCCESS
) {
707 talloc_steal(mem_ctx
, objectclass_res
);
713 static int get_remote_rootdse(struct ldb_context
*ldb
, void *context
,
714 struct ldb_reply
*ares
)
716 struct entryUUID_private
*entryUUID_private
;
717 entryUUID_private
= talloc_get_type(context
,
718 struct entryUUID_private
);
719 if (ares
->type
== LDB_REPLY_ENTRY
) {
721 struct ldb_message_element
*el
= ldb_msg_find_element(ares
->message
, "namingContexts");
722 entryUUID_private
->base_dns
= talloc_realloc(entryUUID_private
, entryUUID_private
->base_dns
, struct ldb_dn
*,
724 for (i
=0; i
< el
->num_values
; i
++) {
725 if (!entryUUID_private
->base_dns
) {
726 return LDB_ERR_OPERATIONS_ERROR
;
728 entryUUID_private
->base_dns
[i
] = ldb_dn_new(entryUUID_private
->base_dns
, ldb
, (const char *)el
->values
[i
].data
);
729 if ( ! ldb_dn_validate(entryUUID_private
->base_dns
[i
])) {
730 return LDB_ERR_OPERATIONS_ERROR
;
733 entryUUID_private
->base_dns
[i
] = NULL
;
739 static int find_base_dns(struct ldb_module
*module
,
740 struct entryUUID_private
*entryUUID_private
)
743 struct ldb_request
*req
;
744 const char *naming_context_attr
[] = {
748 req
= talloc(entryUUID_private
, struct ldb_request
);
750 ldb_set_errstring(module
->ldb
, "Out of Memory");
751 return LDB_ERR_OPERATIONS_ERROR
;
754 req
->operation
= LDB_SEARCH
;
755 req
->op
.search
.base
= ldb_dn_new(req
, module
->ldb
, NULL
);
756 req
->op
.search
.scope
= LDB_SCOPE_BASE
;
758 req
->op
.search
.tree
= ldb_parse_tree(req
, "objectClass=*");
759 if (req
->op
.search
.tree
== NULL
) {
760 ldb_set_errstring(module
->ldb
, "Unable to parse search expression");
762 return LDB_ERR_OPERATIONS_ERROR
;
765 req
->op
.search
.attrs
= naming_context_attr
;
766 req
->controls
= NULL
;
767 req
->context
= entryUUID_private
;
768 req
->callback
= get_remote_rootdse
;
769 ldb_set_timeout(module
->ldb
, req
, 0); /* use default timeout */
771 ret
= ldb_next_request(module
, req
);
773 if (ret
== LDB_SUCCESS
) {
774 ret
= ldb_wait(req
->handle
, LDB_WAIT_ALL
);
778 if (ret
!= LDB_SUCCESS
) {
785 /* the context init function */
786 static int entryUUID_init(struct ldb_module
*module
)
789 struct map_private
*map_private
;
790 struct entryUUID_private
*entryUUID_private
;
791 struct ldb_dn
*schema_dn
;
793 ret
= ldb_map_init(module
, entryUUID_attributes
, entryUUID_objectclasses
, entryUUID_wildcard_attributes
, NULL
);
794 if (ret
!= LDB_SUCCESS
)
797 map_private
= talloc_get_type(module
->private_data
, struct map_private
);
799 entryUUID_private
= talloc_zero(map_private
, struct entryUUID_private
);
800 map_private
->caller_private
= entryUUID_private
;
802 schema_dn
= find_schema_dn(module
->ldb
, map_private
);
804 /* Perhaps no schema yet */
808 ret
= fetch_objectclass_schema(module
->ldb
, schema_dn
, entryUUID_private
,
809 &entryUUID_private
->objectclass_res
);
810 if (ret
!= LDB_SUCCESS
) {
811 /* Perhaps no schema yet */
815 ret
= find_base_dns(module
, entryUUID_private
);
817 return ldb_next_init(module
);
820 /* the context init function */
821 static int nsuniqueid_init(struct ldb_module
*module
)
824 struct map_private
*map_private
;
825 struct entryUUID_private
*entryUUID_private
;
826 struct ldb_dn
*schema_dn
;
828 ret
= ldb_map_init(module
, nsuniqueid_attributes
, NULL
, nsuniqueid_wildcard_attributes
, NULL
);
829 if (ret
!= LDB_SUCCESS
)
832 map_private
= talloc_get_type(module
->private_data
, struct map_private
);
834 entryUUID_private
= talloc_zero(map_private
, struct entryUUID_private
);
835 map_private
->caller_private
= entryUUID_private
;
837 schema_dn
= find_schema_dn(module
->ldb
, map_private
);
839 /* Perhaps no schema yet */
843 ret
= fetch_objectclass_schema(module
->ldb
, schema_dn
, entryUUID_private
,
844 &entryUUID_private
->objectclass_res
);
845 if (ret
!= LDB_SUCCESS
) {
846 /* Perhaps no schema yet */
850 ret
= find_base_dns(module
, entryUUID_private
);
852 return ldb_next_init(module
);
855 static int get_seq(struct ldb_context
*ldb
, void *context
,
856 struct ldb_reply
*ares
)
858 unsigned long long *max_seq
= context
;
859 unsigned long long seq
;
860 if (ares
->type
== LDB_REPLY_ENTRY
) {
861 struct ldb_message_element
*el
= ldb_msg_find_element(ares
->message
, "contextCSN");
863 seq
= entryCSN_to_usn_int(ares
, &el
->values
[0]);
864 *max_seq
= MAX(seq
, *max_seq
);
871 static int entryUUID_sequence_number(struct ldb_module
*module
, struct ldb_request
*req
)
874 struct map_private
*map_private
;
875 struct entryUUID_private
*entryUUID_private
;
876 unsigned long long max_seq
= 0;
877 struct ldb_request
*search_req
;
878 map_private
= talloc_get_type(module
->private_data
, struct map_private
);
880 entryUUID_private
= talloc_get_type(map_private
->caller_private
, struct entryUUID_private
);
882 /* Search the baseDNs for a sequence number */
883 for (i
=0; entryUUID_private
&&
884 entryUUID_private
->base_dns
&&
885 entryUUID_private
->base_dns
[i
];
887 static const char *contextCSN_attr
[] = {
890 search_req
= talloc(req
, struct ldb_request
);
891 if (search_req
== NULL
) {
892 ldb_set_errstring(module
->ldb
, "Out of Memory");
893 return LDB_ERR_OPERATIONS_ERROR
;
896 search_req
->operation
= LDB_SEARCH
;
897 search_req
->op
.search
.base
= entryUUID_private
->base_dns
[i
];
898 search_req
->op
.search
.scope
= LDB_SCOPE_BASE
;
900 search_req
->op
.search
.tree
= ldb_parse_tree(search_req
, "objectClass=*");
901 if (search_req
->op
.search
.tree
== NULL
) {
902 ldb_set_errstring(module
->ldb
, "Unable to parse search expression");
903 talloc_free(search_req
);
904 return LDB_ERR_OPERATIONS_ERROR
;
907 search_req
->op
.search
.attrs
= contextCSN_attr
;
908 search_req
->controls
= NULL
;
909 search_req
->context
= &max_seq
;
910 search_req
->callback
= get_seq
;
911 ldb_set_timeout(module
->ldb
, search_req
, 0); /* use default timeout */
913 ret
= ldb_next_request(module
, search_req
);
915 if (ret
== LDB_SUCCESS
) {
916 ret
= ldb_wait(search_req
->handle
, LDB_WAIT_ALL
);
919 talloc_free(search_req
);
920 if (ret
!= LDB_SUCCESS
) {
925 switch (req
->op
.seq_num
.type
) {
926 case LDB_SEQ_HIGHEST_SEQ
:
927 req
->op
.seq_num
.seq_num
= max_seq
;
930 req
->op
.seq_num
.seq_num
= max_seq
;
931 req
->op
.seq_num
.seq_num
++;
933 case LDB_SEQ_HIGHEST_TIMESTAMP
:
935 req
->op
.seq_num
.seq_num
= (max_seq
>> 24);
939 req
->op
.seq_num
.flags
= 0;
940 req
->op
.seq_num
.flags
|= LDB_SEQ_TIMESTAMP_SEQUENCE
;
941 req
->op
.seq_num
.flags
|= LDB_SEQ_GLOBAL_SEQUENCE
;
945 static struct ldb_module_ops entryUUID_ops
= {
947 .init_context
= entryUUID_init
,
948 .sequence_number
= entryUUID_sequence_number
951 static struct ldb_module_ops nsuniqueid_ops
= {
952 .name
= "nsuniqueid",
953 .init_context
= nsuniqueid_init
,
954 .sequence_number
= entryUUID_sequence_number
957 /* the init function */
958 int ldb_entryUUID_module_init(void)
961 struct ldb_module_ops ops
= ldb_map_get_ops();
962 entryUUID_ops
.add
= ops
.add
;
963 entryUUID_ops
.modify
= ops
.modify
;
964 entryUUID_ops
.del
= ops
.del
;
965 entryUUID_ops
.rename
= ops
.rename
;
966 entryUUID_ops
.search
= ops
.search
;
967 entryUUID_ops
.wait
= ops
.wait
;
968 ret
= ldb_register_module(&entryUUID_ops
);
974 nsuniqueid_ops
.add
= ops
.add
;
975 nsuniqueid_ops
.modify
= ops
.modify
;
976 nsuniqueid_ops
.del
= ops
.del
;
977 nsuniqueid_ops
.rename
= ops
.rename
;
978 nsuniqueid_ops
.search
= ops
.search
;
979 nsuniqueid_ops
.wait
= ops
.wait
;
980 ret
= ldb_register_module(&nsuniqueid_ops
);