2 Unix SMB/CIFS implementation.
6 Copyright (C) Andrew Tridgell 2003
8 This program is free software; you can redistribute it and/or modify
9 it under the terms of the GNU General Public License as published by
10 the Free Software Foundation; either version 3 of the License, or
11 (at your option) any later version.
13 This program is distributed in the hope that it will be useful,
14 but WITHOUT ANY WARRANTY; without even the implied warranty of
15 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 GNU General Public License for more details.
18 You should have received a copy of the GNU General Public License
19 along with this program; if not, write to the Free Software
20 Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
24 this provides the core routines for NDR parsing functions
26 see http://www.opengroup.org/onlinepubs/9629399/chap14.htm for details
32 #define NDR_BASE_MARSHALL_SIZE 1024
34 /* this guid indicates NDR encoding in a protocol tower */
35 const struct dcerpc_syntax_id ndr_transfer_syntax = {
36 { 0x8a885d04, 0x1ceb, 0x11c9, {0x9f, 0xe8}, {0x08,0x00,0x2b,0x10,0x48,0x60} },
40 const struct dcerpc_syntax_id ndr64_transfer_syntax = {
41 { 0x71710533, 0xbeba, 0x4937, {0x83, 0x19}, {0xb5,0xdb,0xef,0x9c,0xcc,0x36} },
46 work out the number of bytes needed to align on a n byte boundary
48 size_t ndr_align_size(uint32_t offset, size_t n)
50 if ((offset & (n-1)) == 0) return 0;
51 return n - (offset & (n-1));
55 initialise a ndr parse structure from a data blob
57 struct ndr_pull *ndr_pull_init_blob(const DATA_BLOB *blob, TALLOC_CTX *mem_ctx)
61 ndr = talloc_zero(mem_ctx, struct ndr_pull);
62 if (!ndr) return NULL;
63 ndr->current_mem_ctx = mem_ctx;
65 ndr->data = blob->data;
66 ndr->data_size = blob->length;
72 advance by 'size' bytes
74 NTSTATUS ndr_pull_advance(struct ndr_pull *ndr, uint32_t size)
77 if (ndr->offset > ndr->data_size) {
78 return ndr_pull_error(ndr, NDR_ERR_BUFSIZE,
79 "ndr_pull_advance by %u failed",
86 set the parse offset to 'ofs'
88 static NTSTATUS ndr_pull_set_offset(struct ndr_pull *ndr, uint32_t ofs)
91 if (ndr->offset > ndr->data_size) {
92 return ndr_pull_error(ndr, NDR_ERR_BUFSIZE,
93 "ndr_pull_set_offset %u failed",
99 /* save the offset/size of the current ndr state */
100 void ndr_pull_save(struct ndr_pull *ndr, struct ndr_pull_save *save)
102 save->offset = ndr->offset;
103 save->data_size = ndr->data_size;
106 /* restore the size/offset of a ndr structure */
107 void ndr_pull_restore(struct ndr_pull *ndr, struct ndr_pull_save *save)
109 ndr->offset = save->offset;
110 ndr->data_size = save->data_size;
114 /* create a ndr_push structure, ready for some marshalling */
115 struct ndr_push *ndr_push_init_ctx(TALLOC_CTX *mem_ctx)
117 struct ndr_push *ndr;
119 ndr = talloc_zero(mem_ctx, struct ndr_push);
125 ndr->alloc_size = NDR_BASE_MARSHALL_SIZE;
126 ndr->data = talloc_array(ndr, uint8_t, ndr->alloc_size);
135 /* create a ndr_push structure, ready for some marshalling */
136 struct ndr_push *ndr_push_init(void)
138 return ndr_push_init_ctx(NULL);
141 /* free a ndr_push structure */
142 void ndr_push_free(struct ndr_push *ndr)
148 /* return a DATA_BLOB structure for the current ndr_push marshalled data */
149 DATA_BLOB ndr_push_blob(struct ndr_push *ndr)
152 blob.data = ndr->data;
153 blob.length = ndr->offset;
155 if (ndr->alloc_size > ndr->offset) {
156 ndr->data[ndr->offset] = 0;
163 expand the available space in the buffer to ndr->offset + extra_size
165 NTSTATUS ndr_push_expand(struct ndr_push *ndr, uint32_t extra_size)
167 uint32_t size = extra_size + ndr->offset;
169 if (size < ndr->offset) {
170 /* extra_size overflowed the offset */
171 return ndr_push_error(ndr, NDR_ERR_BUFSIZE, "Overflow in push_expand to %u",
175 if (ndr->alloc_size > size) {
179 ndr->alloc_size += NDR_BASE_MARSHALL_SIZE;
180 if (size+1 > ndr->alloc_size) {
181 ndr->alloc_size = size+1;
183 ndr->data = talloc_realloc(ndr, ndr->data, uint8_t, ndr->alloc_size);
185 return ndr_push_error(ndr, NDR_ERR_ALLOC, "Failed to push_expand to %u",
192 void ndr_print_debug_helper(struct ndr_print *ndr, const char *format, ...) _PRINTF_ATTRIBUTE(2,3)
198 va_start(ap, format);
199 vasprintf(&s, format, ap);
202 for (i=0;i<ndr->depth;i++) {
206 DEBUG(0,("%s\n", s));
210 static void ndr_print_string_helper(struct ndr_print *ndr, const char *format, ...) _PRINTF_ATTRIBUTE(2,3)
215 for (i=0;i<ndr->depth;i++) {
216 ndr->private_data = talloc_asprintf_append(
217 (char *)ndr->private_data, " ");
220 va_start(ap, format);
221 ndr->private_data = talloc_vasprintf_append(
222 (char *)ndr->private_data, format, ap);
224 ndr->private_data = talloc_asprintf_append(
225 (char *)ndr->private_data, "\n");
229 a useful helper function for printing idl structures via DEBUG()
231 void ndr_print_debug(ndr_print_fn_t fn, const char *name, void *ptr)
233 struct ndr_print *ndr;
235 ndr = talloc_zero(NULL, struct ndr_print);
237 ndr->print = ndr_print_debug_helper;
245 a useful helper function for printing idl unions via DEBUG()
247 void ndr_print_union_debug(ndr_print_fn_t fn, const char *name, uint32_t level, void *ptr)
249 struct ndr_print *ndr;
251 ndr = talloc_zero(NULL, struct ndr_print);
253 ndr->print = ndr_print_debug_helper;
256 ndr_print_set_switch_value(ndr, ptr, level);
262 a useful helper function for printing idl function calls via DEBUG()
264 void ndr_print_function_debug(ndr_print_function_t fn, const char *name, int flags, void *ptr)
266 struct ndr_print *ndr;
268 ndr = talloc_zero(NULL, struct ndr_print);
270 ndr->print = ndr_print_debug_helper;
273 fn(ndr, name, flags, ptr);
279 a useful helper function for printing idl function calls to a string
281 char *ndr_print_function_string(TALLOC_CTX *mem_ctx,
282 ndr_print_function_t fn, const char *name,
283 int flags, void *ptr)
285 struct ndr_print *ndr;
288 ndr = talloc_zero(mem_ctx, struct ndr_print);
289 if (!ndr) return NULL;
290 if (!(ndr->private_data = talloc_strdup(mem_ctx, ""))) {
294 ndr->print = ndr_print_string_helper;
297 fn(ndr, name, flags, ptr);
298 ret = (char *)ndr->private_data;
303 void ndr_set_flags(uint32_t *pflags, uint32_t new_flags)
305 /* the big/little endian flags are inter-dependent */
306 if (new_flags & LIBNDR_FLAG_LITTLE_ENDIAN) {
307 (*pflags) &= ~LIBNDR_FLAG_BIGENDIAN;
309 if (new_flags & LIBNDR_FLAG_BIGENDIAN) {
310 (*pflags) &= ~LIBNDR_FLAG_LITTLE_ENDIAN;
312 if (new_flags & LIBNDR_FLAG_REMAINING) {
313 (*pflags) &= ~LIBNDR_ALIGN_FLAGS;
315 if (new_flags & LIBNDR_ALIGN_FLAGS) {
316 (*pflags) &= ~LIBNDR_FLAG_REMAINING;
318 (*pflags) |= new_flags;
321 static NTSTATUS ndr_map_error(enum ndr_err_code ndr_err)
324 case NDR_ERR_BUFSIZE:
325 return NT_STATUS_BUFFER_TOO_SMALL;
327 return NT_STATUS_INTERNAL_ERROR;
329 return NT_STATUS_NO_MEMORY;
330 case NDR_ERR_ARRAY_SIZE:
331 return NT_STATUS_ARRAY_BOUNDS_EXCEEDED;
336 /* we should map all error codes to different status codes */
337 return NT_STATUS_INVALID_PARAMETER;
341 return and possibly log an NDR error
343 NTSTATUS ndr_pull_error(struct ndr_pull *ndr,
344 enum ndr_err_code ndr_err,
345 const char *format, ...) _PRINTF_ATTRIBUTE(3,4)
350 va_start(ap, format);
351 vasprintf(&s, format, ap);
354 DEBUG(3,("ndr_pull_error(%u): %s\n", ndr_err, s));
358 return ndr_map_error(ndr_err);
362 return and possibly log an NDR error
364 NTSTATUS ndr_push_error(struct ndr_push *ndr,
365 enum ndr_err_code ndr_err,
366 const char *format, ...) _PRINTF_ATTRIBUTE(3,4)
371 va_start(ap, format);
372 vasprintf(&s, format, ap);
375 DEBUG(3,("ndr_push_error(%u): %s\n", ndr_err, s));
379 return ndr_map_error(ndr_err);
383 handle subcontext buffers, which in midl land are user-marshalled, but
384 we use magic in pidl to make them easier to cope with
386 NTSTATUS ndr_pull_subcontext_start(struct ndr_pull *ndr,
387 struct ndr_pull **_subndr,
391 struct ndr_pull *subndr;
392 uint32_t r_content_size;
394 switch (header_size) {
396 uint32_t content_size = ndr->data_size - ndr->offset;
398 content_size = size_is;
400 r_content_size = content_size;
405 uint16_t content_size;
406 NDR_CHECK(ndr_pull_uint16(ndr, NDR_SCALARS, &content_size));
407 if (size_is >= 0 && size_is != content_size) {
408 return ndr_pull_error(ndr, NDR_ERR_SUBCONTEXT, "Bad subcontext (PULL) size_is(%d) mismatch content_size %d",
409 (int)size_is, (int)content_size);
411 r_content_size = content_size;
416 uint32_t content_size;
417 NDR_CHECK(ndr_pull_uint32(ndr, NDR_SCALARS, &content_size));
418 if (size_is >= 0 && size_is != content_size) {
419 return ndr_pull_error(ndr, NDR_ERR_SUBCONTEXT, "Bad subcontext (PULL) size_is(%d) mismatch content_size %d",
420 (int)size_is, (int)content_size);
422 r_content_size = content_size;
426 return ndr_pull_error(ndr, NDR_ERR_SUBCONTEXT, "Bad subcontext (PULL) header_size %d",
430 NDR_PULL_NEED_BYTES(ndr, r_content_size);
432 subndr = talloc_zero(ndr, struct ndr_pull);
433 NT_STATUS_HAVE_NO_MEMORY(subndr);
434 subndr->flags = ndr->flags;
435 subndr->current_mem_ctx = ndr->current_mem_ctx;
437 subndr->data = ndr->data + ndr->offset;
439 subndr->data_size = r_content_size;
445 NTSTATUS ndr_pull_subcontext_end(struct ndr_pull *ndr,
446 struct ndr_pull *subndr,
453 } else if (header_size > 0) {
454 advance = subndr->data_size;
456 advance = subndr->offset;
458 NDR_CHECK(ndr_pull_advance(ndr, advance));
462 NTSTATUS ndr_push_subcontext_start(struct ndr_push *ndr,
463 struct ndr_push **_subndr,
467 struct ndr_push *subndr;
469 subndr = ndr_push_init_ctx(ndr);
470 NT_STATUS_HAVE_NO_MEMORY(subndr);
471 subndr->flags = ndr->flags;
478 push a subcontext header
480 NTSTATUS ndr_push_subcontext_end(struct ndr_push *ndr,
481 struct ndr_push *subndr,
486 ssize_t padding_len = size_is - subndr->offset;
487 if (padding_len > 0) {
488 NDR_CHECK(ndr_push_zero(subndr, padding_len));
489 } else if (padding_len < 0) {
490 return ndr_push_error(ndr, NDR_ERR_SUBCONTEXT, "Bad subcontext (PUSH) content_size %d is larger than size_is(%d)",
491 (int)subndr->offset, (int)size_is);
495 switch (header_size) {
500 NDR_CHECK(ndr_push_uint16(ndr, NDR_SCALARS, subndr->offset));
504 NDR_CHECK(ndr_push_uint32(ndr, NDR_SCALARS, subndr->offset));
508 return ndr_push_error(ndr, NDR_ERR_SUBCONTEXT, "Bad subcontext header size %d",
512 NDR_CHECK(ndr_push_bytes(ndr, subndr->data, subndr->offset));
517 store a token in the ndr context, for later retrieval
519 NTSTATUS ndr_token_store(TALLOC_CTX *mem_ctx,
520 struct ndr_token_list **list,
524 struct ndr_token_list *tok;
525 tok = talloc(mem_ctx, struct ndr_token_list);
527 return NT_STATUS_NO_MEMORY;
531 DLIST_ADD((*list), tok);
536 retrieve a token from a ndr context, using cmp_fn to match the tokens
538 NTSTATUS ndr_token_retrieve_cmp_fn(struct ndr_token_list **list, const void *key, uint32_t *v,
539 comparison_fn_t _cmp_fn, BOOL _remove_tok)
541 struct ndr_token_list *tok;
542 for (tok=*list;tok;tok=tok->next) {
543 if (_cmp_fn && _cmp_fn(tok->key,key)==0) goto found;
544 else if (!_cmp_fn && tok->key == key) goto found;
546 return ndr_map_error(NDR_ERR_TOKEN);
550 DLIST_REMOVE((*list), tok);
557 retrieve a token from a ndr context
559 NTSTATUS ndr_token_retrieve(struct ndr_token_list **list, const void *key, uint32_t *v)
561 return ndr_token_retrieve_cmp_fn(list, key, v, NULL, True);
565 peek at but don't removed a token from a ndr context
567 uint32_t ndr_token_peek(struct ndr_token_list **list, const void *key)
571 status = ndr_token_retrieve_cmp_fn(list, key, &v, NULL, False);
572 if (NT_STATUS_IS_OK(status)) return v;
577 pull an array size field and add it to the array_size_list token list
579 NTSTATUS ndr_pull_array_size(struct ndr_pull *ndr, const void *p)
582 NDR_CHECK(ndr_pull_uint32(ndr, NDR_SCALARS, &size));
583 return ndr_token_store(ndr, &ndr->array_size_list, p, size);
587 get the stored array size field
589 uint32_t ndr_get_array_size(struct ndr_pull *ndr, const void *p)
591 return ndr_token_peek(&ndr->array_size_list, p);
595 check the stored array size field
597 NTSTATUS ndr_check_array_size(struct ndr_pull *ndr, void *p, uint32_t size)
600 stored = ndr_token_peek(&ndr->array_size_list, p);
601 if (stored != size) {
602 return ndr_pull_error(ndr, NDR_ERR_ARRAY_SIZE,
603 "Bad array size - got %u expected %u\n",
610 pull an array length field and add it to the array_length_list token list
612 NTSTATUS ndr_pull_array_length(struct ndr_pull *ndr, const void *p)
614 uint32_t length, offset;
615 NDR_CHECK(ndr_pull_uint32(ndr, NDR_SCALARS, &offset));
617 return ndr_pull_error(ndr, NDR_ERR_ARRAY_SIZE,
618 "non-zero array offset %u\n", offset);
620 NDR_CHECK(ndr_pull_uint32(ndr, NDR_SCALARS, &length));
621 return ndr_token_store(ndr, &ndr->array_length_list, p, length);
625 get the stored array length field
627 uint32_t ndr_get_array_length(struct ndr_pull *ndr, const void *p)
629 return ndr_token_peek(&ndr->array_length_list, p);
633 check the stored array length field
635 NTSTATUS ndr_check_array_length(struct ndr_pull *ndr, void *p, uint32_t length)
638 stored = ndr_token_peek(&ndr->array_length_list, p);
639 if (stored != length) {
640 return ndr_pull_error(ndr, NDR_ERR_ARRAY_SIZE,
641 "Bad array length - got %u expected %u\n",
650 NTSTATUS ndr_push_set_switch_value(struct ndr_push *ndr, const void *p, uint32_t val)
652 return ndr_token_store(ndr, &ndr->switch_list, p, val);
655 NTSTATUS ndr_pull_set_switch_value(struct ndr_pull *ndr, const void *p, uint32_t val)
657 return ndr_token_store(ndr, &ndr->switch_list, p, val);
660 NTSTATUS ndr_print_set_switch_value(struct ndr_print *ndr, const void *p, uint32_t val)
662 return ndr_token_store(ndr, &ndr->switch_list, p, val);
666 retrieve a switch value
668 uint32_t ndr_push_get_switch_value(struct ndr_push *ndr, const void *p)
670 return ndr_token_peek(&ndr->switch_list, p);
673 uint32_t ndr_pull_get_switch_value(struct ndr_pull *ndr, const void *p)
675 return ndr_token_peek(&ndr->switch_list, p);
678 uint32_t ndr_print_get_switch_value(struct ndr_print *ndr, const void *p)
680 return ndr_token_peek(&ndr->switch_list, p);
684 pull a struct from a blob using NDR
686 NTSTATUS ndr_pull_struct_blob(const DATA_BLOB *blob, TALLOC_CTX *mem_ctx, void *p,
687 ndr_pull_flags_fn_t fn)
689 struct ndr_pull *ndr;
690 ndr = ndr_pull_init_blob(blob, mem_ctx);
692 return NT_STATUS_NO_MEMORY;
694 return fn(ndr, NDR_SCALARS|NDR_BUFFERS, p);
698 pull a struct from a blob using NDR - failing if all bytes are not consumed
700 NTSTATUS ndr_pull_struct_blob_all(const DATA_BLOB *blob, TALLOC_CTX *mem_ctx, void *p,
701 ndr_pull_flags_fn_t fn)
703 struct ndr_pull *ndr;
706 ndr = ndr_pull_init_blob(blob, mem_ctx);
708 return NT_STATUS_NO_MEMORY;
710 status = fn(ndr, NDR_SCALARS|NDR_BUFFERS, p);
711 if (!NT_STATUS_IS_OK(status)) return status;
712 if (ndr->offset < ndr->data_size) {
713 return NT_STATUS_PORT_MESSAGE_TOO_LONG;
719 pull a union from a blob using NDR, given the union discriminator
721 NTSTATUS ndr_pull_union_blob(const DATA_BLOB *blob, TALLOC_CTX *mem_ctx, void *p,
722 uint32_t level, ndr_pull_flags_fn_t fn)
724 struct ndr_pull *ndr;
727 ndr = ndr_pull_init_blob(blob, mem_ctx);
729 return NT_STATUS_NO_MEMORY;
731 ndr_pull_set_switch_value(ndr, p, level);
732 status = fn(ndr, NDR_SCALARS|NDR_BUFFERS, p);
733 if (!NT_STATUS_IS_OK(status)) return status;
734 if (ndr->offset != ndr->data_size) {
735 return NT_STATUS_BUFFER_TOO_SMALL;
741 push a struct to a blob using NDR
743 NTSTATUS ndr_push_struct_blob(DATA_BLOB *blob, TALLOC_CTX *mem_ctx, const void *p,
744 ndr_push_flags_fn_t fn)
747 struct ndr_push *ndr;
748 ndr = ndr_push_init_ctx(mem_ctx);
750 return NT_STATUS_NO_MEMORY;
752 status = fn(ndr, NDR_SCALARS|NDR_BUFFERS, p);
753 if (!NT_STATUS_IS_OK(status)) {
757 *blob = ndr_push_blob(ndr);
758 talloc_steal(mem_ctx, blob->data);
765 push a union to a blob using NDR
767 NTSTATUS ndr_push_union_blob(DATA_BLOB *blob, TALLOC_CTX *mem_ctx, void *p,
768 uint32_t level, ndr_push_flags_fn_t fn)
771 struct ndr_push *ndr;
772 ndr = ndr_push_init_ctx(mem_ctx);
774 return NT_STATUS_NO_MEMORY;
776 ndr_push_set_switch_value(ndr, p, level);
777 status = fn(ndr, NDR_SCALARS|NDR_BUFFERS, p);
778 if (!NT_STATUS_IS_OK(status)) {
782 *blob = ndr_push_blob(ndr);
783 talloc_steal(mem_ctx, blob->data);
790 generic ndr_size_*() handler for structures
792 size_t ndr_size_struct(const void *p, int flags, ndr_push_flags_fn_t push)
794 struct ndr_push *ndr;
798 /* avoid recursion */
799 if (flags & LIBNDR_FLAG_NO_NDR_SIZE) return 0;
801 ndr = ndr_push_init_ctx(NULL);
803 ndr->flags |= flags | LIBNDR_FLAG_NO_NDR_SIZE;
804 status = push(ndr, NDR_SCALARS|NDR_BUFFERS, p);
805 if (!NT_STATUS_IS_OK(status)) {
814 generic ndr_size_*() handler for unions
816 size_t ndr_size_union(const void *p, int flags, uint32_t level, ndr_push_flags_fn_t push)
818 struct ndr_push *ndr;
822 /* avoid recursion */
823 if (flags & LIBNDR_FLAG_NO_NDR_SIZE) return 0;
825 ndr = ndr_push_init_ctx(NULL);
827 ndr->flags |= flags | LIBNDR_FLAG_NO_NDR_SIZE;
828 ndr_push_set_switch_value(ndr, p, level);
829 status = push(ndr, NDR_SCALARS|NDR_BUFFERS, p);
830 if (!NT_STATUS_IS_OK(status)) {
839 get the current base for relative pointers for the push
841 uint32_t ndr_push_get_relative_base_offset(struct ndr_push *ndr)
843 return ndr->relative_base_offset;
847 restore the old base for relative pointers for the push
849 void ndr_push_restore_relative_base_offset(struct ndr_push *ndr, uint32_t offset)
851 ndr->relative_base_offset = offset;
855 setup the current base for relative pointers for the push
856 called in the NDR_SCALAR stage
858 NTSTATUS ndr_push_setup_relative_base_offset1(struct ndr_push *ndr, const void *p, uint32_t offset)
860 ndr->relative_base_offset = offset;
861 return ndr_token_store(ndr, &ndr->relative_base_list, p, offset);
865 setup the current base for relative pointers for the push
866 called in the NDR_BUFFERS stage
868 NTSTATUS ndr_push_setup_relative_base_offset2(struct ndr_push *ndr, const void *p)
870 return ndr_token_retrieve(&ndr->relative_base_list, p, &ndr->relative_base_offset);
874 push a relative object - stage1
875 this is called during SCALARS processing
877 NTSTATUS ndr_push_relative_ptr1(struct ndr_push *ndr, const void *p)
880 NDR_CHECK(ndr_push_uint32(ndr, NDR_SCALARS, 0));
883 NDR_CHECK(ndr_push_align(ndr, 4));
884 NDR_CHECK(ndr_token_store(ndr, &ndr->relative_list, p, ndr->offset));
885 return ndr_push_uint32(ndr, NDR_SCALARS, 0xFFFFFFFF);
889 push a relative object - stage2
890 this is called during buffers processing
892 NTSTATUS ndr_push_relative_ptr2(struct ndr_push *ndr, const void *p)
894 struct ndr_push_save save;
895 uint32_t ptr_offset = 0xFFFFFFFF;
899 ndr_push_save(ndr, &save);
900 NDR_CHECK(ndr_token_retrieve(&ndr->relative_list, p, &ptr_offset));
901 if (ptr_offset > ndr->offset) {
902 return ndr_push_error(ndr, NDR_ERR_BUFSIZE,
903 "ndr_push_relative_ptr2 ptr_offset(%u) > ndr->offset(%u)",
904 ptr_offset, ndr->offset);
906 ndr->offset = ptr_offset;
907 if (save.offset < ndr->relative_base_offset) {
908 return ndr_push_error(ndr, NDR_ERR_BUFSIZE,
909 "ndr_push_relative_ptr2 save.offset(%u) < ndr->relative_base_offset(%u)",
910 save.offset, ndr->relative_base_offset);
912 NDR_CHECK(ndr_push_uint32(ndr, NDR_SCALARS, save.offset - ndr->relative_base_offset));
913 ndr_push_restore(ndr, &save);
918 get the current base for relative pointers for the pull
920 uint32_t ndr_pull_get_relative_base_offset(struct ndr_pull *ndr)
922 return ndr->relative_base_offset;
926 restore the old base for relative pointers for the pull
928 void ndr_pull_restore_relative_base_offset(struct ndr_pull *ndr, uint32_t offset)
930 ndr->relative_base_offset = offset;
934 setup the current base for relative pointers for the pull
935 called in the NDR_SCALAR stage
937 NTSTATUS ndr_pull_setup_relative_base_offset1(struct ndr_pull *ndr, const void *p, uint32_t offset)
939 ndr->relative_base_offset = offset;
940 return ndr_token_store(ndr, &ndr->relative_base_list, p, offset);
944 setup the current base for relative pointers for the pull
945 called in the NDR_BUFFERS stage
947 NTSTATUS ndr_pull_setup_relative_base_offset2(struct ndr_pull *ndr, const void *p)
949 return ndr_token_retrieve(&ndr->relative_base_list, p, &ndr->relative_base_offset);
953 pull a relative object - stage1
954 called during SCALARS processing
956 NTSTATUS ndr_pull_relative_ptr1(struct ndr_pull *ndr, const void *p, uint32_t rel_offset)
958 rel_offset += ndr->relative_base_offset;
959 if (rel_offset > ndr->data_size) {
960 return ndr_pull_error(ndr, NDR_ERR_BUFSIZE,
961 "ndr_pull_relative_ptr1 rel_offset(%u) > ndr->data_size(%u)",
962 rel_offset, ndr->data_size);
964 return ndr_token_store(ndr, &ndr->relative_list, p, rel_offset);
968 pull a relative object - stage2
969 called during BUFFERS processing
971 NTSTATUS ndr_pull_relative_ptr2(struct ndr_pull *ndr, const void *p)
974 NDR_CHECK(ndr_token_retrieve(&ndr->relative_list, p, &rel_offset));
975 return ndr_pull_set_offset(ndr, rel_offset);