summaryrefslogtreecommitdiff
path: root/source4/librpc/ndr
diff options
context:
space:
mode:
Diffstat (limited to 'source4/librpc/ndr')
-rw-r--r--source4/librpc/ndr/libndr.h31
-rw-r--r--source4/librpc/ndr/ndr.c152
-rw-r--r--source4/librpc/ndr/ndr_basic.c3
3 files changed, 106 insertions, 80 deletions
diff --git a/source4/librpc/ndr/libndr.h b/source4/librpc/ndr/libndr.h
index 57d9766811..7ab5de52fa 100644
--- a/source4/librpc/ndr/libndr.h
+++ b/source4/librpc/ndr/libndr.h
@@ -23,15 +23,15 @@
*/
-/* offset lists are used to allow a push/pull function to find the
- start of an encapsulating structure */
-struct ndr_ofs_list {
- uint32_t offset;
- uint32_t base;
- struct ndr_ofs_list *next;
+/*
+ this is used by the token store/retrieve code
+*/
+struct ndr_token_list {
+ struct ndr_token_list *next, *prev;
+ const void *key;
+ uint32_t value;
};
-
/* this is the base structure passed to routines that
parse MSRPC formatted data
@@ -47,9 +47,11 @@ struct ndr_pull {
uint32_t offset;
TALLOC_CTX *mem_ctx;
- /* this points at a list of offsets to the structures being processed.
- The first element in the list is the current structure */
- struct ndr_ofs_list *ofs_list;
+ struct ndr_token_list *relative_list;
+
+ /* this is used to ensure we generate unique reference IDs
+ between request and reply */
+ uint32_t ptr_count;
};
struct ndr_pull_save {
@@ -66,15 +68,10 @@ struct ndr_push {
uint32_t offset;
TALLOC_CTX *mem_ctx;
+ struct ndr_token_list *relative_list;
+
/* this is used to ensure we generate unique reference IDs */
uint32_t ptr_count;
-
- /* this points at a list of offsets to the structures being processed.
- The first element in the list is the current structure */
- struct ndr_ofs_list *ofs_list;
-
- /* this list is used by the [relative] code to find the offsets */
- struct ndr_ofs_list *relative_list, *relative_list_end;
};
struct ndr_push_save {
diff --git a/source4/librpc/ndr/ndr.c b/source4/librpc/ndr/ndr.c
index 1d6b90f4bf..1d50d95afa 100644
--- a/source4/librpc/ndr/ndr.c
+++ b/source4/librpc/ndr/ndr.c
@@ -55,7 +55,8 @@ struct ndr_pull *ndr_pull_init_blob(const DATA_BLOB *blob, TALLOC_CTX *mem_ctx)
ndr->data_size = blob->length;
ndr->offset = 0;
ndr->mem_ctx = mem_ctx;
- ndr->ofs_list = NULL;
+ ndr->ptr_count = 0;
+ ndr->relative_list = NULL;
return ndr;
}
@@ -139,9 +140,7 @@ struct ndr_push *ndr_push_init_ctx(TALLOC_CTX *mem_ctx)
ndr->offset = 0;
ndr->ptr_count = 0;
ndr->relative_list = NULL;
- ndr->relative_list_end = NULL;
- ndr->ofs_list = NULL;
-
+
return ndr;
}
@@ -604,12 +603,6 @@ NTSTATUS ndr_push_subcontext_union_fn(struct ndr_push *ndr,
*/
NTSTATUS ndr_pull_struct_start(struct ndr_pull *ndr)
{
- struct ndr_ofs_list *ofs;
- NDR_ALLOC(ndr, ofs);
- ofs->offset = ndr->offset;
- ofs->next = ndr->ofs_list;
- ofs->base = 0;
- ndr->ofs_list = ofs;
return NT_STATUS_OK;
}
@@ -618,7 +611,6 @@ NTSTATUS ndr_pull_struct_start(struct ndr_pull *ndr)
*/
void ndr_pull_struct_end(struct ndr_pull *ndr)
{
- ndr->ofs_list = ndr->ofs_list->next;
}
/*
@@ -626,12 +618,6 @@ void ndr_pull_struct_end(struct ndr_pull *ndr)
*/
NTSTATUS ndr_push_struct_start(struct ndr_push *ndr)
{
- struct ndr_ofs_list *ofs;
- NDR_PUSH_ALLOC(ndr, ofs);
- ofs->offset = ndr->offset;
- ofs->next = ndr->ofs_list;
- ofs->base = 0;
- ndr->ofs_list = ofs;
return NT_STATUS_OK;
}
@@ -640,7 +626,6 @@ NTSTATUS ndr_push_struct_start(struct ndr_push *ndr)
*/
void ndr_push_struct_end(struct ndr_push *ndr)
{
- ndr->ofs_list = ndr->ofs_list->next;
}
@@ -665,11 +650,7 @@ NTSTATUS ndr_pull_relative(struct ndr_pull *ndr, const void **buf, size_t size,
wrong, and there doesn't seem to be anything relying on it,
but I am keeping the code around in case I missed a
critical use for it (tridge, august 2004) */
-#if OLD_RELATIVE_BEHAVIOUR
- NDR_CHECK(ndr_pull_set_offset(ndr, ofs + ndr->ofs_list->offset));
-#else
NDR_CHECK(ndr_pull_set_offset(ndr, ofs));
-#endif
NDR_CHECK(ndr_pull_subcontext(ndr, &ndr2, ndr->data_size - ndr->offset));
/* strings must be allocated by the backend functions */
if (ndr->flags & LIBNDR_STRING_FLAGS) {
@@ -683,53 +664,98 @@ NTSTATUS ndr_pull_relative(struct ndr_pull *ndr, const void **buf, size_t size,
return NT_STATUS_OK;
}
+
/*
- push a relative structure
+ store a token in the ndr context, for later retrieval
*/
-NTSTATUS ndr_push_relative(struct ndr_push *ndr, int ndr_flags, const void *p)
+static NTSTATUS ndr_token_store(TALLOC_CTX *mem_ctx,
+ struct ndr_token_list **list,
+ const void *key,
+ uint32_t value)
{
- struct ndr_ofs_list *ofs;
- if (ndr_flags & NDR_SCALARS) {
- if (!p) {
- NDR_CHECK(ndr_push_uint32(ndr, 0));
- return NT_STATUS_OK;
- }
- NDR_PUSH_ALLOC(ndr, ofs);
- NDR_CHECK(ndr_push_align(ndr, 4));
- ofs->offset = ndr->offset;
-#if OLD_RELATIVE_BEHAVIOUR
- ofs->base = ndr->ofs_list->offset;
-#else
- ofs->base = 0;
-#endif
- NDR_CHECK(ndr_push_uint32(ndr, 0xFFFFFFFF));
- ofs->next = NULL;
- if (ndr->relative_list_end) {
- ndr->relative_list_end->next = ofs;
- } else {
- ndr->relative_list = ofs;
- }
- ndr->relative_list_end = ofs;
+ struct ndr_token_list *tok;
+ tok = talloc_p(mem_ctx, struct ndr_token_list);
+ if (tok == NULL) {
+ return NT_STATUS_NO_MEMORY;
}
- if (ndr_flags & NDR_BUFFERS) {
- struct ndr_push_save save;
- if (!p) {
- return NT_STATUS_OK;
- }
- ofs = ndr->relative_list;
- if (!ofs) {
- return ndr_push_error(ndr, NDR_ERR_RELATIVE, "Empty relative stack");
- }
- ndr->relative_list = ndr->relative_list->next;
- if (ndr->relative_list == NULL) {
- ndr->relative_list_end = NULL;
+ tok->key = key;
+ tok->value = value;
+ DLIST_ADD((*list), tok);
+ return NT_STATUS_OK;
+}
+
+/*
+ retrieve a token from a ndr context
+*/
+static uint32_t ndr_token_retrieve(struct ndr_token_list **list, const void *key)
+{
+ struct ndr_token_list *tok;
+ for (tok=*list;tok;tok=tok->next) {
+ if (tok->key == key) {
+ DLIST_REMOVE((*list), tok);
+ return tok->value;
}
- NDR_CHECK(ndr_push_align(ndr, 4));
- ndr_push_save(ndr, &save);
- ndr->offset = ofs->offset;
- NDR_CHECK(ndr_push_uint32(ndr, save.offset - ofs->base));
- ndr_push_restore(ndr, &save);
}
+ return 0;
+}
+
+
+/*
+ pull a relative object - stage1
+ called during SCALARS processing
+*/
+NTSTATUS ndr_pull_relative1(struct ndr_pull *ndr, const void *p, uint32_t rel_offset)
+{
+ return ndr_token_store(ndr->mem_ctx, &ndr->relative_list, p, rel_offset);
+}
+
+/*
+ pull a relative object - stage2
+ called during BUFFERS processing
+*/
+NTSTATUS ndr_pull_relative2(struct ndr_pull *ndr, const void *p)
+{
+ uint32_t rel_offset;
+ rel_offset = ndr_token_retrieve(&ndr->relative_list, p);
+ if (rel_offset == 0) {
+ return NT_STATUS_INTERNAL_ERROR;
+ }
+ return ndr_pull_set_offset(ndr, rel_offset);
+}
+
+/*
+ push a relative object - stage1
+ this is called during SCALARS processing
+*/
+NTSTATUS ndr_push_relative1(struct ndr_push *ndr, const void *p)
+{
+ if (p == NULL) {
+ NDR_CHECK(ndr_push_uint32(ndr, 0));
+ return NT_STATUS_OK;
+ }
+ NDR_CHECK(ndr_push_align(ndr, 4));
+ NDR_CHECK(ndr_token_store(ndr->mem_ctx, &ndr->relative_list, p, ndr->offset));
+ return ndr_push_uint32(ndr, 0xFFFFFFFF);
+}
+
+/*
+ push a relative object - stage2
+ this is called during buffers processing
+*/
+NTSTATUS ndr_push_relative2(struct ndr_push *ndr, const void *p)
+{
+ struct ndr_push_save save;
+ if (p == NULL) {
+ return NT_STATUS_OK;
+ }
+ NDR_CHECK(ndr_push_align(ndr, 4));
+ ndr_push_save(ndr, &save);
+ ndr->offset = ndr_token_retrieve(&ndr->relative_list, p);
+ if (ndr->offset == 0) {
+ return NT_STATUS_INTERNAL_ERROR;
+ }
+ NDR_CHECK(ndr_push_uint32(ndr, save.offset));
+ ndr_push_restore(ndr, &save);
return NT_STATUS_OK;
}
diff --git a/source4/librpc/ndr/ndr_basic.c b/source4/librpc/ndr/ndr_basic.c
index bf72e0ad8b..88a58e91fd 100644
--- a/source4/librpc/ndr/ndr_basic.c
+++ b/source4/librpc/ndr/ndr_basic.c
@@ -72,6 +72,9 @@ NTSTATUS ndr_pull_ptr(struct ndr_pull *ndr, uint32_t *v)
{
NTSTATUS status;
status = ndr_pull_uint32(ndr, v);
+ if (*v != 0) {
+ ndr->ptr_count++;
+ }
return status;
}