2 Unix SMB/CIFS implementation.
6 Copyright (C) Andrew Tridgell 2003
7 Copyright (C) Jelmer Vernooij 2005-2008
9 This program is free software; you can redistribute it and/or modify
10 it under the terms of the GNU General Public License as published by
11 the Free Software Foundation; either version 3 of the License, or
12 (at your option) any later version.
14 This program is distributed in the hope that it will be useful,
15 but WITHOUT ANY WARRANTY; without even the implied warranty of
16 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17 GNU General Public License for more details.
19 You should have received a copy of the GNU General Public License
20 along with this program. If not, see <http://www.gnu.org/licenses/>.
24 this provides the core routines for NDR parsing functions
26 see http://www.opengroup.org/onlinepubs/9629399/chap14.htm for details
31 #include "librpc/ndr/libndr.h"
32 #include "../lib/util/dlinklist.h"
35 #define DBGC_CLASS DBGC_RPC_PARSE
37 #define NDR_BASE_MARSHALL_SIZE 1024
40 * This value is arbitary, but designed to reduce the memory a client
41 * can allocate and the work the client can force in processing a
44 * In an ideal world this would be controlled by range() restrictions
45 * on array sizes and careful IDL construction to avoid arbitary
46 * linked lists, but this is a backstop for now.
48 #define NDR_TOKEN_MAX_LIST_SIZE 65535
50 /* this guid indicates NDR encoding in a protocol tower */
51 const struct ndr_syntax_id ndr_transfer_syntax_ndr = {
52 { 0x8a885d04, 0x1ceb, 0x11c9, {0x9f, 0xe8}, {0x08,0x00,0x2b,0x10,0x48,0x60} },
56 const struct ndr_syntax_id ndr_transfer_syntax_ndr64 = {
57 { 0x71710533, 0xbeba, 0x4937, {0x83, 0x19}, {0xb5,0xdb,0xef,0x9c,0xcc,0x36} },
61 const struct ndr_syntax_id ndr_syntax_id_null = {
62 { 0, 0, 0, { 0, 0 }, { 0, 0, 0, 0, 0, 0 } },
67 work out the number of bytes needed to align on a n byte boundary
69 _PUBLIC_ size_t ndr_align_size(uint32_t offset, size_t n)
71 if ((offset & (n-1)) == 0) return 0;
72 return n - (offset & (n-1));
76 initialise a ndr parse structure from a data blob
78 _PUBLIC_ struct ndr_pull *ndr_pull_init_blob(const DATA_BLOB *blob, TALLOC_CTX *mem_ctx)
82 ndr = talloc_zero(mem_ctx, struct ndr_pull);
83 if (!ndr) return NULL;
84 ndr->current_mem_ctx = mem_ctx;
86 ndr->data = blob->data;
87 ndr->data_size = blob->length;
92 _PUBLIC_ enum ndr_err_code ndr_pull_append(struct ndr_pull *ndr, DATA_BLOB *blob)
94 enum ndr_err_code ndr_err;
99 if (blob->length == 0) {
100 return NDR_ERR_SUCCESS;
103 ndr_err = ndr_token_retrieve(&ndr->array_size_list, ndr, &append);
104 if (ndr_err == NDR_ERR_TOKEN) {
106 ndr_err = NDR_ERR_SUCCESS;
110 if (ndr->data_size == 0) {
115 if (append == UINT32_MAX) {
117 * append == UINT32_MAX means that
118 * ndr->data is either NULL or a valid
119 * talloc child of ndr, which means
120 * we can use data_blob_append() without
121 * data_blob_talloc() of the existing callers data
123 b = data_blob_const(ndr->data, ndr->data_size);
125 b = data_blob_talloc(ndr, ndr->data, ndr->data_size);
126 if (b.data == NULL) {
127 return ndr_pull_error(ndr, NDR_ERR_ALLOC, "%s", __location__);
131 ok = data_blob_append(ndr, &b, blob->data, blob->length);
133 return ndr_pull_error(ndr, NDR_ERR_ALLOC, "%s", __location__);
137 ndr->data_size = b.length;
139 return ndr_token_store(ndr, &ndr->array_size_list, ndr, UINT32_MAX);
142 _PUBLIC_ enum ndr_err_code ndr_pull_pop(struct ndr_pull *ndr)
147 if (ndr->relative_base_offset != 0) {
148 return ndr_pull_error(ndr, NDR_ERR_RELATIVE,
151 if (ndr->relative_highest_offset != 0) {
152 return ndr_pull_error(ndr, NDR_ERR_RELATIVE,
155 if (ndr->relative_list.count != 0) {
156 return ndr_pull_error(ndr, NDR_ERR_RELATIVE,
159 if (ndr->relative_base_list.count != 0) {
160 return ndr_pull_error(ndr, NDR_ERR_RELATIVE,
165 * we need to keep up to 7 bytes
166 * in order to get the aligment right.
168 skip = ndr->offset & 0xFFFFFFF8;
171 return NDR_ERR_SUCCESS;
175 ndr->data_size -= skip;
177 append = ndr_token_peek(&ndr->array_size_list, ndr);
178 if (append != UINT32_MAX) {
180 * here we assume, that ndr->data is not a
181 * talloc child of ndr.
184 return NDR_ERR_SUCCESS;
187 memmove(ndr->data, ndr->data + skip, ndr->data_size);
189 ndr->data = talloc_realloc(ndr, ndr->data, uint8_t, ndr->data_size);
190 if (ndr->data_size != 0 && ndr->data == NULL) {
191 return ndr_pull_error(ndr, NDR_ERR_ALLOC, "%s", __location__);
194 return NDR_ERR_SUCCESS;
198 advance by 'size' bytes
200 _PUBLIC_ enum ndr_err_code ndr_pull_advance(struct ndr_pull *ndr, uint32_t size)
203 if (ndr->offset > ndr->data_size) {
204 return ndr_pull_error(ndr, NDR_ERR_BUFSIZE,
205 "ndr_pull_advance by %u failed",
208 return NDR_ERR_SUCCESS;
212 set the parse offset to 'ofs'
214 static enum ndr_err_code ndr_pull_set_offset(struct ndr_pull *ndr, uint32_t ofs)
217 if (ndr->offset > ndr->data_size) {
218 return ndr_pull_error(ndr, NDR_ERR_BUFSIZE,
219 "ndr_pull_set_offset %u failed",
222 return NDR_ERR_SUCCESS;
225 /* create a ndr_push structure, ready for some marshalling */
226 _PUBLIC_ struct ndr_push *ndr_push_init_ctx(TALLOC_CTX *mem_ctx)
228 struct ndr_push *ndr;
230 ndr = talloc_zero(mem_ctx, struct ndr_push);
236 ndr->alloc_size = NDR_BASE_MARSHALL_SIZE;
237 ndr->data = talloc_array(ndr, uint8_t, ndr->alloc_size);
246 /* return a DATA_BLOB structure for the current ndr_push marshalled data */
247 _PUBLIC_ DATA_BLOB ndr_push_blob(struct ndr_push *ndr)
250 blob = data_blob_const(ndr->data, ndr->offset);
251 if (ndr->alloc_size > ndr->offset) {
252 ndr->data[ndr->offset] = 0;
259 expand the available space in the buffer to ndr->offset + extra_size
261 _PUBLIC_ enum ndr_err_code ndr_push_expand(struct ndr_push *ndr, uint32_t extra_size)
263 uint32_t size = extra_size + ndr->offset;
265 if (size < ndr->offset) {
266 /* extra_size overflowed the offset */
267 return ndr_push_error(ndr, NDR_ERR_BUFSIZE, "Overflow in push_expand to %u",
271 if (ndr->fixed_buf_size) {
272 if (ndr->alloc_size >= size) {
273 return NDR_ERR_SUCCESS;
275 return ndr_push_error(ndr,
277 "Overflow of fixed buffer in "
282 if (ndr->alloc_size > size) {
283 return NDR_ERR_SUCCESS;
286 ndr->alloc_size += NDR_BASE_MARSHALL_SIZE;
287 if (size+1 > ndr->alloc_size) {
288 ndr->alloc_size = size+1;
290 ndr->data = talloc_realloc(ndr, ndr->data, uint8_t, ndr->alloc_size);
292 return ndr_push_error(ndr, NDR_ERR_ALLOC, "Failed to push_expand to %u",
296 return NDR_ERR_SUCCESS;
299 _PUBLIC_ void ndr_print_debugc_helper(struct ndr_print *ndr, const char *format, ...)
307 va_start(ap, format);
308 ret = vasprintf(&s, format, ap);
315 dbgc_class = *(int *)ndr->private_data;
317 if (ndr->no_newline) {
318 DEBUGADDC(dbgc_class, 1,("%s", s));
323 for (i=0;i<ndr->depth;i++) {
324 DEBUGADDC(dbgc_class, 1,(" "));
327 DEBUGADDC(dbgc_class, 1,("%s\n", s));
331 _PUBLIC_ void ndr_print_debug_helper(struct ndr_print *ndr, const char *format, ...)
338 va_start(ap, format);
339 ret = vasprintf(&s, format, ap);
346 if (ndr->no_newline) {
347 DEBUGADD(1,("%s", s));
352 for (i=0;i<ndr->depth;i++) {
356 DEBUGADD(1,("%s\n", s));
360 _PUBLIC_ void ndr_print_printf_helper(struct ndr_print *ndr, const char *format, ...)
365 if (!ndr->no_newline) {
366 for (i=0;i<ndr->depth;i++) {
371 va_start(ap, format);
374 if (!ndr->no_newline) {
379 _PUBLIC_ void ndr_print_string_helper(struct ndr_print *ndr, const char *format, ...)
384 if (!ndr->no_newline) {
385 for (i=0;i<ndr->depth;i++) {
386 ndr->private_data = talloc_asprintf_append_buffer(
387 (char *)ndr->private_data, " ");
391 va_start(ap, format);
392 ndr->private_data = talloc_vasprintf_append_buffer((char *)ndr->private_data,
395 if (!ndr->no_newline) {
396 ndr->private_data = talloc_asprintf_append_buffer((char *)ndr->private_data,
402 a useful helper function for printing idl structures via DEBUGC()
404 _PUBLIC_ void ndr_print_debugc(int dbgc_class, ndr_print_fn_t fn, const char *name, void *ptr)
406 struct ndr_print *ndr;
408 DEBUGC(dbgc_class, 1,(" "));
410 ndr = talloc_zero(NULL, struct ndr_print);
412 ndr->private_data = &dbgc_class;
413 ndr->print = ndr_print_debugc_helper;
416 #ifdef DEBUG_PASSWORD
417 if (CHECK_DEBUGLVL(100)) {
418 ndr->print_secrets = true;
427 a useful helper function for printing idl structures via DEBUG()
429 _PUBLIC_ void ndr_print_debug(ndr_print_fn_t fn, const char *name, void *ptr)
431 struct ndr_print *ndr;
435 ndr = talloc_zero(NULL, struct ndr_print);
437 ndr->print = ndr_print_debug_helper;
440 #ifdef DEBUG_PASSWORD
441 if (CHECK_DEBUGLVL(100)) {
442 ndr->print_secrets = true;
451 a useful helper function for printing idl unions via DEBUG()
453 _PUBLIC_ void ndr_print_union_debug(ndr_print_fn_t fn, const char *name, uint32_t level, void *ptr)
455 struct ndr_print *ndr;
459 ndr = talloc_zero(NULL, struct ndr_print);
461 ndr->print = ndr_print_debug_helper;
464 #ifdef DEBUG_PASSWORD
465 if (CHECK_DEBUGLVL(100)) {
466 ndr->print_secrets = true;
470 ndr_print_set_switch_value(ndr, ptr, level);
476 a useful helper function for printing idl function calls via DEBUG()
478 _PUBLIC_ void ndr_print_function_debug(ndr_print_function_t fn, const char *name, int flags, void *ptr)
480 struct ndr_print *ndr;
484 ndr = talloc_zero(NULL, struct ndr_print);
486 ndr->print = ndr_print_debug_helper;
489 #ifdef DEBUG_PASSWORD
490 if (CHECK_DEBUGLVL(100)) {
491 ndr->print_secrets = true;
495 fn(ndr, name, flags, ptr);
500 a useful helper function for printing idl structures to a string
502 _PUBLIC_ char *ndr_print_struct_string(TALLOC_CTX *mem_ctx, ndr_print_fn_t fn, const char *name, void *ptr)
504 struct ndr_print *ndr;
507 ndr = talloc_zero(mem_ctx, struct ndr_print);
508 if (!ndr) return NULL;
509 ndr->private_data = talloc_strdup(ndr, "");
510 if (!ndr->private_data) {
513 ndr->print = ndr_print_string_helper;
518 ret = talloc_steal(mem_ctx, (char *)ndr->private_data);
525 a useful helper function for printing idl unions to a string
527 _PUBLIC_ char *ndr_print_union_string(TALLOC_CTX *mem_ctx, ndr_print_fn_t fn, const char *name, uint32_t level, void *ptr)
529 struct ndr_print *ndr;
532 ndr = talloc_zero(mem_ctx, struct ndr_print);
533 if (!ndr) return NULL;
534 ndr->private_data = talloc_strdup(ndr, "");
535 if (!ndr->private_data) {
538 ndr->print = ndr_print_string_helper;
541 ndr_print_set_switch_value(ndr, ptr, level);
543 ret = talloc_steal(mem_ctx, (char *)ndr->private_data);
550 a useful helper function for printing idl function calls to a string
552 _PUBLIC_ char *ndr_print_function_string(TALLOC_CTX *mem_ctx,
553 ndr_print_function_t fn, const char *name,
554 int flags, void *ptr)
556 struct ndr_print *ndr;
559 ndr = talloc_zero(mem_ctx, struct ndr_print);
560 if (!ndr) return NULL;
561 ndr->private_data = talloc_strdup(ndr, "");
562 if (!ndr->private_data) {
565 ndr->print = ndr_print_string_helper;
568 fn(ndr, name, flags, ptr);
569 ret = talloc_steal(mem_ctx, (char *)ndr->private_data);
575 _PUBLIC_ void ndr_set_flags(uint32_t *pflags, uint32_t new_flags)
577 /* the big/little endian flags are inter-dependent */
578 if (new_flags & LIBNDR_FLAG_LITTLE_ENDIAN) {
579 (*pflags) &= ~LIBNDR_FLAG_BIGENDIAN;
580 (*pflags) &= ~LIBNDR_FLAG_NDR64;
582 if (new_flags & LIBNDR_FLAG_BIGENDIAN) {
583 (*pflags) &= ~LIBNDR_FLAG_LITTLE_ENDIAN;
584 (*pflags) &= ~LIBNDR_FLAG_NDR64;
586 if (new_flags & LIBNDR_ALIGN_FLAGS) {
587 /* Ensure we only have the passed-in
588 align flag set in the new_flags,
589 remove any old align flag. */
590 (*pflags) &= ~LIBNDR_ALIGN_FLAGS;
592 if (new_flags & LIBNDR_FLAG_NO_RELATIVE_REVERSE) {
593 (*pflags) &= ~LIBNDR_FLAG_RELATIVE_REVERSE;
595 (*pflags) |= new_flags;
599 return and possibly log an NDR error
601 _PUBLIC_ enum ndr_err_code _ndr_pull_error(struct ndr_pull *ndr,
602 enum ndr_err_code ndr_err,
603 const char *function,
604 const char *location,
605 const char *format, ...)
611 if (ndr->flags & LIBNDR_FLAG_INCOMPLETE_BUFFER) {
613 case NDR_ERR_BUFSIZE:
614 return NDR_ERR_INCOMPLETE_BUFFER;
620 va_start(ap, format);
621 ret = vasprintf(&s, format, ap);
625 return NDR_ERR_ALLOC;
628 D_WARNING("%s: ndr_pull_error(%s): %s at %s\n",
630 ndr_map_error2string(ndr_err),
640 return and possibly log an NDR error
642 _PUBLIC_ enum ndr_err_code _ndr_push_error(struct ndr_push *ndr,
643 enum ndr_err_code ndr_err,
644 const char *function,
645 const char *location,
646 const char *format, ...)
652 va_start(ap, format);
653 ret = vasprintf(&s, format, ap);
657 return NDR_ERR_ALLOC;
660 D_WARNING("%s: ndr_push_error(%s): %s at %s\n",
662 ndr_map_error2string(ndr_err),
672 handle subcontext buffers, which in midl land are user-marshalled, but
673 we use magic in pidl to make them easier to cope with
675 _PUBLIC_ enum ndr_err_code ndr_pull_subcontext_start(struct ndr_pull *ndr,
676 struct ndr_pull **_subndr,
680 struct ndr_pull *subndr;
681 uint32_t r_content_size;
682 bool force_le = false;
683 bool force_be = false;
685 switch (header_size) {
687 uint32_t content_size = ndr->data_size - ndr->offset;
689 content_size = size_is;
691 r_content_size = content_size;
696 uint16_t content_size;
697 NDR_CHECK(ndr_pull_uint16(ndr, NDR_SCALARS, &content_size));
698 if (size_is >= 0 && size_is != content_size) {
699 return ndr_pull_error(ndr, NDR_ERR_SUBCONTEXT, "Bad subcontext (PULL) size_is(%d) (0x%04x) mismatch content_size %d (0x%04x)",
700 (int)size_is, (int)size_is,
704 r_content_size = content_size;
709 uint32_t content_size;
710 NDR_CHECK(ndr_pull_uint3264(ndr, NDR_SCALARS, &content_size));
711 if (size_is >= 0 && size_is != content_size) {
712 return ndr_pull_error(ndr, NDR_ERR_SUBCONTEXT, "Bad subcontext (PULL) size_is(%d) (0x%08x) mismatch content_size %d (0x%08x)",
713 (int)size_is, (int)size_is,
717 r_content_size = content_size;
722 * Common Type Header for the Serialization Stream
723 * See [MS-RPCE] 2.2.6 Type Serialization Version 1
729 uint32_t content_size;
733 NDR_CHECK(ndr_pull_uint8(ndr, NDR_SCALARS, &version));
736 return ndr_pull_error(ndr, NDR_ERR_SUBCONTEXT,
737 "Bad subcontext (PULL) Common Type Header version %d != 1",
745 NDR_CHECK(ndr_pull_uint8(ndr, NDR_SCALARS, &drep));
748 } else if (drep == 0x00) {
751 return ndr_pull_error(ndr, NDR_ERR_SUBCONTEXT,
752 "Bad subcontext (PULL) Common Type Header invalid drep 0x%02X",
756 /* length of the "Private Header for Constructed Type" */
757 NDR_CHECK(ndr_pull_uint16(ndr, NDR_SCALARS, &hdrlen));
759 return ndr_pull_error(ndr, NDR_ERR_SUBCONTEXT,
760 "Bad subcontext (PULL) Common Type Header length %d != 8",
764 /* filler should be ignored */
765 NDR_CHECK(ndr_pull_uint32(ndr, NDR_SCALARS, &filler));
768 * Private Header for Constructed Type
770 /* length - will be updated latter */
771 NDR_CHECK(ndr_pull_uint32(ndr, NDR_SCALARS, &content_size));
772 if (size_is >= 0 && size_is != content_size) {
773 return ndr_pull_error(ndr, NDR_ERR_SUBCONTEXT, "Bad subcontext (PULL) size_is(%d) mismatch content_size %d",
774 (int)size_is, (int)content_size);
776 /* the content size must be a multiple of 8 */
777 if ((content_size % 8) != 0) {
778 return ndr_pull_error(ndr, NDR_ERR_SUBCONTEXT,
779 "Bad subcontext (PULL) size_is(%d) not padded to 8 content_size %d",
780 (int)size_is, (int)content_size);
782 r_content_size = content_size;
785 NDR_CHECK(ndr_pull_uint32(ndr, NDR_SCALARS, &reserved));
790 * a shallow copy like subcontext
791 * useful for DCERPC pipe chunks.
793 subndr = talloc_zero(ndr, struct ndr_pull);
794 NDR_ERR_HAVE_NO_MEMORY(subndr);
796 subndr->flags = ndr->flags;
797 subndr->current_mem_ctx = ndr->current_mem_ctx;
798 subndr->data = ndr->data;
799 subndr->offset = ndr->offset;
800 subndr->data_size = ndr->data_size;
803 return NDR_ERR_SUCCESS;
806 return ndr_pull_error(ndr, NDR_ERR_SUBCONTEXT, "Bad subcontext (PULL) header_size %d",
810 NDR_PULL_NEED_BYTES(ndr, r_content_size);
812 subndr = talloc_zero(ndr, struct ndr_pull);
813 NDR_ERR_HAVE_NO_MEMORY(subndr);
814 subndr->flags = ndr->flags & ~LIBNDR_FLAG_NDR64;
815 subndr->current_mem_ctx = ndr->current_mem_ctx;
817 subndr->data = ndr->data + ndr->offset;
819 subndr->data_size = r_content_size;
822 ndr_set_flags(&ndr->flags, LIBNDR_FLAG_LITTLE_ENDIAN);
823 } else if (force_be) {
824 ndr_set_flags(&ndr->flags, LIBNDR_FLAG_BIGENDIAN);
828 return NDR_ERR_SUCCESS;
831 _PUBLIC_ enum ndr_err_code ndr_pull_subcontext_end(struct ndr_pull *ndr,
832 struct ndr_pull *subndr,
837 uint32_t highest_ofs;
839 if (header_size == 0xFFFFFFFF) {
840 advance = subndr->offset - ndr->offset;
841 } else if (size_is >= 0) {
843 } else if (header_size > 0) {
844 advance = subndr->data_size;
846 advance = subndr->offset;
849 if (subndr->offset > ndr->relative_highest_offset) {
850 highest_ofs = subndr->offset;
852 highest_ofs = subndr->relative_highest_offset;
854 if (!(subndr->flags & LIBNDR_FLAG_SUBCONTEXT_NO_UNREAD_BYTES)) {
856 * avoid an error unless SUBCONTEXT_NO_UNREAD_BYTES is specified
858 highest_ofs = advance;
860 if (highest_ofs < advance) {
861 return ndr_pull_error(subndr, NDR_ERR_UNREAD_BYTES,
862 "not all bytes consumed ofs[%u] advance[%u]",
863 highest_ofs, advance);
866 NDR_CHECK(ndr_pull_advance(ndr, advance));
867 return NDR_ERR_SUCCESS;
870 _PUBLIC_ enum ndr_err_code ndr_push_subcontext_start(struct ndr_push *ndr,
871 struct ndr_push **_subndr,
875 struct ndr_push *subndr;
877 subndr = ndr_push_init_ctx(ndr);
878 NDR_ERR_HAVE_NO_MEMORY(subndr);
879 subndr->flags = ndr->flags & ~LIBNDR_FLAG_NDR64;
882 NDR_CHECK(ndr_push_zero(subndr, size_is));
884 subndr->relative_end_offset = size_is;
888 return NDR_ERR_SUCCESS;
892 push a subcontext header
894 _PUBLIC_ enum ndr_err_code ndr_push_subcontext_end(struct ndr_push *ndr,
895 struct ndr_push *subndr,
902 padding_len = size_is - subndr->offset;
903 if (padding_len < 0) {
904 return ndr_push_error(ndr, NDR_ERR_SUBCONTEXT, "Bad subcontext (PUSH) content_size %d is larger than size_is(%d)",
905 (int)subndr->offset, (int)size_is);
907 subndr->offset = size_is;
910 switch (header_size) {
915 NDR_CHECK(ndr_push_uint16(ndr, NDR_SCALARS, subndr->offset));
919 NDR_CHECK(ndr_push_uint3264(ndr, NDR_SCALARS, subndr->offset));
924 * Common Type Header for the Serialization Stream
925 * See [MS-RPCE] 2.2.6 Type Serialization Version 1
927 padding_len = NDR_ROUND(subndr->offset, 8) - subndr->offset;
928 if (padding_len > 0) {
929 NDR_CHECK(ndr_push_zero(subndr, padding_len));
933 NDR_CHECK(ndr_push_uint8(ndr, NDR_SCALARS, 1));
939 NDR_CHECK(ndr_push_uint8(ndr, NDR_SCALARS, NDR_BE(ndr)?0x00:0x10));
941 /* length of the "Private Header for Constructed Type" */
942 NDR_CHECK(ndr_push_uint16(ndr, NDR_SCALARS, 8));
945 NDR_CHECK(ndr_push_uint32(ndr, NDR_SCALARS, 0xCCCCCCCC));
948 * Private Header for Constructed Type
950 /* length - will be updated latter */
951 NDR_CHECK(ndr_push_uint32(ndr, NDR_SCALARS, subndr->offset));
954 NDR_CHECK(ndr_push_uint32(ndr, NDR_SCALARS, 0));
958 return ndr_push_error(ndr, NDR_ERR_SUBCONTEXT, "Bad subcontext header size %d",
962 NDR_CHECK(ndr_push_bytes(ndr, subndr->data, subndr->offset));
963 return NDR_ERR_SUCCESS;
973 store a token in the ndr context, for later retrieval
975 _PUBLIC_ enum ndr_err_code ndr_token_store(TALLOC_CTX *mem_ctx,
976 struct ndr_token_list *list,
980 if (list->tokens == NULL) {
981 list->tokens = talloc_array(mem_ctx, struct ndr_token, 10);
982 if (list->tokens == NULL) {
983 NDR_ERR_HAVE_NO_MEMORY(list->tokens);
986 struct ndr_token *new_tokens = NULL;
987 uint32_t alloc_count = talloc_array_length(list->tokens);
990 * Check every time we have not allocated too many
991 * tokens. This ensures developer sanity when
992 * debugging the boundary condition
994 if (list->count >= NDR_TOKEN_MAX_LIST_SIZE) {
995 return NDR_ERR_RANGE;
997 if (list->count == alloc_count) {
1000 * Double the list, until we start in chunks
1003 unsigned increment = MIN(list->count, 1000);
1004 new_alloc = alloc_count + increment;
1005 if (new_alloc < alloc_count) {
1006 return NDR_ERR_RANGE;
1008 new_tokens = talloc_realloc(mem_ctx, list->tokens,
1009 struct ndr_token, new_alloc);
1010 NDR_ERR_HAVE_NO_MEMORY(new_tokens);
1011 list->tokens = new_tokens;
1014 list->tokens[list->count].key = key;
1015 list->tokens[list->count].value = value;
1017 return NDR_ERR_SUCCESS;
1021 retrieve a token from a ndr context, using cmp_fn to match the tokens
1023 _PUBLIC_ enum ndr_err_code ndr_token_retrieve_cmp_fn(struct ndr_token_list *list,
1024 const void *key, uint32_t *v,
1025 comparison_fn_t _cmp_fn,
1028 struct ndr_token *tokens = list->tokens;
1031 for (i = list->count - 1; i < list->count; i--) {
1032 if (_cmp_fn(tokens[i].key, key) == 0) {
1037 for (i = list->count - 1; i < list->count; i--) {
1038 if (tokens[i].key == key) {
1043 return NDR_ERR_TOKEN;
1045 *v = tokens[i].value;
1047 if (i != list->count - 1) {
1048 tokens[i] = tokens[list->count - 1];
1052 return NDR_ERR_SUCCESS;
1056 retrieve a token from a ndr context
1058 _PUBLIC_ enum ndr_err_code ndr_token_retrieve(struct ndr_token_list *list,
1059 const void *key, uint32_t *v)
1061 return ndr_token_retrieve_cmp_fn(list, key, v, NULL, true);
1065 peek at but don't removed a token from a ndr context
1067 _PUBLIC_ uint32_t ndr_token_peek(struct ndr_token_list *list, const void *key)
1070 struct ndr_token *tokens = list->tokens;
1072 for (i = list->count - 1; i < list->count; i--) {
1073 if (tokens[i].key == key) {
1074 return tokens[i].value;
1082 pull an array size field and add it to the array_size_list token list
1084 _PUBLIC_ enum ndr_err_code ndr_pull_array_size(struct ndr_pull *ndr, const void *p)
1086 enum ndr_err_code ret;
1088 NDR_CHECK(ndr_pull_uint3264(ndr, NDR_SCALARS, &size));
1089 ret = ndr_token_store(ndr, &ndr->array_size_list, p, size);
1090 if (ret == NDR_ERR_RANGE) {
1091 return ndr_pull_error(ndr, ret,
1092 "More than %d NDR tokens stored for array_size",
1093 NDR_TOKEN_MAX_LIST_SIZE);
1099 get the stored array size field
1101 _PUBLIC_ uint32_t ndr_get_array_size(struct ndr_pull *ndr, const void *p)
1103 return ndr_token_peek(&ndr->array_size_list, p);
1107 check the stored array size field
1109 _PUBLIC_ enum ndr_err_code ndr_check_array_size(struct ndr_pull *ndr, void *p, uint32_t size)
1112 stored = ndr_token_peek(&ndr->array_size_list, p);
1113 if (stored != size) {
1114 return ndr_pull_error(ndr, NDR_ERR_ARRAY_SIZE,
1115 "Bad array size - got %u expected %u\n",
1118 return NDR_ERR_SUCCESS;
1122 pull an array length field and add it to the array_length_list token list
1124 _PUBLIC_ enum ndr_err_code ndr_pull_array_length(struct ndr_pull *ndr, const void *p)
1126 enum ndr_err_code ret;
1127 uint32_t length, offset;
1128 NDR_CHECK(ndr_pull_uint3264(ndr, NDR_SCALARS, &offset));
1130 return ndr_pull_error(ndr, NDR_ERR_ARRAY_SIZE,
1131 "non-zero array offset %u\n", offset);
1133 NDR_CHECK(ndr_pull_uint3264(ndr, NDR_SCALARS, &length));
1134 ret = ndr_token_store(ndr, &ndr->array_length_list, p, length);
1135 if (ret == NDR_ERR_RANGE) {
1136 return ndr_pull_error(ndr, ret,
1137 "More than %d NDR tokens stored for array_length_list",
1138 NDR_TOKEN_MAX_LIST_SIZE);
1144 get the stored array length field
1146 _PUBLIC_ uint32_t ndr_get_array_length(struct ndr_pull *ndr, const void *p)
1148 return ndr_token_peek(&ndr->array_length_list, p);
1152 check the stored array length field
1154 _PUBLIC_ enum ndr_err_code ndr_check_array_length(struct ndr_pull *ndr, void *p, uint32_t length)
1157 stored = ndr_token_peek(&ndr->array_length_list, p);
1158 if (stored != length) {
1159 return ndr_pull_error(ndr, NDR_ERR_ARRAY_SIZE,
1160 "Bad array length - got %u expected %u\n",
1163 return NDR_ERR_SUCCESS;
1166 _PUBLIC_ enum ndr_err_code ndr_push_pipe_chunk_trailer(struct ndr_push *ndr, int ndr_flags, uint32_t count)
1168 if (ndr->flags & LIBNDR_FLAG_NDR64) {
1169 int64_t tmp = 0 - (int64_t)count;
1170 uint64_t ncount = tmp;
1172 NDR_CHECK(ndr_push_hyper(ndr, ndr_flags, ncount));
1175 return NDR_ERR_SUCCESS;
1178 _PUBLIC_ enum ndr_err_code ndr_check_pipe_chunk_trailer(struct ndr_pull *ndr, int ndr_flags, uint32_t count)
1180 if (ndr->flags & LIBNDR_FLAG_NDR64) {
1181 int64_t tmp = 0 - (int64_t)count;
1182 uint64_t ncount1 = tmp;
1185 NDR_CHECK(ndr_pull_hyper(ndr, ndr_flags, &ncount2));
1186 if (ncount1 == ncount2) {
1187 return NDR_ERR_SUCCESS;
1190 return ndr_pull_error(ndr, NDR_ERR_ARRAY_SIZE,
1191 "Bad pipe trailer[%lld should be %lld] size was %lu\"",
1192 (unsigned long long)ncount2,
1193 (unsigned long long)ncount1,
1194 (unsigned long)count);
1197 return NDR_ERR_SUCCESS;
1201 store a switch value
1203 _PUBLIC_ enum ndr_err_code ndr_push_set_switch_value(struct ndr_push *ndr, const void *p, uint32_t val)
1205 enum ndr_err_code ret =
1206 ndr_token_store(ndr, &ndr->switch_list, p, val);
1207 if (ret == NDR_ERR_RANGE) {
1208 return ndr_push_error(ndr, ret,
1209 "More than %d NDR tokens stored for switch_list",
1210 NDR_TOKEN_MAX_LIST_SIZE);
1215 _PUBLIC_ enum ndr_err_code ndr_pull_set_switch_value(struct ndr_pull *ndr, const void *p, uint32_t val)
1218 enum ndr_err_code ret =
1219 ndr_token_store(ndr, &ndr->switch_list, p, val);
1220 if (ret == NDR_ERR_RANGE) {
1221 return ndr_pull_error(ndr, ret,
1222 "More than %d NDR tokens stored for switch_list",
1223 NDR_TOKEN_MAX_LIST_SIZE);
1228 _PUBLIC_ enum ndr_err_code ndr_print_set_switch_value(struct ndr_print *ndr, const void *p, uint32_t val)
1230 return ndr_token_store(ndr, &ndr->switch_list, p, val);
1234 retrieve a switch value
1236 _PUBLIC_ uint32_t ndr_push_get_switch_value(struct ndr_push *ndr, const void *p)
1238 return ndr_token_peek(&ndr->switch_list, p);
1241 _PUBLIC_ uint32_t ndr_pull_get_switch_value(struct ndr_pull *ndr, const void *p)
1243 return ndr_token_peek(&ndr->switch_list, p);
1246 _PUBLIC_ uint32_t ndr_print_get_switch_value(struct ndr_print *ndr, const void *p)
1248 return ndr_token_peek(&ndr->switch_list, p);
1251 /* retrieve a switch value and remove it from the list */
1252 _PUBLIC_ uint32_t ndr_pull_steal_switch_value(struct ndr_pull *ndr, const void *p)
1254 enum ndr_err_code status;
1257 status = ndr_token_retrieve(&ndr->switch_list, p, &v);
1258 if (!NDR_ERR_CODE_IS_SUCCESS(status)) {
1266 pull a struct from a blob using NDR
1268 _PUBLIC_ enum ndr_err_code ndr_pull_struct_blob(const DATA_BLOB *blob, TALLOC_CTX *mem_ctx, void *p,
1269 ndr_pull_flags_fn_t fn)
1271 struct ndr_pull *ndr;
1272 ndr = ndr_pull_init_blob(blob, mem_ctx);
1273 NDR_ERR_HAVE_NO_MEMORY(ndr);
1274 NDR_CHECK_FREE(fn(ndr, NDR_SCALARS|NDR_BUFFERS, p));
1276 return NDR_ERR_SUCCESS;
1280 pull a struct from a blob using NDR - failing if all bytes are not consumed
1282 _PUBLIC_ enum ndr_err_code ndr_pull_struct_blob_all(const DATA_BLOB *blob, TALLOC_CTX *mem_ctx,
1283 void *p, ndr_pull_flags_fn_t fn)
1285 struct ndr_pull *ndr;
1286 uint32_t highest_ofs;
1287 ndr = ndr_pull_init_blob(blob, mem_ctx);
1288 NDR_ERR_HAVE_NO_MEMORY(ndr);
1289 NDR_CHECK_FREE(fn(ndr, NDR_SCALARS|NDR_BUFFERS, p));
1290 if (ndr->offset > ndr->relative_highest_offset) {
1291 highest_ofs = ndr->offset;
1293 highest_ofs = ndr->relative_highest_offset;
1295 if (highest_ofs < ndr->data_size) {
1296 enum ndr_err_code ret;
1297 ret = ndr_pull_error(ndr, NDR_ERR_UNREAD_BYTES,
1298 "not all bytes consumed ofs[%u] size[%u]",
1299 highest_ofs, ndr->data_size);
1304 return NDR_ERR_SUCCESS;
1308 pull a struct from a blob using NDR - failing if all bytes are not consumed
1310 This only works for structures with NO allocated memory, like
1311 objectSID and GUID. This helps because we parse these a lot.
1313 _PUBLIC_ enum ndr_err_code ndr_pull_struct_blob_all_noalloc(const DATA_BLOB *blob,
1314 void *p, ndr_pull_flags_fn_t fn)
1317 * We init this structure on the stack here, to avoid a
1318 * talloc() as otherwise this call to the fn() is assured not
1319 * to be doing any allocation, eg SIDs and GUIDs.
1321 * This allows us to keep the safety of the PIDL-generated
1322 * code without the talloc() overhead.
1324 struct ndr_pull ndr = {
1326 .data_size = blob->length,
1327 .current_mem_ctx = (void *)-1
1329 uint32_t highest_ofs;
1330 NDR_CHECK(fn(&ndr, NDR_SCALARS|NDR_BUFFERS, p));
1331 if (ndr.offset > ndr.relative_highest_offset) {
1332 highest_ofs = ndr.offset;
1334 highest_ofs = ndr.relative_highest_offset;
1336 if (highest_ofs < ndr.data_size) {
1337 enum ndr_err_code ret;
1338 ret = ndr_pull_error(&ndr, NDR_ERR_UNREAD_BYTES,
1339 "not all bytes consumed ofs[%u] size[%u]",
1340 highest_ofs, ndr.data_size);
1343 return NDR_ERR_SUCCESS;
1347 pull a union from a blob using NDR, given the union discriminator
1349 _PUBLIC_ enum ndr_err_code ndr_pull_union_blob(const DATA_BLOB *blob, TALLOC_CTX *mem_ctx,
1351 uint32_t level, ndr_pull_flags_fn_t fn)
1353 struct ndr_pull *ndr;
1354 ndr = ndr_pull_init_blob(blob, mem_ctx);
1355 NDR_ERR_HAVE_NO_MEMORY(ndr);
1356 NDR_CHECK_FREE(ndr_pull_set_switch_value(ndr, p, level));
1357 NDR_CHECK_FREE(fn(ndr, NDR_SCALARS|NDR_BUFFERS, p));
1359 return NDR_ERR_SUCCESS;
1363 pull a union from a blob using NDR, given the union discriminator,
1364 failing if all bytes are not consumed
1366 _PUBLIC_ enum ndr_err_code ndr_pull_union_blob_all(const DATA_BLOB *blob, TALLOC_CTX *mem_ctx,
1368 uint32_t level, ndr_pull_flags_fn_t fn)
1370 struct ndr_pull *ndr;
1371 uint32_t highest_ofs;
1372 ndr = ndr_pull_init_blob(blob, mem_ctx);
1373 NDR_ERR_HAVE_NO_MEMORY(ndr);
1374 NDR_CHECK_FREE(ndr_pull_set_switch_value(ndr, p, level));
1375 NDR_CHECK_FREE(fn(ndr, NDR_SCALARS|NDR_BUFFERS, p));
1376 if (ndr->offset > ndr->relative_highest_offset) {
1377 highest_ofs = ndr->offset;
1379 highest_ofs = ndr->relative_highest_offset;
1381 if (highest_ofs < ndr->data_size) {
1382 enum ndr_err_code ret;
1383 ret = ndr_pull_error(ndr, NDR_ERR_UNREAD_BYTES,
1384 "not all bytes consumed ofs[%u] size[%u]",
1385 highest_ofs, ndr->data_size);
1390 return NDR_ERR_SUCCESS;
1394 push a struct to a blob using NDR
1396 _PUBLIC_ enum ndr_err_code ndr_push_struct_blob(DATA_BLOB *blob, TALLOC_CTX *mem_ctx, const void *p, ndr_push_flags_fn_t fn)
1398 struct ndr_push *ndr;
1399 ndr = ndr_push_init_ctx(mem_ctx);
1400 NDR_ERR_HAVE_NO_MEMORY(ndr);
1402 NDR_CHECK(fn(ndr, NDR_SCALARS|NDR_BUFFERS, p));
1404 *blob = ndr_push_blob(ndr);
1405 talloc_steal(mem_ctx, blob->data);
1408 return NDR_ERR_SUCCESS;
1412 push a struct into a provided blob using NDR.
1414 We error because we want to have the performance issue (extra
1415 talloc() calls) show up as an error, not just slower code. This is
1416 used for things like GUIDs, which we expect to be a fixed size, and
1417 SIDs that we can pre-calculate the size for.
1419 _PUBLIC_ enum ndr_err_code ndr_push_struct_into_fixed_blob(
1420 DATA_BLOB *blob, const void *p, ndr_push_flags_fn_t fn)
1422 struct ndr_push ndr = {
1424 .alloc_size = blob->length,
1425 .fixed_buf_size = true
1428 NDR_CHECK(fn(&ndr, NDR_SCALARS|NDR_BUFFERS, p));
1430 if (ndr.offset != blob->length) {
1431 return ndr_push_error(&ndr, NDR_ERR_BUFSIZE,
1432 "buffer was either to large or small "
1433 "ofs[%u] size[%zu]",
1434 ndr.offset, blob->length);
1437 return NDR_ERR_SUCCESS;
1441 push a union to a blob using NDR
1443 _PUBLIC_ enum ndr_err_code ndr_push_union_blob(DATA_BLOB *blob, TALLOC_CTX *mem_ctx, void *p,
1444 uint32_t level, ndr_push_flags_fn_t fn)
1446 struct ndr_push *ndr;
1447 ndr = ndr_push_init_ctx(mem_ctx);
1448 NDR_ERR_HAVE_NO_MEMORY(ndr);
1450 NDR_CHECK(ndr_push_set_switch_value(ndr, p, level));
1451 NDR_CHECK(fn(ndr, NDR_SCALARS|NDR_BUFFERS, p));
1453 *blob = ndr_push_blob(ndr);
1454 talloc_steal(mem_ctx, blob->data);
1457 return NDR_ERR_SUCCESS;
1461 generic ndr_size_*() handler for structures
1463 _PUBLIC_ size_t ndr_size_struct(const void *p, int flags, ndr_push_flags_fn_t push)
1465 struct ndr_push *ndr;
1466 enum ndr_err_code status;
1469 /* avoid recursion */
1470 if (flags & LIBNDR_FLAG_NO_NDR_SIZE) return 0;
1472 ndr = ndr_push_init_ctx(NULL);
1474 ndr->flags |= flags | LIBNDR_FLAG_NO_NDR_SIZE;
1475 status = push(ndr, NDR_SCALARS|NDR_BUFFERS, discard_const(p));
1476 if (!NDR_ERR_CODE_IS_SUCCESS(status)) {
1486 generic ndr_size_*() handler for unions
1488 _PUBLIC_ size_t ndr_size_union(const void *p, int flags, uint32_t level, ndr_push_flags_fn_t push)
1490 struct ndr_push *ndr;
1491 enum ndr_err_code status;
1494 /* avoid recursion */
1495 if (flags & LIBNDR_FLAG_NO_NDR_SIZE) return 0;
1497 ndr = ndr_push_init_ctx(NULL);
1499 ndr->flags |= flags | LIBNDR_FLAG_NO_NDR_SIZE;
1501 status = ndr_push_set_switch_value(ndr, p, level);
1502 if (!NDR_ERR_CODE_IS_SUCCESS(status)) {
1506 status = push(ndr, NDR_SCALARS|NDR_BUFFERS, p);
1507 if (!NDR_ERR_CODE_IS_SUCCESS(status)) {
1517 get the current base for relative pointers for the push
1519 _PUBLIC_ uint32_t ndr_push_get_relative_base_offset(struct ndr_push *ndr)
1521 return ndr->relative_base_offset;
1525 restore the old base for relative pointers for the push
1527 _PUBLIC_ void ndr_push_restore_relative_base_offset(struct ndr_push *ndr, uint32_t offset)
1529 ndr->relative_base_offset = offset;
1533 setup the current base for relative pointers for the push
1534 called in the NDR_SCALAR stage
1536 _PUBLIC_ enum ndr_err_code ndr_push_setup_relative_base_offset1(struct ndr_push *ndr, const void *p, uint32_t offset)
1538 enum ndr_err_code ret;
1539 ndr->relative_base_offset = offset;
1540 ret = ndr_token_store(ndr, &ndr->relative_base_list, p, offset);
1541 if (ret == NDR_ERR_RANGE) {
1542 return ndr_push_error(ndr, ret,
1543 "More than %d NDR tokens stored for relative_base_list",
1544 NDR_TOKEN_MAX_LIST_SIZE);
1550 setup the current base for relative pointers for the push
1551 called in the NDR_BUFFERS stage
1553 _PUBLIC_ enum ndr_err_code ndr_push_setup_relative_base_offset2(struct ndr_push *ndr, const void *p)
1555 return ndr_token_retrieve(&ndr->relative_base_list, p, &ndr->relative_base_offset);
1559 push a relative object - stage1
1560 this is called during SCALARS processing
1562 _PUBLIC_ enum ndr_err_code ndr_push_relative_ptr1(struct ndr_push *ndr, const void *p)
1564 enum ndr_err_code ret;
1566 NDR_CHECK(ndr_push_uint32(ndr, NDR_SCALARS, 0));
1567 return NDR_ERR_SUCCESS;
1569 NDR_CHECK(ndr_push_align(ndr, 4));
1570 ret = ndr_token_store(ndr, &ndr->relative_list, p, ndr->offset);
1571 if (ret == NDR_ERR_RANGE) {
1572 return ndr_push_error(ndr, ret,
1573 "More than %d NDR tokens stored for relative_list",
1574 NDR_TOKEN_MAX_LIST_SIZE);
1577 return ndr_push_uint32(ndr, NDR_SCALARS, 0xFFFFFFFF);
1581 push a short relative object - stage1
1582 this is called during SCALARS processing
1584 _PUBLIC_ enum ndr_err_code ndr_push_short_relative_ptr1(struct ndr_push *ndr, const void *p)
1586 enum ndr_err_code ret;
1588 NDR_CHECK(ndr_push_uint16(ndr, NDR_SCALARS, 0));
1589 return NDR_ERR_SUCCESS;
1591 NDR_CHECK(ndr_push_align(ndr, 2));
1592 ret = ndr_token_store(ndr, &ndr->relative_list, p, ndr->offset);
1593 if (ret == NDR_ERR_RANGE) {
1594 return ndr_push_error(ndr, ret,
1595 "More than %d NDR tokens stored for relative_list",
1596 NDR_TOKEN_MAX_LIST_SIZE);
1599 return ndr_push_uint16(ndr, NDR_SCALARS, 0xFFFF);
1602 push a relative object - stage2
1603 this is called during buffers processing
1605 static enum ndr_err_code ndr_push_relative_ptr2(struct ndr_push *ndr, const void *p)
1607 uint32_t save_offset;
1608 uint32_t ptr_offset = 0xFFFFFFFF;
1610 return NDR_ERR_SUCCESS;
1612 save_offset = ndr->offset;
1613 NDR_CHECK(ndr_token_retrieve(&ndr->relative_list, p, &ptr_offset));
1614 if (ptr_offset > ndr->offset) {
1615 return ndr_push_error(ndr, NDR_ERR_BUFSIZE,
1616 "ndr_push_relative_ptr2 ptr_offset(%u) > ndr->offset(%u)",
1617 ptr_offset, ndr->offset);
1619 ndr->offset = ptr_offset;
1620 if (save_offset < ndr->relative_base_offset) {
1621 return ndr_push_error(ndr, NDR_ERR_BUFSIZE,
1622 "ndr_push_relative_ptr2 save_offset(%u) < ndr->relative_base_offset(%u)",
1623 save_offset, ndr->relative_base_offset);
1625 NDR_CHECK(ndr_push_uint32(ndr, NDR_SCALARS, save_offset - ndr->relative_base_offset));
1626 ndr->offset = save_offset;
1627 return NDR_ERR_SUCCESS;
1630 push a short relative object - stage2
1631 this is called during buffers processing
1633 _PUBLIC_ enum ndr_err_code ndr_push_short_relative_ptr2(struct ndr_push *ndr, const void *p)
1635 uint32_t save_offset;
1636 uint32_t ptr_offset = 0xFFFF;
1637 uint32_t relative_offset;
1642 return NDR_ERR_SUCCESS;
1645 if (ndr->offset < ndr->relative_base_offset) {
1646 return ndr_push_error(ndr, NDR_ERR_BUFSIZE,
1647 "ndr_push_relative_ptr2 ndr->offset(%u) < ndr->relative_base_offset(%u)",
1648 ndr->offset, ndr->relative_base_offset);
1651 relative_offset = ndr->offset - ndr->relative_base_offset;
1653 if (ndr->flags & LIBNDR_FLAG_NOALIGN) {
1655 } else if (ndr->flags & LIBNDR_FLAG_ALIGN2) {
1657 } else if (ndr->flags & LIBNDR_FLAG_ALIGN4) {
1659 } else if (ndr->flags & LIBNDR_FLAG_ALIGN8) {
1663 pad = ndr_align_size(relative_offset, align);
1665 NDR_CHECK(ndr_push_zero(ndr, pad));
1668 relative_offset = ndr->offset - ndr->relative_base_offset;
1669 if (relative_offset > UINT16_MAX) {
1670 return ndr_push_error(ndr, NDR_ERR_BUFSIZE,
1671 "ndr_push_relative_ptr2 relative_offset(%u) > UINT16_MAX",
1675 save_offset = ndr->offset;
1676 NDR_CHECK(ndr_token_retrieve(&ndr->relative_list, p, &ptr_offset));
1677 if (ptr_offset > ndr->offset) {
1678 return ndr_push_error(ndr, NDR_ERR_BUFSIZE,
1679 "ndr_push_short_relative_ptr2 ptr_offset(%u) > ndr->offset(%u)",
1680 ptr_offset, ndr->offset);
1682 ndr->offset = ptr_offset;
1683 NDR_CHECK(ndr_push_uint16(ndr, NDR_SCALARS, relative_offset));
1684 ndr->offset = save_offset;
1685 return NDR_ERR_SUCCESS;
1689 push a relative object - stage2 start
1690 this is called during buffers processing
1692 _PUBLIC_ enum ndr_err_code ndr_push_relative_ptr2_start(struct ndr_push *ndr, const void *p)
1694 enum ndr_err_code ret;
1696 return NDR_ERR_SUCCESS;
1698 if (!(ndr->flags & LIBNDR_FLAG_RELATIVE_REVERSE)) {
1699 uint32_t relative_offset;
1703 if (ndr->offset < ndr->relative_base_offset) {
1704 return ndr_push_error(ndr, NDR_ERR_BUFSIZE,
1705 "ndr_push_relative_ptr2_start ndr->offset(%u) < ndr->relative_base_offset(%u)",
1706 ndr->offset, ndr->relative_base_offset);
1709 relative_offset = ndr->offset - ndr->relative_base_offset;
1711 if (ndr->flags & LIBNDR_FLAG_NOALIGN) {
1713 } else if (ndr->flags & LIBNDR_FLAG_ALIGN2) {
1715 } else if (ndr->flags & LIBNDR_FLAG_ALIGN4) {
1717 } else if (ndr->flags & LIBNDR_FLAG_ALIGN8) {
1721 pad = ndr_align_size(relative_offset, align);
1723 NDR_CHECK(ndr_push_zero(ndr, pad));
1726 return ndr_push_relative_ptr2(ndr, p);
1728 if (ndr->relative_end_offset == -1) {
1729 return ndr_push_error(ndr, NDR_ERR_RELATIVE,
1730 "ndr_push_relative_ptr2_start RELATIVE_REVERSE flag set and relative_end_offset %d",
1731 ndr->relative_end_offset);
1733 ret = ndr_token_store(ndr,
1734 &ndr->relative_begin_list,
1737 if (ret == NDR_ERR_RANGE) {
1738 return ndr_push_error(ndr, ret,
1739 "More than %d NDR tokens stored for array_size",
1740 NDR_TOKEN_MAX_LIST_SIZE);
1746 push a relative object - stage2 end
1747 this is called during buffers processing
1749 _PUBLIC_ enum ndr_err_code ndr_push_relative_ptr2_end(struct ndr_push *ndr, const void *p)
1751 uint32_t begin_offset = 0xFFFFFFFF;
1753 uint32_t correct_offset = 0;
1758 return NDR_ERR_SUCCESS;
1761 if (!(ndr->flags & LIBNDR_FLAG_RELATIVE_REVERSE)) {
1762 return NDR_ERR_SUCCESS;
1765 if (ndr->flags & LIBNDR_FLAG_NO_NDR_SIZE) {
1766 /* better say more than calculation a too small buffer */
1767 NDR_PUSH_ALIGN(ndr, 8);
1768 return NDR_ERR_SUCCESS;
1771 if (ndr->relative_end_offset < ndr->offset) {
1772 return ndr_push_error(ndr, NDR_ERR_RELATIVE,
1773 "ndr_push_relative_ptr2_end:"
1774 "relative_end_offset %u < offset %u",
1775 ndr->relative_end_offset, ndr->offset);
1778 NDR_CHECK(ndr_token_retrieve(&ndr->relative_begin_list, p, &begin_offset));
1780 /* we have marshalled a buffer, see how long it was */
1781 len = ndr->offset - begin_offset;
1784 return ndr_push_error(ndr, NDR_ERR_RELATIVE,
1785 "ndr_push_relative_ptr2_end:"
1786 "offset %u - begin_offset %u < 0",
1787 ndr->offset, begin_offset);
1790 if (ndr->relative_end_offset < len) {
1791 return ndr_push_error(ndr, NDR_ERR_RELATIVE,
1792 "ndr_push_relative_ptr2_end:"
1793 "relative_end_offset %u < len %lld",
1794 ndr->offset, (long long)len);
1797 /* the reversed offset is at the end of the main buffer */
1798 correct_offset = ndr->relative_end_offset - len;
1800 if (ndr->flags & LIBNDR_FLAG_NOALIGN) {
1802 } else if (ndr->flags & LIBNDR_FLAG_ALIGN2) {
1804 } else if (ndr->flags & LIBNDR_FLAG_ALIGN4) {
1806 } else if (ndr->flags & LIBNDR_FLAG_ALIGN8) {
1810 pad = ndr_align_size(correct_offset, align);
1812 correct_offset += pad;
1813 correct_offset -= align;
1816 if (correct_offset < begin_offset) {
1817 return ndr_push_error(ndr, NDR_ERR_RELATIVE,
1818 "ndr_push_relative_ptr2_end: "
1819 "correct_offset %u < begin_offset %u",
1820 correct_offset, begin_offset);
1824 uint32_t clear_size = correct_offset - begin_offset;
1826 clear_size = MIN(clear_size, len);
1828 /* now move the marshalled buffer to the end of the main buffer */
1829 memmove(ndr->data + correct_offset, ndr->data + begin_offset, len);
1832 /* and wipe out old buffer within the main buffer */
1833 memset(ndr->data + begin_offset, '\0', clear_size);
1837 /* and set the end offset for the next buffer */
1838 ndr->relative_end_offset = correct_offset;
1840 /* finally write the offset to the main buffer */
1841 ndr->offset = correct_offset;
1842 NDR_CHECK(ndr_push_relative_ptr2(ndr, p));
1844 /* restore to where we were in the main buffer */
1845 ndr->offset = begin_offset;
1847 return NDR_ERR_SUCCESS;
1851 get the current base for relative pointers for the pull
1853 _PUBLIC_ uint32_t ndr_pull_get_relative_base_offset(struct ndr_pull *ndr)
1855 return ndr->relative_base_offset;
1859 restore the old base for relative pointers for the pull
1861 _PUBLIC_ void ndr_pull_restore_relative_base_offset(struct ndr_pull *ndr, uint32_t offset)
1863 ndr->relative_base_offset = offset;
1867 setup the current base for relative pointers for the pull
1868 called in the NDR_SCALAR stage
1870 _PUBLIC_ enum ndr_err_code ndr_pull_setup_relative_base_offset1(struct ndr_pull *ndr, const void *p, uint32_t offset)
1872 enum ndr_err_code ret;
1873 ndr->relative_base_offset = offset;
1874 ret = ndr_token_store(ndr, &ndr->relative_base_list, p, offset);
1875 if (ret == NDR_ERR_RANGE) {
1876 return ndr_pull_error(ndr, ret,
1877 "More than %d NDR tokens stored for relative_base_list",
1878 NDR_TOKEN_MAX_LIST_SIZE);
1884 setup the current base for relative pointers for the pull
1885 called in the NDR_BUFFERS stage
1887 _PUBLIC_ enum ndr_err_code ndr_pull_setup_relative_base_offset2(struct ndr_pull *ndr, const void *p)
1889 return ndr_token_retrieve(&ndr->relative_base_list, p, &ndr->relative_base_offset);
1893 pull a relative object - stage1
1894 called during SCALARS processing
1896 _PUBLIC_ enum ndr_err_code ndr_pull_relative_ptr1(struct ndr_pull *ndr, const void *p, uint32_t rel_offset)
1898 enum ndr_err_code ret;
1899 rel_offset += ndr->relative_base_offset;
1900 if (rel_offset > ndr->data_size) {
1901 return ndr_pull_error(ndr, NDR_ERR_BUFSIZE,
1902 "ndr_pull_relative_ptr1 rel_offset(%u) > ndr->data_size(%u)",
1903 rel_offset, ndr->data_size);
1905 ret = ndr_token_store(ndr, &ndr->relative_list, p, rel_offset);
1906 if (ret == NDR_ERR_RANGE) {
1907 return ndr_pull_error(ndr, ret,
1908 "More than %d NDR tokens stored for relative_list",
1909 NDR_TOKEN_MAX_LIST_SIZE);
1915 pull a relative object - stage2
1916 called during BUFFERS processing
1918 _PUBLIC_ enum ndr_err_code ndr_pull_relative_ptr2(struct ndr_pull *ndr, const void *p)
1920 uint32_t rel_offset;
1921 NDR_CHECK(ndr_token_retrieve(&ndr->relative_list, p, &rel_offset));
1922 return ndr_pull_set_offset(ndr, rel_offset);
1925 const static struct {
1926 enum ndr_err_code err;
1928 } ndr_err_code_strings[] = {
1929 { NDR_ERR_SUCCESS, "Success" },
1930 { NDR_ERR_ARRAY_SIZE, "Bad Array Size" },
1931 { NDR_ERR_BAD_SWITCH, "Bad Switch" },
1932 { NDR_ERR_OFFSET, "Offset Error" },
1933 { NDR_ERR_RELATIVE, "Relative Pointer Error" },
1934 { NDR_ERR_CHARCNV, "Character Conversion Error" },
1935 { NDR_ERR_LENGTH, "Length Error" },
1936 { NDR_ERR_SUBCONTEXT, "Subcontext Error" },
1937 { NDR_ERR_COMPRESSION, "Compression Error" },
1938 { NDR_ERR_STRING, "String Error" },
1939 { NDR_ERR_VALIDATE, "Validate Error" },
1940 { NDR_ERR_BUFSIZE, "Buffer Size Error" },
1941 { NDR_ERR_ALLOC, "Allocation Error" },
1942 { NDR_ERR_RANGE, "Range Error" },
1943 { NDR_ERR_TOKEN, "Token Error" },
1944 { NDR_ERR_IPV4ADDRESS, "IPv4 Address Error" },
1945 { NDR_ERR_INVALID_POINTER, "Invalid Pointer" },
1946 { NDR_ERR_UNREAD_BYTES, "Unread Bytes" },
1947 { NDR_ERR_NDR64, "NDR64 assertion error" },
1948 { NDR_ERR_INCOMPLETE_BUFFER, "Incomplete Buffer" },
1952 _PUBLIC_ const char *ndr_map_error2string(enum ndr_err_code ndr_err)
1955 for (i = 0; ndr_err_code_strings[i].string != NULL; i++) {
1956 if (ndr_err_code_strings[i].err == ndr_err)
1957 return ndr_err_code_strings[i].string;
1959 return "Unknown error";