summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMatthieu Patou <mat@matws.net>2009-12-10 10:04:48 +0300
committerStefan Metzmacher <metze@samba.org>2009-12-12 10:21:22 +0100
commitf0054da041b961bde25f63791d3b33cc834bd365 (patch)
treed708d6ecc65c0999ba26927c0cd5c20594d568c8
parent5767b1dacc546baef1db569315ba1309bbb99566 (diff)
downloadsamba-f0054da041b961bde25f63791d3b33cc834bd365.tar.gz
samba-f0054da041b961bde25f63791d3b33cc834bd365.tar.bz2
samba-f0054da041b961bde25f63791d3b33cc834bd365.zip
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 <metze@samba.org>
-rw-r--r--librpc/ndr/ndr.c42
-rw-r--r--librpc/ndr/ndr_basic.c12
2 files changed, 54 insertions, 0 deletions
diff --git a/librpc/ndr/ndr.c b/librpc/ndr/ndr.c
index 1969decb5b..a151994b6a 100644
--- a/librpc/ndr/ndr.c
+++ b/librpc/ndr/ndr.c
@@ -1074,6 +1074,20 @@ _PUBLIC_ enum ndr_err_code ndr_push_relative_ptr1(struct ndr_push *ndr, const vo
}
/*
+ 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 64fa5a6299..1fd6fdea74 100644
--- a/librpc/ndr/ndr_basic.c
+++ b/librpc/ndr/ndr_basic.c
@@ -176,6 +176,18 @@ _PUBLIC_ enum ndr_err_code ndr_pull_double(struct ndr_pull *ndr, int ndr_flags,
}
/*
+ 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
*/
_PUBLIC_ enum ndr_err_code ndr_pull_generic_ptr(struct ndr_pull *ndr, uint32_t *v)