librpc/ndr: add support for relative_short pointers
authorMatthieu Patou <mat@matws.net>
Thu, 10 Dec 2009 07:04:48 +0000 (10:04 +0300)
committerStefan Metzmacher <metze@samba.org>
Sat, 12 Dec 2009 09:21:22 +0000 (10:21 +0100)
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>
librpc/ndr/ndr.c
librpc/ndr/ndr_basic.c

index 1969decb5b866925c4e6e399f128d00e9580b45c..a151994b6af64c6d25b907ac8194a76880eb4cfc 100644 (file)
@@ -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
index 64fa5a62998268b8977683b1befde75bdb8fcef9..1fd6fdea7416f35c157e70555c1013beca84753a 100644 (file)
@@ -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
 */