diff options
author | Andrew Tridgell <tridge@samba.org> | 2004-08-12 05:15:41 +0000 |
---|---|---|
committer | Gerald (Jerry) Carter <jerry@samba.org> | 2007-10-10 12:57:54 -0500 |
commit | e2357c67f5afbfeacafab6997b57ea262cd3c05a (patch) | |
tree | f003a9ce63846a5ce8340b366df502d8bf49c381 /source4/librpc | |
parent | fa8d37adae70a5f479262b722e47aa7fc21aaf5c (diff) | |
download | samba-e2357c67f5afbfeacafab6997b57ea262cd3c05a.tar.gz samba-e2357c67f5afbfeacafab6997b57ea262cd3c05a.tar.bz2 samba-e2357c67f5afbfeacafab6997b57ea262cd3c05a.zip |
r1757: much simpler (and smaller, faster etc) way of doing relative pointers
in pidl. This mechanism should be much easier to extend to the
"retrospective subcontexts" that jelmer needs.
also produced more standards complient full-pointer offsets. This
keeps ethereal happy with decoding our epmapper frames.
(This used to be commit ecb7378bbcd86727aedfa04a9e302e06b0a2ccd9)
Diffstat (limited to 'source4/librpc')
-rw-r--r-- | source4/librpc/ndr/libndr.h | 31 | ||||
-rw-r--r-- | source4/librpc/ndr/ndr.c | 152 | ||||
-rw-r--r-- | source4/librpc/ndr/ndr_basic.c | 3 |
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; } |