From f0054da041b961bde25f63791d3b33cc834bd365 Mon Sep 17 00:00:00 2001 From: Matthieu Patou Date: Thu, 10 Dec 2009 10:04:48 +0300 Subject: [PATCH] librpc/ndr: add support for relative_short pointers relative_short is like relative but instead of having the offset coded on 4 bytes it's coded on 2 bytes. Such things happen in GET_DFS_REFERAL messages. Signed-off-by: Stefan Metzmacher --- librpc/ndr/ndr.c | 42 ++++++++++++++++++++++++++++++++++++++++++ librpc/ndr/ndr_basic.c | 12 ++++++++++++ 2 files changed, 54 insertions(+) diff --git a/librpc/ndr/ndr.c b/librpc/ndr/ndr.c index 1969decb5b8..a151994b6af 100644 --- a/librpc/ndr/ndr.c +++ b/librpc/ndr/ndr.c @@ -1073,6 +1073,20 @@ _PUBLIC_ enum ndr_err_code ndr_push_relative_ptr1(struct ndr_push *ndr, const vo return ndr_push_uint32(ndr, NDR_SCALARS, 0xFFFFFFFF); } +/* + push a short relative object - stage1 + this is called during SCALARS processing +*/ +_PUBLIC_ enum ndr_err_code ndr_push_short_relative_ptr1(struct ndr_push *ndr, const void *p) +{ + if (p == NULL) { + NDR_CHECK(ndr_push_uint16(ndr, NDR_SCALARS, 0)); + return NDR_ERR_SUCCESS; + } + NDR_CHECK(ndr_push_align(ndr, 2)); + NDR_CHECK(ndr_token_store(ndr, &ndr->relative_list, p, ndr->offset)); + return ndr_push_uint16(ndr, NDR_SCALARS, 0xFFFF); +} /* push a relative object - stage2 this is called during buffers processing @@ -1101,6 +1115,34 @@ _PUBLIC_ enum ndr_err_code ndr_push_relative_ptr2(struct ndr_push *ndr, const vo ndr->offset = save_offset; return NDR_ERR_SUCCESS; } +/* + push a short relative object - stage2 + this is called during buffers processing +*/ +_PUBLIC_ enum ndr_err_code ndr_push_short_relative_ptr2(struct ndr_push *ndr, const void *p) +{ + uint32_t save_offset; + uint32_t ptr_offset = 0xFFFF; + if (p == NULL) { + return NDR_ERR_SUCCESS; + } + save_offset = ndr->offset; + NDR_CHECK(ndr_token_retrieve(&ndr->relative_list, p, &ptr_offset)); + if (ptr_offset > ndr->offset) { + return ndr_push_error(ndr, NDR_ERR_BUFSIZE, + "ndr_push_short_relative_ptr2 ptr_offset(%u) > ndr->offset(%u)", + ptr_offset, ndr->offset); + } + ndr->offset = ptr_offset; + if (save_offset < ndr->relative_base_offset) { + return ndr_push_error(ndr, NDR_ERR_BUFSIZE, + "ndr_push_relative_ptr2 save_offset(%u) < ndr->relative_base_offset(%u)", + save_offset, ndr->relative_base_offset); + } + NDR_CHECK(ndr_push_uint16(ndr, NDR_SCALARS, save_offset - ndr->relative_base_offset)); + ndr->offset = save_offset; + return NDR_ERR_SUCCESS; +} /* get the current base for relative pointers for the pull diff --git a/librpc/ndr/ndr_basic.c b/librpc/ndr/ndr_basic.c index 64fa5a62998..1fd6fdea741 100644 --- a/librpc/ndr/ndr_basic.c +++ b/librpc/ndr/ndr_basic.c @@ -175,6 +175,18 @@ _PUBLIC_ enum ndr_err_code ndr_pull_double(struct ndr_pull *ndr, int ndr_flags, return NDR_ERR_SUCCESS; } +/* + parse a pointer referent identifier stored in 2 bytes +*/ +_PUBLIC_ enum ndr_err_code ndr_pull_relative_ptr_short(struct ndr_pull *ndr, uint16_t *v) +{ + NDR_CHECK(ndr_pull_uint16(ndr, NDR_SCALARS, v)); + if (*v != 0) { + ndr->ptr_count++; + } + return NDR_ERR_SUCCESS; +} + /* parse a pointer referent identifier */ -- 2.34.1