ctdb-tests: Update statd-callout tests to handle both modes
[samba4-gss.git] / librpc / ndr / ndr.c
blobc25e8bd1ca52ebb843b1430acdccc7286c55b54d
1 /*
2 Unix SMB/CIFS implementation.
4 libndr interface
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
27 of NDR encoding rules
30 #include "includes.h"
31 #include "librpc/ndr/libndr.h"
32 #include "librpc/ndr/ndr_private.h"
33 #include "../lib/util/dlinklist.h"
35 #undef DBGC_CLASS
36 #define DBGC_CLASS DBGC_RPC_PARSE
38 #define NDR_BASE_MARSHALL_SIZE 1024
41 * This value is arbitrary, but designed to reduce the memory a client
42 * can allocate and the work the client can force in processing a
43 * malicious packet.
45 * In an ideal world this would be controlled by range() restrictions
46 * on array sizes and careful IDL construction to avoid arbitrary
47 * linked lists, but this is a backstop for now.
49 #define NDR_TOKEN_MAX_LIST_SIZE 65535
51 size_t ndr_token_max_list_size(void) {
52 return NDR_TOKEN_MAX_LIST_SIZE;
55 /* this guid indicates NDR encoding in a protocol tower */
56 const struct ndr_syntax_id ndr_transfer_syntax_ndr = {
57 { 0x8a885d04, 0x1ceb, 0x11c9, {0x9f, 0xe8}, {0x08,0x00,0x2b,0x10,0x48,0x60} },
61 const struct ndr_syntax_id ndr_transfer_syntax_ndr64 = {
62 { 0x71710533, 0xbeba, 0x4937, {0x83, 0x19}, {0xb5,0xdb,0xef,0x9c,0xcc,0x36} },
66 const struct ndr_syntax_id ndr_syntax_id_null = {
67 { 0, 0, 0, { 0, 0 }, { 0, 0, 0, 0, 0, 0 } },
72 work out the number of bytes needed to align on a n byte boundary
74 _PUBLIC_ size_t ndr_align_size(uint32_t offset, size_t n)
76 if ((offset & (n-1)) == 0) return 0;
77 return n - (offset & (n-1));
81 initialise a ndr parse structure from a data blob
83 _PUBLIC_ struct ndr_pull *ndr_pull_init_blob(const DATA_BLOB *blob, TALLOC_CTX *mem_ctx)
85 struct ndr_pull *ndr;
87 ndr = talloc_zero(mem_ctx, struct ndr_pull);
88 if (!ndr) return NULL;
89 ndr->current_mem_ctx = mem_ctx;
91 ndr->data = blob->data;
92 ndr->data_size = blob->length;
94 return ndr;
97 _PUBLIC_ enum ndr_err_code ndr_pull_append(struct ndr_pull *ndr, DATA_BLOB *blob)
99 enum ndr_err_code ndr_err;
100 DATA_BLOB b;
101 uint32_t append = 0;
102 bool ok;
104 if (blob->length == 0) {
105 return NDR_ERR_SUCCESS;
108 ndr_err = ndr_token_retrieve(&ndr->array_size_list, ndr, &append);
109 if (ndr_err == NDR_ERR_TOKEN) {
110 append = 0;
111 ndr_err = NDR_ERR_SUCCESS;
113 NDR_CHECK(ndr_err);
115 if (ndr->data_size == 0) {
116 ndr->data = NULL;
117 append = UINT32_MAX;
120 if (append == UINT32_MAX) {
122 * append == UINT32_MAX means that
123 * ndr->data is either NULL or a valid
124 * talloc child of ndr, which means
125 * we can use data_blob_append() without
126 * data_blob_talloc() of the existing callers data
128 b = data_blob_const(ndr->data, ndr->data_size);
129 } else {
130 b = data_blob_talloc(ndr, ndr->data, ndr->data_size);
131 if (b.data == NULL) {
132 return ndr_pull_error(ndr, NDR_ERR_ALLOC, "%s", __location__);
136 ok = data_blob_append(ndr, &b, blob->data, blob->length);
137 if (!ok) {
138 return ndr_pull_error(ndr, NDR_ERR_ALLOC, "%s", __location__);
141 ndr->data = b.data;
142 ndr->data_size = b.length;
144 return ndr_token_store(ndr, &ndr->array_size_list, ndr, UINT32_MAX);
147 _PUBLIC_ enum ndr_err_code ndr_pull_pop(struct ndr_pull *ndr)
149 uint32_t skip = 0;
150 uint32_t append = 0;
151 enum ndr_err_code ndr_err;
153 if (ndr->relative_base_offset != 0) {
154 return ndr_pull_error(ndr, NDR_ERR_RELATIVE,
155 "%s", __location__);
157 if (ndr->relative_highest_offset != 0) {
158 return ndr_pull_error(ndr, NDR_ERR_RELATIVE,
159 "%s", __location__);
161 if (ndr->relative_list.count != 0) {
162 return ndr_pull_error(ndr, NDR_ERR_RELATIVE,
163 "%s", __location__);
165 if (ndr->relative_base_list.count != 0) {
166 return ndr_pull_error(ndr, NDR_ERR_RELATIVE,
167 "%s", __location__);
171 * we need to keep up to 7 bytes
172 * in order to get the alignment right.
174 skip = ndr->offset & 0xFFFFFFF8;
176 if (skip == 0) {
177 return NDR_ERR_SUCCESS;
180 ndr->offset -= skip;
181 ndr->data_size -= skip;
183 ndr_err = ndr_token_peek(&ndr->array_size_list, ndr, &append);
184 if (ndr_err == NDR_ERR_TOKEN) {
186 * here we assume, that ndr->data is not a
187 * talloc child of ndr.
189 ndr->data += skip;
190 return NDR_ERR_SUCCESS;
193 memmove(ndr->data, ndr->data + skip, ndr->data_size);
195 ndr->data = talloc_realloc(ndr, ndr->data, uint8_t, ndr->data_size);
196 if (ndr->data_size != 0 && ndr->data == NULL) {
197 return ndr_pull_error(ndr, NDR_ERR_ALLOC, "%s", __location__);
200 return NDR_ERR_SUCCESS;
204 advance by 'size' bytes
206 _PUBLIC_ enum ndr_err_code ndr_pull_advance(struct ndr_pull *ndr, uint32_t size)
208 NDR_PULL_NEED_BYTES(ndr, size);
209 ndr->offset += size;
210 return NDR_ERR_SUCCESS;
214 set the parse offset to 'ofs'
216 static enum ndr_err_code ndr_pull_set_offset(struct ndr_pull *ndr, uint32_t ofs)
218 ndr->offset = ofs;
219 if (ndr->offset > ndr->data_size) {
220 return ndr_pull_error(ndr, NDR_ERR_BUFSIZE,
221 "ndr_pull_set_offset %"PRIu32" failed",
222 ofs);
224 return NDR_ERR_SUCCESS;
227 /* create a ndr_push structure, ready for some marshalling */
228 _PUBLIC_ struct ndr_push *ndr_push_init_ctx(TALLOC_CTX *mem_ctx)
230 struct ndr_push *ndr;
232 ndr = talloc_zero(mem_ctx, struct ndr_push);
233 if (!ndr) {
234 return NULL;
237 ndr->flags = 0;
238 ndr->alloc_size = NDR_BASE_MARSHALL_SIZE;
239 ndr->data = talloc_array(ndr, uint8_t, ndr->alloc_size);
240 if (!ndr->data) {
241 TALLOC_FREE(ndr);
242 return NULL;
245 return ndr;
248 /* return a DATA_BLOB structure for the current ndr_push marshalled data */
249 _PUBLIC_ DATA_BLOB ndr_push_blob(struct ndr_push *ndr)
251 DATA_BLOB blob;
252 blob = data_blob_const(ndr->data, ndr->offset);
253 if (ndr->alloc_size > ndr->offset) {
254 ndr->data[ndr->offset] = 0;
256 return blob;
261 expand the available space in the buffer to ndr->offset + extra_size
263 _PUBLIC_ enum ndr_err_code ndr_push_expand(struct ndr_push *ndr, uint32_t extra_size)
265 uint32_t size = extra_size + ndr->offset;
267 if (size < ndr->offset) {
268 /* extra_size overflowed the offset */
269 return ndr_push_error(ndr, NDR_ERR_BUFSIZE, "Overflow in push_expand to %"PRIu32,
270 size);
273 if (ndr->fixed_buf_size) {
274 if (ndr->alloc_size >= size) {
275 return NDR_ERR_SUCCESS;
277 return ndr_push_error(ndr,
278 NDR_ERR_BUFSIZE,
279 "Overflow of fixed buffer in "
280 "push_expand to %"PRIu32,
281 size);
284 if (ndr->alloc_size > size) {
285 return NDR_ERR_SUCCESS;
288 ndr->alloc_size += NDR_BASE_MARSHALL_SIZE;
289 if (size == UINT32_MAX) {
290 return ndr_push_error(ndr, NDR_ERR_BUFSIZE, "Overflow in push_expand");
292 if (size+1 > ndr->alloc_size) {
293 ndr->alloc_size = size+1;
295 ndr->data = talloc_realloc(ndr, ndr->data, uint8_t, ndr->alloc_size);
296 if (!ndr->data) {
297 return ndr_push_error(ndr, NDR_ERR_ALLOC, "Failed to push_expand to %"PRIu32,
298 ndr->alloc_size);
301 return NDR_ERR_SUCCESS;
304 _PUBLIC_ void ndr_print_debugc_helper(struct ndr_print *ndr, const char *format, ...)
306 va_list ap;
307 char *s = NULL;
308 uint32_t i;
309 int ret;
310 int dbgc_class;
312 va_start(ap, format);
313 ret = vasprintf(&s, format, ap);
314 va_end(ap);
316 if (ret == -1) {
317 return;
320 dbgc_class = *(int *)ndr->private_data;
322 if (ndr->no_newline) {
323 DEBUGADDC(dbgc_class, 1,("%s", s));
324 free(s);
325 return;
328 for (i=0;i<ndr->depth;i++) {
329 DEBUGADDC(dbgc_class, 1,(" "));
332 DEBUGADDC(dbgc_class, 1,("%s\n", s));
333 free(s);
336 _PUBLIC_ void ndr_print_debug_helper(struct ndr_print *ndr, const char *format, ...)
338 va_list ap;
339 char *s = NULL;
340 uint32_t i;
341 int ret;
343 va_start(ap, format);
344 ret = vasprintf(&s, format, ap);
345 va_end(ap);
347 if (ret == -1) {
348 return;
351 if (ndr->no_newline) {
352 DEBUGADD(1,("%s", s));
353 free(s);
354 return;
357 for (i=0;i<ndr->depth;i++) {
358 DEBUGADD(1,(" "));
361 DEBUGADD(1,("%s\n", s));
362 free(s);
365 _PUBLIC_ void ndr_print_printf_helper(struct ndr_print *ndr, const char *format, ...)
367 va_list ap;
368 uint32_t i;
370 if (!ndr->no_newline) {
371 for (i=0;i<ndr->depth;i++) {
372 printf(" ");
376 va_start(ap, format);
377 vprintf(format, ap);
378 va_end(ap);
379 if (!ndr->no_newline) {
380 printf("\n");
384 _PUBLIC_ void ndr_print_string_helper(struct ndr_print *ndr, const char *format, ...)
386 va_list ap;
387 uint32_t i;
389 if (!ndr->no_newline) {
390 for (i=0;i<ndr->depth;i++) {
391 ndr->private_data = talloc_asprintf_append_buffer(
392 (char *)ndr->private_data, " ");
396 va_start(ap, format);
397 ndr->private_data = talloc_vasprintf_append_buffer((char *)ndr->private_data,
398 format, ap);
399 va_end(ap);
400 if (!ndr->no_newline) {
401 ndr->private_data = talloc_asprintf_append_buffer((char *)ndr->private_data,
402 "\n");
407 a useful helper function for printing idl structures via DEBUGC()
409 _PUBLIC_ void ndr_print_debugc(int dbgc_class,
410 ndr_print_fn_t fn,
411 const char *name,
412 const void *ptr)
414 struct ndr_print *ndr;
416 DEBUGC(dbgc_class, 1,(" "));
418 ndr = talloc_zero(NULL, struct ndr_print);
419 if (!ndr) return;
420 ndr->private_data = &dbgc_class;
421 ndr->print = ndr_print_debugc_helper;
422 ndr->depth = 1;
423 ndr->flags = 0;
424 #ifdef DEBUG_PASSWORD
425 if (CHECK_DEBUGLVL(100)) {
426 ndr->print_secrets = true;
428 #endif
430 fn(ndr, name, ptr);
431 TALLOC_FREE(ndr);
435 a useful helper function for printing idl structures via DEBUG()
437 _PUBLIC_ bool ndr_print_debug(int level,
438 ndr_print_fn_t fn,
439 const char *name,
440 const void *ptr,
441 const char *location,
442 const char *function)
444 struct ndr_print *ndr;
445 bool ret = false;
447 ndr = talloc_zero(NULL, struct ndr_print);
448 if (!ndr) return false;
449 ndr->private_data = talloc_strdup(ndr, "");
450 if (ndr->private_data == NULL) {
451 goto fail;
453 ndr->print = ndr_print_string_helper;
454 ndr->depth = 1;
455 ndr->flags = 0;
456 #ifdef DEBUG_PASSWORD
457 if (CHECK_DEBUGLVL(100)) {
458 ndr->print_secrets = true;
460 #endif
462 fn(ndr, name, ptr);
463 DEBUGLF(level, (" %s", (char *)ndr->private_data), location, function);
465 ret = true;
466 fail:
467 TALLOC_FREE(ndr);
468 return ret;
472 a useful helper function for printing idl unions via DEBUG()
474 _PUBLIC_ void ndr_print_union_debug(ndr_print_fn_t fn,
475 const char *name,
476 uint32_t level,
477 const void *ptr)
479 struct ndr_print *ndr;
481 DEBUG(1,(" "));
483 ndr = talloc_zero(NULL, struct ndr_print);
484 if (!ndr) return;
485 ndr->print = ndr_print_debug_helper;
486 ndr->depth = 1;
487 ndr->flags = 0;
488 #ifdef DEBUG_PASSWORD
489 if (CHECK_DEBUGLVL(100)) {
490 ndr->print_secrets = true;
492 #endif
494 ndr_print_set_switch_value(ndr, ptr, level);
495 fn(ndr, name, ptr);
496 TALLOC_FREE(ndr);
500 a useful helper function for printing idl function calls via DEBUG()
502 _PUBLIC_ void ndr_print_function_debug(ndr_print_function_t fn,
503 const char *name,
504 ndr_flags_type flags,
505 const void *ptr)
507 struct ndr_print *ndr;
509 DEBUG(1,(" "));
511 ndr = talloc_zero(NULL, struct ndr_print);
512 if (!ndr) return;
513 ndr->print = ndr_print_debug_helper;
514 ndr->depth = 1;
515 ndr->flags = 0;
516 #ifdef DEBUG_PASSWORD
517 if (CHECK_DEBUGLVL(100)) {
518 ndr->print_secrets = true;
520 #endif
522 fn(ndr, name, flags, ptr);
523 TALLOC_FREE(ndr);
526 static char *ndr_print_generic_string(TALLOC_CTX *mem_ctx,
527 ndr_print_function_t inout_fn,
528 ndr_flags_type inout_flags,
529 ndr_print_fn_t single_fn,
530 bool print_secrets,
531 const char *name,
532 const uint32_t *level,
533 const void *ptr)
535 struct ndr_print *ndr;
536 char *ret = NULL;
538 ndr = talloc_zero(mem_ctx, struct ndr_print);
539 if (!ndr) return NULL;
540 ndr->private_data = talloc_strdup(ndr, "");
541 if (!ndr->private_data) {
542 goto failed;
544 ndr->print = ndr_print_string_helper;
545 ndr->depth = 1;
546 ndr->flags = 0;
547 ndr->print_secrets = print_secrets;
548 if (level != NULL) {
549 ndr_print_set_switch_value(ndr, ptr, *level);
551 if (inout_fn != NULL) {
552 inout_fn(ndr, name, inout_flags, ptr);
553 } else {
554 single_fn(ndr, name, ptr);
556 ret = talloc_steal(mem_ctx, (char *)ndr->private_data);
557 if (print_secrets) {
558 talloc_keep_secret(ret);
560 failed:
561 TALLOC_FREE(ndr);
562 return ret;
566 a useful helper function for printing idl structures to a string
568 _PUBLIC_ char *ndr_print_struct_string(TALLOC_CTX *mem_ctx,
569 ndr_print_fn_t fn,
570 const char *name,
571 const void *ptr)
573 return ndr_print_generic_string(mem_ctx,
574 NULL, /* inout_fn */
575 0, /* inout_flags */
576 fn, /* single_fn */
577 false, /* print_secrets */
578 name,
579 NULL, /* level */
580 ptr);
584 a useful helper function for printing idl structures to a string
585 This includes values marked with NDR_SECRET
587 _PUBLIC_ char *ndr_print_struct_secret_string(TALLOC_CTX *mem_ctx,
588 ndr_print_fn_t fn,
589 const char *name,
590 const void *ptr)
592 return ndr_print_generic_string(mem_ctx,
593 NULL, /* inout_fn */
594 0, /* inout_flags */
595 fn, /* single_fn */
596 true, /* print_secrets */
597 name,
598 NULL, /* level */
599 ptr);
603 a useful helper function for printing idl unions to a string
605 _PUBLIC_ char *ndr_print_union_string(TALLOC_CTX *mem_ctx,
606 ndr_print_fn_t fn,
607 const char *name,
608 uint32_t level,
609 const void *ptr)
611 return ndr_print_generic_string(mem_ctx,
612 NULL, /* inout_fn */
613 0, /* inout_flags */
614 fn, /* single_fn */
615 false, /* print_secrets */
616 name,
617 &level,
618 ptr);
622 a useful helper function for printing idl unions to a string
623 This includes values marked with NDR_SECRET
625 _PUBLIC_ char *ndr_print_union_secret_string(TALLOC_CTX *mem_ctx,
626 ndr_print_fn_t fn,
627 const char *name,
628 uint32_t level,
629 const void *ptr)
631 return ndr_print_generic_string(mem_ctx,
632 NULL, /* inout_fn */
633 0, /* inout_flags */
634 fn, /* single_fn */
635 true, /* print_secrets */
636 name,
637 &level,
638 ptr);
642 a useful helper function for printing idl function calls to a string
644 _PUBLIC_ char *ndr_print_function_string(TALLOC_CTX *mem_ctx,
645 ndr_print_function_t fn,
646 const char *name,
647 ndr_flags_type flags,
648 const void *ptr)
650 return ndr_print_generic_string(mem_ctx,
651 fn, /* inout_fn */
652 flags, /* inout_flags */
653 NULL, /* single_fn */
654 false, /* print_secrets */
655 name,
656 NULL, /* level */
657 ptr);
661 a useful helper function for printing idl function calls to a string
662 This includes values marked with NDR_SECRET
664 _PUBLIC_ char *ndr_print_function_secret_string(TALLOC_CTX *mem_ctx,
665 ndr_print_function_t fn,
666 const char *name,
667 ndr_flags_type flags,
668 const void *ptr)
670 return ndr_print_generic_string(mem_ctx,
671 fn, /* inout_fn */
672 flags, /* inout_flags */
673 NULL, /* single_fn */
674 true, /* print_secrets */
675 name,
676 NULL, /* level */
677 ptr);
680 _PUBLIC_ void ndr_set_flags(libndr_flags *pflags, libndr_flags new_flags)
682 /* the big/little endian flags are inter-dependent */
683 if (new_flags & LIBNDR_FLAG_LITTLE_ENDIAN) {
684 (*pflags) &= ~LIBNDR_FLAG_BIGENDIAN;
685 (*pflags) &= ~LIBNDR_FLAG_NDR64;
687 if (new_flags & LIBNDR_FLAG_BIGENDIAN) {
688 (*pflags) &= ~LIBNDR_FLAG_LITTLE_ENDIAN;
689 (*pflags) &= ~LIBNDR_FLAG_NDR64;
691 if (new_flags & LIBNDR_ALIGN_FLAGS) {
692 /* Ensure we only have the passed-in
693 align flag set in the new_flags,
694 remove any old align flag. */
695 (*pflags) &= ~LIBNDR_ALIGN_FLAGS;
697 if (new_flags & LIBNDR_FLAG_NO_RELATIVE_REVERSE) {
698 (*pflags) &= ~LIBNDR_FLAG_RELATIVE_REVERSE;
700 (*pflags) |= new_flags;
704 return and possibly log an NDR error
706 _PUBLIC_ enum ndr_err_code _ndr_pull_error(struct ndr_pull *ndr,
707 enum ndr_err_code ndr_err,
708 const char *function,
709 const char *location,
710 const char *format, ...)
712 char *s=NULL;
713 va_list ap;
714 int ret;
716 if (ndr->flags & LIBNDR_FLAG_INCOMPLETE_BUFFER) {
717 switch (ndr_err) {
718 case NDR_ERR_BUFSIZE:
719 return NDR_ERR_INCOMPLETE_BUFFER;
720 default:
721 break;
725 va_start(ap, format);
726 ret = vasprintf(&s, format, ap);
727 va_end(ap);
729 if (ret == -1) {
730 return NDR_ERR_ALLOC;
733 D_WARNING("%s: ndr_pull_error(%s): %s at %s\n",
734 function,
735 ndr_map_error2string(ndr_err),
737 location);
739 free(s);
741 return ndr_err;
745 return and possibly log an NDR error
747 _PUBLIC_ enum ndr_err_code _ndr_push_error(struct ndr_push *ndr,
748 enum ndr_err_code ndr_err,
749 const char *function,
750 const char *location,
751 const char *format, ...)
753 char *s=NULL;
754 va_list ap;
755 int ret;
757 va_start(ap, format);
758 ret = vasprintf(&s, format, ap);
759 va_end(ap);
761 if (ret == -1) {
762 return NDR_ERR_ALLOC;
765 D_WARNING("%s: ndr_push_error(%s): %s at %s\n",
766 function,
767 ndr_map_error2string(ndr_err),
769 location);
771 free(s);
773 return ndr_err;
777 handle subcontext buffers, which in midl land are user-marshalled, but
778 we use magic in pidl to make them easier to cope with
780 _PUBLIC_ enum ndr_err_code ndr_pull_subcontext_start(struct ndr_pull *ndr,
781 struct ndr_pull **_subndr,
782 size_t header_size,
783 ssize_t size_is)
785 struct ndr_pull *subndr;
786 uint32_t r_content_size;
787 bool force_le = false;
788 bool force_be = false;
790 switch (header_size) {
791 case 0: {
792 uint32_t content_size = ndr->data_size - ndr->offset;
793 if (size_is >= 0) {
794 content_size = size_is;
796 r_content_size = content_size;
797 break;
800 case 2: {
801 uint16_t content_size;
802 NDR_CHECK(ndr_pull_uint16(ndr, NDR_SCALARS, &content_size));
803 if (size_is >= 0 && size_is != content_size) {
804 return ndr_pull_error(ndr, NDR_ERR_SUBCONTEXT, "Bad subcontext (PULL) size_is(%zd) (0x%04zx) mismatch content_size %"PRIu16" (0x%04"PRIx16")",
805 size_is, size_is,
806 content_size,
807 content_size);
809 r_content_size = content_size;
810 break;
813 case 4: {
814 uint32_t content_size;
815 NDR_CHECK(ndr_pull_uint3264(ndr, NDR_SCALARS, &content_size));
816 if (size_is >= 0 && size_is != content_size) {
817 return ndr_pull_error(ndr, NDR_ERR_SUBCONTEXT, "Bad subcontext (PULL) size_is(%zd) (0x%08zx) mismatch content_size %"PRIu32" (0x%08"PRIx32")",
818 size_is, size_is,
819 content_size,
820 content_size);
822 r_content_size = content_size;
823 break;
825 case 0xFFFFFC01: {
827 * Common Type Header for the Serialization Stream
828 * See [MS-RPCE] 2.2.6 Type Serialization Version 1
830 uint8_t version;
831 uint8_t drep;
832 uint16_t hdrlen;
833 uint32_t filler;
834 uint32_t content_size;
835 uint32_t reserved;
837 /* version */
838 NDR_CHECK(ndr_pull_uint8(ndr, NDR_SCALARS, &version));
840 if (version != 1) {
841 return ndr_pull_error(ndr, NDR_ERR_SUBCONTEXT,
842 "Bad subcontext (PULL) Common Type Header version %"PRIu8" != 1",
843 version);
847 * 0x10 little endian
848 * 0x00 big endian
850 NDR_CHECK(ndr_pull_uint8(ndr, NDR_SCALARS, &drep));
851 if (drep == 0x10) {
852 force_le = true;
853 } else if (drep == 0x00) {
854 force_be = true;
855 } else {
856 return ndr_pull_error(ndr, NDR_ERR_SUBCONTEXT,
857 "Bad subcontext (PULL) Common Type Header invalid drep 0x%02"PRIX8,
858 drep);
861 /* length of the "Private Header for Constructed Type" */
862 NDR_CHECK(ndr_pull_uint16(ndr, NDR_SCALARS, &hdrlen));
863 if (hdrlen != 8) {
864 return ndr_pull_error(ndr, NDR_ERR_SUBCONTEXT,
865 "Bad subcontext (PULL) Common Type Header length %"PRIu16" != 8",
866 hdrlen);
869 /* filler should be ignored */
870 NDR_CHECK(ndr_pull_uint32(ndr, NDR_SCALARS, &filler));
873 * Private Header for Constructed Type
875 /* length - will be updated later */
876 NDR_CHECK(ndr_pull_uint32(ndr, NDR_SCALARS, &content_size));
877 if (size_is >= 0 && size_is != content_size) {
878 return ndr_pull_error(ndr, NDR_ERR_SUBCONTEXT, "Bad subcontext (PULL) size_is(%zd) mismatch content_size %"PRIu32,
879 size_is, content_size);
881 /* the content size must be a multiple of 8 */
882 if ((content_size % 8) != 0) {
883 return ndr_pull_error(ndr, NDR_ERR_SUBCONTEXT,
884 "Bad subcontext (PULL) size_is(%zd) not padded to 8 content_size %"PRIu32,
885 size_is, content_size);
887 r_content_size = content_size;
889 /* reserved */
890 NDR_CHECK(ndr_pull_uint32(ndr, NDR_SCALARS, &reserved));
891 break;
893 case 0xFFFFFFFF:
895 * a shallow copy like subcontext
896 * useful for DCERPC pipe chunks.
898 subndr = talloc_zero(ndr, struct ndr_pull);
899 NDR_ERR_HAVE_NO_MEMORY(subndr);
901 subndr->flags = ndr->flags;
902 subndr->current_mem_ctx = ndr->current_mem_ctx;
903 subndr->data = ndr->data;
904 subndr->offset = ndr->offset;
905 subndr->data_size = ndr->data_size;
907 *_subndr = subndr;
908 return NDR_ERR_SUCCESS;
910 default:
911 return ndr_pull_error(ndr, NDR_ERR_SUBCONTEXT, "Bad subcontext (PULL) header_size %zu",
912 header_size);
915 NDR_PULL_NEED_BYTES(ndr, r_content_size);
917 subndr = talloc_zero(ndr, struct ndr_pull);
918 NDR_ERR_HAVE_NO_MEMORY(subndr);
919 subndr->flags = ndr->flags & ~LIBNDR_FLAG_NDR64;
920 subndr->current_mem_ctx = ndr->current_mem_ctx;
922 subndr->data = ndr->data + ndr->offset;
923 subndr->offset = 0;
924 subndr->data_size = r_content_size;
926 if (force_le) {
927 ndr_set_flags(&subndr->flags, LIBNDR_FLAG_LITTLE_ENDIAN);
928 } else if (force_be) {
929 ndr_set_flags(&subndr->flags, LIBNDR_FLAG_BIGENDIAN);
932 *_subndr = subndr;
933 return NDR_ERR_SUCCESS;
936 _PUBLIC_ enum ndr_err_code ndr_pull_subcontext_end(struct ndr_pull *ndr,
937 struct ndr_pull *subndr,
938 size_t header_size,
939 ssize_t size_is)
941 uint32_t advance;
942 uint32_t highest_ofs;
944 if (header_size == 0xFFFFFFFF) {
945 advance = subndr->offset - ndr->offset;
946 } else if (size_is >= 0) {
947 advance = size_is;
948 } else if (header_size > 0) {
949 advance = subndr->data_size;
950 } else {
951 advance = subndr->offset;
954 if (subndr->offset > ndr->relative_highest_offset) {
955 highest_ofs = subndr->offset;
956 } else {
957 highest_ofs = subndr->relative_highest_offset;
959 if (!(subndr->flags & LIBNDR_FLAG_SUBCONTEXT_NO_UNREAD_BYTES)) {
961 * avoid an error unless SUBCONTEXT_NO_UNREAD_BYTES is specified
963 highest_ofs = advance;
965 if (highest_ofs < advance) {
966 return ndr_pull_error(subndr, NDR_ERR_UNREAD_BYTES,
967 "not all bytes consumed ofs[%"PRIu32"] advance[%"PRIu32"]",
968 highest_ofs, advance);
971 NDR_CHECK(ndr_pull_advance(ndr, advance));
972 return NDR_ERR_SUCCESS;
975 _PUBLIC_ enum ndr_err_code ndr_push_subcontext_start(struct ndr_push *ndr,
976 struct ndr_push **_subndr,
977 size_t header_size,
978 ssize_t size_is)
980 struct ndr_push *subndr;
982 subndr = ndr_push_init_ctx(ndr);
983 NDR_ERR_HAVE_NO_MEMORY(subndr);
984 subndr->flags = ndr->flags & ~LIBNDR_FLAG_NDR64;
986 if (size_is > 0) {
987 enum ndr_err_code status;
989 status = ndr_push_zero(subndr, size_is);
990 if (!NDR_ERR_CODE_IS_SUCCESS(status)) {
991 TALLOC_FREE(subndr);
992 return status;
994 subndr->offset = 0;
995 subndr->relative_end_offset = size_is;
998 *_subndr = subndr;
999 return NDR_ERR_SUCCESS;
1003 push a subcontext header
1005 _PUBLIC_ enum ndr_err_code ndr_push_subcontext_end(struct ndr_push *ndr,
1006 struct ndr_push *subndr,
1007 size_t header_size,
1008 ssize_t size_is)
1010 ssize_t padding_len;
1012 if (size_is >= 0) {
1013 padding_len = size_is - subndr->offset;
1014 if (padding_len < 0) {
1015 return ndr_push_error(ndr, NDR_ERR_SUBCONTEXT, "Bad subcontext (PUSH) content_size %"PRIu32" is larger than size_is(%zd)",
1016 subndr->offset, size_is);
1018 subndr->offset = size_is;
1021 switch (header_size) {
1022 case 0:
1023 break;
1025 case 2:
1026 if (subndr->offset > UINT16_MAX) {
1027 return ndr_push_error(
1028 ndr,
1029 NDR_ERR_BUFSIZE,
1030 "Subcontext (PUSH) too large: %" PRIu32
1031 " does not fit into 16 bits",
1032 subndr->offset);
1034 NDR_CHECK(ndr_push_uint16(ndr, NDR_SCALARS, subndr->offset));
1035 break;
1037 case 4:
1038 NDR_CHECK(ndr_push_uint3264(ndr, NDR_SCALARS, subndr->offset));
1039 break;
1041 case 0xFFFFFC01:
1043 * Common Type Header for the Serialization Stream
1044 * See [MS-RPCE] 2.2.6 Type Serialization Version 1
1046 padding_len = NDR_ROUND(subndr->offset, 8) - subndr->offset;
1047 if (padding_len > 0) {
1048 NDR_CHECK(ndr_push_zero(subndr, padding_len));
1051 /* version */
1052 NDR_CHECK(ndr_push_uint8(ndr, NDR_SCALARS, 1));
1055 * 0x10 little endian
1056 * 0x00 big endian
1058 NDR_CHECK(ndr_push_uint8(ndr, NDR_SCALARS, NDR_BE(ndr)?0x00:0x10));
1060 /* length of the "Private Header for Constructed Type" */
1061 NDR_CHECK(ndr_push_uint16(ndr, NDR_SCALARS, 8));
1063 /* filler */
1064 NDR_CHECK(ndr_push_uint32(ndr, NDR_SCALARS, 0xCCCCCCCC));
1067 * Private Header for Constructed Type
1069 /* length - will be updated later */
1070 NDR_CHECK(ndr_push_uint32(ndr, NDR_SCALARS, subndr->offset));
1072 /* reserved */
1073 NDR_CHECK(ndr_push_uint32(ndr, NDR_SCALARS, 0));
1074 break;
1076 default:
1077 return ndr_push_error(ndr, NDR_ERR_SUBCONTEXT, "Bad subcontext header size %zu",
1078 header_size);
1081 NDR_CHECK(ndr_push_bytes(ndr, subndr->data, subndr->offset));
1082 return NDR_ERR_SUCCESS;
1086 struct ndr_token {
1087 const void *key;
1088 uint32_t value;
1092 store a token in the ndr context, for later retrieval
1094 _PUBLIC_ enum ndr_err_code ndr_token_store(TALLOC_CTX *mem_ctx,
1095 struct ndr_token_list *list,
1096 const void *key,
1097 uint32_t value)
1099 if (list->tokens == NULL) {
1100 list->tokens = talloc_array(mem_ctx, struct ndr_token, 10);
1101 if (list->tokens == NULL) {
1102 NDR_ERR_HAVE_NO_MEMORY(list->tokens);
1104 } else {
1105 struct ndr_token *new_tokens = NULL;
1106 uint32_t alloc_count = talloc_array_length(list->tokens);
1109 * Check every time we have not allocated too many
1110 * tokens. This ensures developer sanity when
1111 * debugging the boundary condition
1113 if (list->count >= NDR_TOKEN_MAX_LIST_SIZE) {
1114 return NDR_ERR_RANGE;
1116 if (list->count == alloc_count) {
1117 uint32_t new_alloc;
1119 * Double the list, until we start in chunks
1120 * of 1000
1122 uint32_t increment = MIN(list->count, 1000);
1123 new_alloc = alloc_count + increment;
1124 if (new_alloc < alloc_count) {
1125 return NDR_ERR_RANGE;
1127 new_tokens = talloc_realloc(mem_ctx, list->tokens,
1128 struct ndr_token, new_alloc);
1129 NDR_ERR_HAVE_NO_MEMORY(new_tokens);
1130 list->tokens = new_tokens;
1133 list->tokens[list->count].key = key;
1134 list->tokens[list->count].value = value;
1135 list->count++;
1136 return NDR_ERR_SUCCESS;
1140 retrieve a token from a ndr context, using cmp_fn to match the tokens
1142 static enum ndr_err_code ndr_token_find(struct ndr_token_list *list,
1143 const void *key,
1144 uint32_t *v,
1145 comparison_fn_t _cmp_fn,
1146 unsigned *_i)
1148 struct ndr_token *tokens = list->tokens;
1149 unsigned i;
1150 for (i = list->count - 1; i < list->count; i--) {
1151 if (_cmp_fn(tokens[i].key, key) == 0) {
1152 *_i = i;
1153 *v = tokens[i].value;
1154 return NDR_ERR_SUCCESS;
1157 return NDR_ERR_TOKEN;
1161 * retrieve a token from a ndr context, matching by key address.
1163 static enum ndr_err_code ndr_token_find_by_key_address(struct ndr_token_list *list,
1164 const void *key,
1165 uint32_t *v,
1166 unsigned *_i)
1168 struct ndr_token *tokens = list->tokens;
1169 unsigned i;
1170 for (i = list->count - 1; i < list->count; i--) {
1171 if (tokens[i].key == key) {
1172 *_i = i;
1173 *v = tokens[i].value;
1174 return NDR_ERR_SUCCESS;
1177 return NDR_ERR_TOKEN;
1181 _PUBLIC_ enum ndr_err_code ndr_token_peek_cmp_fn(struct ndr_token_list *list,
1182 const void *key,
1183 uint32_t *v,
1184 comparison_fn_t _cmp_fn)
1186 unsigned i;
1187 return ndr_token_find(list, key, v, _cmp_fn, &i);
1191 retrieve a token from a ndr context
1193 _PUBLIC_ enum ndr_err_code ndr_token_retrieve(struct ndr_token_list *list,
1194 const void *key, uint32_t *v)
1196 enum ndr_err_code err;
1197 uint32_t last;
1198 unsigned i;
1200 err = ndr_token_find_by_key_address(list, key, v, &i);
1201 if (!NDR_ERR_CODE_IS_SUCCESS(err)) {
1202 return err;
1205 last = list->count - 1;
1206 if (i != last) {
1207 list->tokens[i] = list->tokens[last];
1209 list->count--;
1211 return NDR_ERR_SUCCESS;
1215 peek at but don't removed a token from a ndr context
1217 _PUBLIC_ enum ndr_err_code ndr_token_peek(struct ndr_token_list *list,
1218 const void *key, uint32_t *v)
1220 unsigned i;
1221 return ndr_token_find_by_key_address(list, key, v, &i);
1225 pull an array size field and add it to the array_size_list token list
1227 _PUBLIC_ enum ndr_err_code ndr_pull_array_size(struct ndr_pull *ndr, const void *p)
1229 enum ndr_err_code ret;
1230 uint32_t size;
1231 NDR_CHECK(ndr_pull_uint3264(ndr, NDR_SCALARS, &size));
1232 ret = ndr_token_store(ndr, &ndr->array_size_list, p, size);
1233 if (ret == NDR_ERR_RANGE) {
1234 return ndr_pull_error(ndr, ret,
1235 "More than %d NDR tokens stored for array_size",
1236 NDR_TOKEN_MAX_LIST_SIZE);
1238 return ret;
1242 get the stored array size field
1244 _PUBLIC_ enum ndr_err_code ndr_get_array_size(struct ndr_pull *ndr, const void *p, uint32_t *size)
1246 return ndr_token_peek(&ndr->array_size_list, p, size);
1250 get and remove from the stored list the stored array size field
1252 _PUBLIC_ enum ndr_err_code ndr_steal_array_size(struct ndr_pull *ndr, const void *p, uint32_t *size)
1254 return ndr_token_retrieve(&ndr->array_size_list, p, size);
1258 * check the stored array size field and remove from the stored list
1259 * (the array_size NDR token list). We try to remove when possible to
1260 * avoid the list growing towards the bounds check
1262 _PUBLIC_ enum ndr_err_code ndr_check_steal_array_size(struct ndr_pull *ndr, const void *p, uint32_t size)
1264 uint32_t stored;
1265 NDR_CHECK(ndr_steal_array_size(ndr, p, &stored));
1266 if (stored != size) {
1267 return ndr_pull_error(ndr, NDR_ERR_ARRAY_SIZE,
1268 "Bad array size - got %u expected %u\n",
1269 stored, size);
1271 return NDR_ERR_SUCCESS;
1275 * check the stored array size field (leaving it on the array_size
1276 * token list)
1278 _PUBLIC_ enum ndr_err_code ndr_check_array_size(struct ndr_pull *ndr, const void *p, uint32_t size)
1280 uint32_t stored;
1281 NDR_CHECK(ndr_get_array_size(ndr, p, &stored));
1282 if (stored != size) {
1283 return ndr_pull_error(ndr, NDR_ERR_ARRAY_SIZE,
1284 "Bad array size - got %"PRIu32" expected %"PRIu32"\n",
1285 stored, size);
1287 return NDR_ERR_SUCCESS;
1291 pull an array length field and add it to the array_length_list token list
1293 _PUBLIC_ enum ndr_err_code ndr_pull_array_length(struct ndr_pull *ndr, const void *p)
1295 enum ndr_err_code ret;
1296 uint32_t length, offset;
1297 NDR_CHECK(ndr_pull_uint3264(ndr, NDR_SCALARS, &offset));
1298 if (offset != 0) {
1299 return ndr_pull_error(ndr, NDR_ERR_ARRAY_SIZE,
1300 "non-zero array offset %"PRIu32"\n", offset);
1302 NDR_CHECK(ndr_pull_uint3264(ndr, NDR_SCALARS, &length));
1303 ret = ndr_token_store(ndr, &ndr->array_length_list, p, length);
1304 if (ret == NDR_ERR_RANGE) {
1305 return ndr_pull_error(ndr, ret,
1306 "More than %d NDR tokens stored for array_length_list",
1307 NDR_TOKEN_MAX_LIST_SIZE);
1309 return ret;
1313 get the stored array length field
1315 _PUBLIC_ enum ndr_err_code ndr_get_array_length(struct ndr_pull *ndr, const void *p, uint32_t *length)
1317 return ndr_token_peek(&ndr->array_length_list, p, length);
1321 * check the stored array length field and remove from the stored list
1322 * (the array_size NDR token list). We try to remove when possible to
1323 * avoid the list growing towards the bounds check
1325 _PUBLIC_ enum ndr_err_code ndr_steal_array_length(struct ndr_pull *ndr, const void *p, uint32_t *length)
1327 return ndr_token_retrieve(&ndr->array_length_list, p, length);
1330 check the stored array length field, removing it from the list
1332 _PUBLIC_ enum ndr_err_code ndr_check_steal_array_length(struct ndr_pull *ndr, const void *p, uint32_t length)
1334 uint32_t stored;
1335 NDR_CHECK(ndr_steal_array_length(ndr, p, &stored));
1336 if (stored != length) {
1337 return ndr_pull_error(ndr, NDR_ERR_ARRAY_SIZE,
1338 "Bad array length: got %"PRIu32" expected %"PRIu32"\n",
1339 stored, length);
1341 return NDR_ERR_SUCCESS;
1344 _PUBLIC_ enum ndr_err_code ndr_push_pipe_chunk_trailer(struct ndr_push *ndr, ndr_flags_type ndr_flags, uint32_t count)
1346 if (ndr->flags & LIBNDR_FLAG_NDR64) {
1347 int64_t tmp = 0 - (int64_t)count;
1348 uint64_t ncount = tmp;
1350 NDR_CHECK(ndr_push_hyper(ndr, ndr_flags, ncount));
1353 return NDR_ERR_SUCCESS;
1356 _PUBLIC_ enum ndr_err_code ndr_check_pipe_chunk_trailer(struct ndr_pull *ndr, ndr_flags_type ndr_flags, uint32_t count)
1358 if (ndr->flags & LIBNDR_FLAG_NDR64) {
1359 int64_t tmp = 0 - (int64_t)count;
1360 uint64_t ncount1 = tmp;
1361 uint64_t ncount2;
1363 NDR_CHECK(ndr_pull_hyper(ndr, ndr_flags, &ncount2));
1364 if (ncount1 == ncount2) {
1365 return NDR_ERR_SUCCESS;
1368 return ndr_pull_error(ndr, NDR_ERR_ARRAY_SIZE,
1369 "Bad pipe trailer[%"PRIu64" should be %"PRIu64"] size was %"PRIu32"\"",
1370 ncount2,
1371 ncount1,
1372 count);
1375 return NDR_ERR_SUCCESS;
1379 store a switch value
1381 _PUBLIC_ enum ndr_err_code ndr_push_set_switch_value(struct ndr_push *ndr, const void *p, uint32_t val)
1383 enum ndr_err_code ret =
1384 ndr_token_store(ndr, &ndr->switch_list, p, val);
1385 if (ret == NDR_ERR_RANGE) {
1386 return ndr_push_error(ndr, ret,
1387 "More than %d NDR tokens stored for switch_list",
1388 NDR_TOKEN_MAX_LIST_SIZE);
1390 return ret;
1393 _PUBLIC_ enum ndr_err_code ndr_pull_set_switch_value(struct ndr_pull *ndr, const void *p, uint32_t val)
1396 enum ndr_err_code ret =
1397 ndr_token_store(ndr, &ndr->switch_list, p, val);
1398 if (ret == NDR_ERR_RANGE) {
1399 return ndr_pull_error(ndr, ret,
1400 "More than %d NDR tokens stored for switch_list",
1401 NDR_TOKEN_MAX_LIST_SIZE);
1403 return ret;
1406 _PUBLIC_ enum ndr_err_code ndr_print_set_switch_value(struct ndr_print *ndr, const void *p, uint32_t val)
1408 return ndr_token_store(ndr, &ndr->switch_list, p, val);
1411 /* retrieve a switch value (for push) and remove it from the list */
1412 _PUBLIC_ enum ndr_err_code ndr_push_steal_switch_value(struct ndr_push *ndr,
1413 const void *p,
1414 uint32_t *v)
1416 return ndr_token_retrieve(&ndr->switch_list, p, v);
1419 /* retrieve a switch value and remove it from the list */
1420 _PUBLIC_ uint32_t ndr_print_steal_switch_value(struct ndr_print *ndr, const void *p)
1422 enum ndr_err_code status;
1423 uint32_t v;
1425 status = ndr_token_retrieve(&ndr->switch_list, p, &v);
1426 if (!NDR_ERR_CODE_IS_SUCCESS(status)) {
1427 return 0;
1430 return v;
1433 /* retrieve a switch value and remove it from the list */
1434 _PUBLIC_ enum ndr_err_code ndr_pull_steal_switch_value(struct ndr_pull *ndr,
1435 const void *p,
1436 uint32_t *v)
1438 return ndr_token_retrieve(&ndr->switch_list, p, v);
1442 pull a struct from a blob using NDR
1444 _PUBLIC_ enum ndr_err_code ndr_pull_struct_blob(const DATA_BLOB *blob, TALLOC_CTX *mem_ctx, void *p,
1445 ndr_pull_flags_fn_t fn)
1447 struct ndr_pull *ndr;
1448 ndr = ndr_pull_init_blob(blob, mem_ctx);
1449 NDR_ERR_HAVE_NO_MEMORY(ndr);
1450 NDR_CHECK_FREE(fn(ndr, NDR_SCALARS|NDR_BUFFERS, p));
1451 TALLOC_FREE(ndr);
1452 return NDR_ERR_SUCCESS;
1456 pull a struct from a blob using NDR - failing if all bytes are not consumed
1458 _PUBLIC_ enum ndr_err_code ndr_pull_struct_blob_all(const DATA_BLOB *blob, TALLOC_CTX *mem_ctx,
1459 void *p, ndr_pull_flags_fn_t fn)
1461 struct ndr_pull *ndr;
1462 uint32_t highest_ofs;
1463 ndr = ndr_pull_init_blob(blob, mem_ctx);
1464 NDR_ERR_HAVE_NO_MEMORY(ndr);
1465 NDR_CHECK_FREE(fn(ndr, NDR_SCALARS|NDR_BUFFERS, p));
1466 if (ndr->offset > ndr->relative_highest_offset) {
1467 highest_ofs = ndr->offset;
1468 } else {
1469 highest_ofs = ndr->relative_highest_offset;
1471 if (highest_ofs < ndr->data_size) {
1472 enum ndr_err_code ret;
1473 ret = ndr_pull_error(ndr, NDR_ERR_UNREAD_BYTES,
1474 "not all bytes consumed ofs[%"PRIu32"] size[%"PRIu32"]",
1475 highest_ofs, ndr->data_size);
1476 TALLOC_FREE(ndr);
1477 return ret;
1479 TALLOC_FREE(ndr);
1480 return NDR_ERR_SUCCESS;
1483 _PUBLIC_ enum ndr_err_code
1484 _ndr_deepcopy_struct(ndr_push_flags_fn_t push_fn,
1485 const void *src,
1486 ndr_pull_flags_fn_t pull_fn,
1487 TALLOC_CTX *dst_mem, void *dst)
1489 TALLOC_CTX *frame = talloc_stackframe();
1490 DATA_BLOB blob = { .length = 0, };
1491 enum ndr_err_code ndr_err;
1493 ndr_err = ndr_push_struct_blob(&blob, frame, src, push_fn);
1494 if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
1495 TALLOC_FREE(frame);
1496 return ndr_err;
1499 ndr_err = ndr_pull_struct_blob_all(&blob, dst_mem, dst, pull_fn);
1500 if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
1501 TALLOC_FREE(frame);
1502 return ndr_err;
1505 TALLOC_FREE(frame);
1506 return NDR_ERR_SUCCESS;
1510 * pull a struct from a blob using NDR
1512 * This only works for structures with NO allocated memory, like
1513 * objectSID and GUID. This helps because we parse these a lot.
1515 _PUBLIC_ enum ndr_err_code ndr_pull_struct_blob_noalloc(const uint8_t *buf,
1516 size_t buflen,
1517 void *p,
1518 ndr_pull_flags_fn_t fn,
1519 size_t *consumed)
1522 * We init this structure on the stack here, to avoid a
1523 * talloc() as otherwise this call to the fn() is assured not
1524 * to be doing any allocation, eg SIDs and GUIDs.
1526 * This allows us to keep the safety of the PIDL-generated
1527 * code without the talloc() overhead.
1529 struct ndr_pull ndr = {
1530 .data = discard_const_p(uint8_t, buf),
1531 .data_size = buflen,
1532 .current_mem_ctx = (void *)-1,
1535 NDR_CHECK(fn(&ndr, NDR_SCALARS|NDR_BUFFERS, p));
1536 *consumed = MAX(ndr.offset, ndr.relative_highest_offset);
1538 return NDR_ERR_SUCCESS;
1542 pull a struct from a blob using NDR - failing if all bytes are not consumed
1544 This only works for structures with NO allocated memory, like
1545 objectSID and GUID. This helps because we parse these a lot.
1547 _PUBLIC_ enum ndr_err_code
1548 ndr_pull_struct_blob_all_noalloc(const DATA_BLOB *blob,
1549 void *p,
1550 ndr_pull_flags_fn_t fn)
1552 size_t consumed;
1553 enum ndr_err_code ndr_err;
1555 ndr_err = ndr_pull_struct_blob_noalloc(blob->data,
1556 blob->length,
1559 &consumed);
1560 if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
1561 return ndr_err;
1564 if (consumed < blob->length) {
1565 D_WARNING("not all bytes consumed ofs[%zu] size[%zu]",
1566 consumed,
1567 blob->length);
1568 return NDR_ERR_UNREAD_BYTES;
1571 return NDR_ERR_SUCCESS;
1575 pull a union from a blob using NDR, given the union discriminator
1577 _PUBLIC_ enum ndr_err_code ndr_pull_union_blob(const DATA_BLOB *blob, TALLOC_CTX *mem_ctx,
1578 void *p,
1579 uint32_t level, ndr_pull_flags_fn_t fn)
1581 struct ndr_pull *ndr;
1582 ndr = ndr_pull_init_blob(blob, mem_ctx);
1583 NDR_ERR_HAVE_NO_MEMORY(ndr);
1584 NDR_CHECK_FREE(ndr_pull_set_switch_value(ndr, p, level));
1585 NDR_CHECK_FREE(fn(ndr, NDR_SCALARS|NDR_BUFFERS, p));
1586 TALLOC_FREE(ndr);
1587 return NDR_ERR_SUCCESS;
1591 pull a union from a blob using NDR, given the union discriminator,
1592 failing if all bytes are not consumed
1594 _PUBLIC_ enum ndr_err_code ndr_pull_union_blob_all(const DATA_BLOB *blob, TALLOC_CTX *mem_ctx,
1595 void *p,
1596 uint32_t level, ndr_pull_flags_fn_t fn)
1598 struct ndr_pull *ndr;
1599 uint32_t highest_ofs;
1600 ndr = ndr_pull_init_blob(blob, mem_ctx);
1601 NDR_ERR_HAVE_NO_MEMORY(ndr);
1602 NDR_CHECK_FREE(ndr_pull_set_switch_value(ndr, p, level));
1603 NDR_CHECK_FREE(fn(ndr, NDR_SCALARS|NDR_BUFFERS, p));
1604 if (ndr->offset > ndr->relative_highest_offset) {
1605 highest_ofs = ndr->offset;
1606 } else {
1607 highest_ofs = ndr->relative_highest_offset;
1609 if (highest_ofs < ndr->data_size) {
1610 enum ndr_err_code ret;
1611 ret = ndr_pull_error(ndr, NDR_ERR_UNREAD_BYTES,
1612 "not all bytes consumed ofs[%"PRIu32"] size[%"PRIu32"]",
1613 highest_ofs, ndr->data_size);
1614 TALLOC_FREE(ndr);
1615 return ret;
1617 TALLOC_FREE(ndr);
1618 return NDR_ERR_SUCCESS;
1622 push a struct to a blob using NDR
1624 _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)
1626 struct ndr_push *ndr;
1627 ndr = ndr_push_init_ctx(mem_ctx);
1628 NDR_ERR_HAVE_NO_MEMORY(ndr);
1630 NDR_CHECK_FREE(fn(ndr, NDR_SCALARS|NDR_BUFFERS, p));
1632 *blob = ndr_push_blob(ndr);
1633 talloc_steal(mem_ctx, blob->data);
1634 TALLOC_FREE(ndr);
1636 return NDR_ERR_SUCCESS;
1640 push a struct into a provided blob using NDR.
1642 We error because we want to have the performance issue (extra
1643 talloc() calls) show up as an error, not just slower code. This is
1644 used for things like GUIDs, which we expect to be a fixed size, and
1645 SIDs that we can pre-calculate the size for.
1647 _PUBLIC_ enum ndr_err_code ndr_push_struct_into_fixed_blob(
1648 DATA_BLOB *blob, const void *p, ndr_push_flags_fn_t fn)
1650 struct ndr_push ndr = {
1651 .data = blob->data,
1652 .alloc_size = blob->length,
1653 .fixed_buf_size = true
1656 NDR_CHECK(fn(&ndr, NDR_SCALARS|NDR_BUFFERS, p));
1658 if (ndr.offset != blob->length) {
1659 return ndr_push_error(&ndr, NDR_ERR_BUFSIZE,
1660 "buffer was either too large or small "
1661 "ofs[%"PRIu32"] size[%zu]",
1662 ndr.offset, blob->length);
1665 return NDR_ERR_SUCCESS;
1669 push a union to a blob using NDR
1671 _PUBLIC_ enum ndr_err_code ndr_push_union_blob(DATA_BLOB *blob, TALLOC_CTX *mem_ctx, void *p,
1672 uint32_t level, ndr_push_flags_fn_t fn)
1674 struct ndr_push *ndr;
1675 ndr = ndr_push_init_ctx(mem_ctx);
1676 NDR_ERR_HAVE_NO_MEMORY(ndr);
1678 NDR_CHECK_FREE(ndr_push_set_switch_value(ndr, p, level));
1679 NDR_CHECK_FREE(fn(ndr, NDR_SCALARS|NDR_BUFFERS, p));
1681 *blob = ndr_push_blob(ndr);
1682 talloc_steal(mem_ctx, blob->data);
1683 TALLOC_FREE(ndr);
1685 return NDR_ERR_SUCCESS;
1689 generic ndr_size_*() handler for structures
1691 _PUBLIC_ size_t ndr_size_struct(const void *p, libndr_flags flags, ndr_push_flags_fn_t push)
1693 struct ndr_push *ndr;
1694 enum ndr_err_code status;
1695 size_t ret;
1697 /* avoid recursion */
1698 if (flags & LIBNDR_FLAG_NO_NDR_SIZE) return 0;
1700 /* Avoid following a NULL pointer */
1701 if (p == NULL) {
1702 return 0;
1705 ndr = ndr_push_init_ctx(NULL);
1706 if (!ndr) return 0;
1707 ndr->flags |= flags | LIBNDR_FLAG_NO_NDR_SIZE;
1708 status = push(ndr, NDR_SCALARS|NDR_BUFFERS, discard_const(p));
1709 if (!NDR_ERR_CODE_IS_SUCCESS(status)) {
1710 TALLOC_FREE(ndr);
1711 return 0;
1713 ret = ndr->offset;
1714 TALLOC_FREE(ndr);
1715 return ret;
1719 generic ndr_size_*() handler for unions
1721 _PUBLIC_ size_t ndr_size_union(const void *p, libndr_flags flags, uint32_t level, ndr_push_flags_fn_t push)
1723 struct ndr_push *ndr;
1724 enum ndr_err_code status;
1725 size_t ret;
1727 /* avoid recursion */
1728 if (flags & LIBNDR_FLAG_NO_NDR_SIZE) return 0;
1730 /* Avoid following a NULL pointer */
1731 if (p == NULL) {
1732 return 0;
1735 ndr = ndr_push_init_ctx(NULL);
1736 if (!ndr) return 0;
1737 ndr->flags |= flags | LIBNDR_FLAG_NO_NDR_SIZE;
1739 status = ndr_push_set_switch_value(ndr, p, level);
1740 if (!NDR_ERR_CODE_IS_SUCCESS(status)) {
1741 TALLOC_FREE(ndr);
1742 return 0;
1744 status = push(ndr, NDR_SCALARS|NDR_BUFFERS, p);
1745 if (!NDR_ERR_CODE_IS_SUCCESS(status)) {
1746 TALLOC_FREE(ndr);
1747 return 0;
1749 ret = ndr->offset;
1750 TALLOC_FREE(ndr);
1751 return ret;
1755 get the current base for relative pointers for the push
1757 _PUBLIC_ uint32_t ndr_push_get_relative_base_offset(struct ndr_push *ndr)
1759 return ndr->relative_base_offset;
1763 restore the old base for relative pointers for the push
1765 _PUBLIC_ void ndr_push_restore_relative_base_offset(struct ndr_push *ndr, uint32_t offset)
1767 ndr->relative_base_offset = offset;
1771 setup the current base for relative pointers for the push
1772 called in the NDR_SCALAR stage
1774 _PUBLIC_ enum ndr_err_code ndr_push_setup_relative_base_offset1(struct ndr_push *ndr, const void *p, uint32_t offset)
1776 enum ndr_err_code ret;
1777 ndr->relative_base_offset = offset;
1778 ret = ndr_token_store(ndr, &ndr->relative_base_list, p, offset);
1779 if (ret == NDR_ERR_RANGE) {
1780 return ndr_push_error(ndr, ret,
1781 "More than %d NDR tokens stored for relative_base_list",
1782 NDR_TOKEN_MAX_LIST_SIZE);
1784 return ret;
1788 setup the current base for relative pointers for the push
1789 called in the NDR_BUFFERS stage
1791 _PUBLIC_ enum ndr_err_code ndr_push_setup_relative_base_offset2(struct ndr_push *ndr, const void *p)
1793 return ndr_token_retrieve(&ndr->relative_base_list, p, &ndr->relative_base_offset);
1797 push a relative object - stage1
1798 this is called during SCALARS processing
1800 _PUBLIC_ enum ndr_err_code ndr_push_relative_ptr1(struct ndr_push *ndr, const void *p)
1802 enum ndr_err_code ret;
1803 if (p == NULL) {
1804 NDR_CHECK(ndr_push_uint32(ndr, NDR_SCALARS, 0));
1805 return NDR_ERR_SUCCESS;
1807 NDR_CHECK(ndr_push_align(ndr, 4));
1808 ret = ndr_token_store(ndr, &ndr->relative_list, p, ndr->offset);
1809 if (ret == NDR_ERR_RANGE) {
1810 return ndr_push_error(ndr, ret,
1811 "More than %d NDR tokens stored for relative_list",
1812 NDR_TOKEN_MAX_LIST_SIZE);
1814 NDR_CHECK(ret);
1815 return ndr_push_uint32(ndr, NDR_SCALARS, UINT32_MAX);
1819 push a short relative object - stage1
1820 this is called during SCALARS processing
1822 _PUBLIC_ enum ndr_err_code ndr_push_short_relative_ptr1(struct ndr_push *ndr, const void *p)
1824 enum ndr_err_code ret;
1825 if (p == NULL) {
1826 NDR_CHECK(ndr_push_uint16(ndr, NDR_SCALARS, 0));
1827 return NDR_ERR_SUCCESS;
1829 NDR_CHECK(ndr_push_align(ndr, 2));
1830 ret = ndr_token_store(ndr, &ndr->relative_list, p, ndr->offset);
1831 if (ret == NDR_ERR_RANGE) {
1832 return ndr_push_error(ndr, ret,
1833 "More than %d NDR tokens stored for relative_list",
1834 NDR_TOKEN_MAX_LIST_SIZE);
1836 NDR_CHECK(ret);
1837 return ndr_push_uint16(ndr, NDR_SCALARS, 0xFFFF);
1840 push a relative object - stage2
1841 this is called during buffers processing
1843 static enum ndr_err_code ndr_push_relative_ptr2(struct ndr_push *ndr, const void *p)
1845 uint32_t save_offset;
1846 uint32_t ptr_offset = 0xFFFFFFFF;
1847 if (p == NULL) {
1848 return NDR_ERR_SUCCESS;
1850 if (ndr->offset < ndr->relative_base_offset) {
1851 return ndr_push_error(
1852 ndr,
1853 NDR_ERR_BUFSIZE,
1854 "ndr_push_relative_ptr2 ndr->offset(%" PRIu32 ") "
1855 "< ndr->relative_base_offset(%" PRIu32 ")",
1856 ndr->offset,
1857 ndr->relative_base_offset);
1859 NDR_CHECK(ndr_token_retrieve(&ndr->relative_list, p, &ptr_offset));
1860 if (ptr_offset > ndr->offset) {
1861 return ndr_push_error(ndr, NDR_ERR_BUFSIZE,
1862 "ndr_push_relative_ptr2 ptr_offset(%"PRIu32") > ndr->offset(%"PRIu32")",
1863 ptr_offset, ndr->offset);
1865 save_offset = ndr->offset;
1866 ndr->offset = ptr_offset;
1867 NDR_CHECK(ndr_push_uint32(ndr, NDR_SCALARS, save_offset - ndr->relative_base_offset));
1868 ndr->offset = save_offset;
1869 return NDR_ERR_SUCCESS;
1872 push a short relative object - stage2
1873 this is called during buffers processing
1875 _PUBLIC_ enum ndr_err_code ndr_push_short_relative_ptr2(struct ndr_push *ndr, const void *p)
1877 uint32_t save_offset;
1878 uint32_t ptr_offset = 0xFFFF;
1879 uint32_t relative_offset;
1880 size_t pad;
1881 size_t align = 1;
1883 if (p == NULL) {
1884 return NDR_ERR_SUCCESS;
1887 if (ndr->offset < ndr->relative_base_offset) {
1888 return ndr_push_error(ndr, NDR_ERR_BUFSIZE,
1889 "ndr_push_relative_ptr2 ndr->offset(%"PRIu32") < ndr->relative_base_offset(%"PRIu32")",
1890 ndr->offset, ndr->relative_base_offset);
1893 relative_offset = ndr->offset - ndr->relative_base_offset;
1895 if (ndr->flags & LIBNDR_FLAG_NOALIGN) {
1896 align = 1;
1897 } else if (ndr->flags & LIBNDR_FLAG_ALIGN2) {
1898 align = 2;
1899 } else if (ndr->flags & LIBNDR_FLAG_ALIGN4) {
1900 align = 4;
1901 } else if (ndr->flags & LIBNDR_FLAG_ALIGN8) {
1902 align = 8;
1905 pad = ndr_align_size(relative_offset, align);
1906 if (pad != 0) {
1907 NDR_CHECK(ndr_push_zero(ndr, pad));
1910 relative_offset = ndr->offset - ndr->relative_base_offset;
1911 if (relative_offset > UINT16_MAX) {
1912 return ndr_push_error(ndr, NDR_ERR_BUFSIZE,
1913 "ndr_push_relative_ptr2 relative_offset(%"PRIu32") > UINT16_MAX",
1914 relative_offset);
1917 save_offset = ndr->offset;
1918 NDR_CHECK(ndr_token_retrieve(&ndr->relative_list, p, &ptr_offset));
1919 if (ptr_offset > ndr->offset) {
1920 return ndr_push_error(ndr, NDR_ERR_BUFSIZE,
1921 "ndr_push_short_relative_ptr2 ptr_offset(%"PRIu32") > ndr->offset(%"PRIu32")",
1922 ptr_offset, ndr->offset);
1924 ndr->offset = ptr_offset;
1925 NDR_CHECK(ndr_push_uint16(ndr, NDR_SCALARS, relative_offset));
1926 ndr->offset = save_offset;
1927 return NDR_ERR_SUCCESS;
1931 push a relative object - stage2 start
1932 this is called during buffers processing
1934 _PUBLIC_ enum ndr_err_code ndr_push_relative_ptr2_start(struct ndr_push *ndr, const void *p)
1936 enum ndr_err_code ret;
1937 if (p == NULL) {
1938 return NDR_ERR_SUCCESS;
1940 if (!(ndr->flags & LIBNDR_FLAG_RELATIVE_REVERSE)) {
1941 uint32_t relative_offset;
1942 size_t pad;
1943 size_t align = 1;
1945 if (ndr->offset < ndr->relative_base_offset) {
1946 return ndr_push_error(ndr, NDR_ERR_BUFSIZE,
1947 "ndr_push_relative_ptr2_start ndr->offset(%"PRIu32") < ndr->relative_base_offset(%"PRIu32")",
1948 ndr->offset, ndr->relative_base_offset);
1951 relative_offset = ndr->offset - ndr->relative_base_offset;
1953 if (ndr->flags & LIBNDR_FLAG_NOALIGN) {
1954 align = 1;
1955 } else if (ndr->flags & LIBNDR_FLAG_ALIGN2) {
1956 align = 2;
1957 } else if (ndr->flags & LIBNDR_FLAG_ALIGN4) {
1958 align = 4;
1959 } else if (ndr->flags & LIBNDR_FLAG_ALIGN8) {
1960 align = 8;
1963 pad = ndr_align_size(relative_offset, align);
1964 if (pad) {
1965 NDR_CHECK(ndr_push_zero(ndr, pad));
1968 return ndr_push_relative_ptr2(ndr, p);
1970 if (ndr->relative_end_offset == -1) {
1971 return ndr_push_error(ndr, NDR_ERR_RELATIVE,
1972 "ndr_push_relative_ptr2_start RELATIVE_REVERSE flag set and relative_end_offset %"PRIu32,
1973 ndr->relative_end_offset);
1975 ret = ndr_token_store(ndr,
1976 &ndr->relative_begin_list,
1978 ndr->offset);
1979 if (ret == NDR_ERR_RANGE) {
1980 return ndr_push_error(ndr, ret,
1981 "More than %d NDR tokens stored for array_size",
1982 NDR_TOKEN_MAX_LIST_SIZE);
1984 return ret;
1988 push a relative object - stage2 end
1989 this is called during buffers processing
1991 _PUBLIC_ enum ndr_err_code ndr_push_relative_ptr2_end(struct ndr_push *ndr, const void *p)
1993 uint32_t begin_offset = 0xFFFFFFFF;
1994 ssize_t len;
1995 uint32_t correct_offset = 0;
1996 uint32_t align = 1;
1997 uint32_t pad = 0;
1999 if (p == NULL) {
2000 return NDR_ERR_SUCCESS;
2003 if (!(ndr->flags & LIBNDR_FLAG_RELATIVE_REVERSE)) {
2004 return NDR_ERR_SUCCESS;
2007 if (ndr->flags & LIBNDR_FLAG_NO_NDR_SIZE) {
2008 /* better say more than calculation a too small buffer */
2009 NDR_PUSH_ALIGN(ndr, 8);
2010 return NDR_ERR_SUCCESS;
2013 if (ndr->relative_end_offset < ndr->offset) {
2014 return ndr_push_error(ndr, NDR_ERR_RELATIVE,
2015 "ndr_push_relative_ptr2_end:"
2016 "relative_end_offset %"PRIu32" < offset %"PRIu32,
2017 ndr->relative_end_offset, ndr->offset);
2020 NDR_CHECK(ndr_token_retrieve(&ndr->relative_begin_list, p, &begin_offset));
2022 /* we have marshalled a buffer, see how long it was */
2023 len = ndr->offset - begin_offset;
2025 if (len < 0) {
2026 return ndr_push_error(ndr, NDR_ERR_RELATIVE,
2027 "ndr_push_relative_ptr2_end:"
2028 "offset %"PRIu32" - begin_offset %"PRIu32" < 0",
2029 ndr->offset, begin_offset);
2032 if (ndr->relative_end_offset < len) {
2033 return ndr_push_error(ndr, NDR_ERR_RELATIVE,
2034 "ndr_push_relative_ptr2_end:"
2035 "relative_end_offset %"PRIu32" < len %zd",
2036 ndr->offset, len);
2039 /* the reversed offset is at the end of the main buffer */
2040 correct_offset = ndr->relative_end_offset - len;
2042 if (ndr->flags & LIBNDR_FLAG_NOALIGN) {
2043 align = 1;
2044 } else if (ndr->flags & LIBNDR_FLAG_ALIGN2) {
2045 align = 2;
2046 } else if (ndr->flags & LIBNDR_FLAG_ALIGN4) {
2047 align = 4;
2048 } else if (ndr->flags & LIBNDR_FLAG_ALIGN8) {
2049 align = 8;
2052 pad = ndr_align_size(correct_offset, align);
2053 if (pad) {
2054 correct_offset += pad;
2055 correct_offset -= align;
2058 if (correct_offset < begin_offset) {
2059 return ndr_push_error(ndr, NDR_ERR_RELATIVE,
2060 "ndr_push_relative_ptr2_end: "
2061 "correct_offset %"PRIu32" < begin_offset %"PRIu32,
2062 correct_offset, begin_offset);
2065 if (len > 0) {
2066 uint32_t clear_size = correct_offset - begin_offset;
2068 clear_size = MIN(clear_size, len);
2070 /* now move the marshalled buffer to the end of the main buffer */
2071 memmove(ndr->data + correct_offset, ndr->data + begin_offset, len);
2073 if (clear_size) {
2074 /* and wipe out old buffer within the main buffer */
2075 memset(ndr->data + begin_offset, '\0', clear_size);
2079 /* and set the end offset for the next buffer */
2080 ndr->relative_end_offset = correct_offset;
2082 /* finally write the offset to the main buffer */
2083 ndr->offset = correct_offset;
2084 NDR_CHECK(ndr_push_relative_ptr2(ndr, p));
2086 /* restore to where we were in the main buffer */
2087 ndr->offset = begin_offset;
2089 return NDR_ERR_SUCCESS;
2093 get the current base for relative pointers for the pull
2095 _PUBLIC_ uint32_t ndr_pull_get_relative_base_offset(struct ndr_pull *ndr)
2097 return ndr->relative_base_offset;
2101 restore the old base for relative pointers for the pull
2103 _PUBLIC_ void ndr_pull_restore_relative_base_offset(struct ndr_pull *ndr, uint32_t offset)
2105 ndr->relative_base_offset = offset;
2109 setup the current base for relative pointers for the pull
2110 called in the NDR_SCALAR stage
2112 _PUBLIC_ enum ndr_err_code ndr_pull_setup_relative_base_offset1(struct ndr_pull *ndr, const void *p, uint32_t offset)
2114 enum ndr_err_code ret;
2115 ndr->relative_base_offset = offset;
2116 ret = ndr_token_store(ndr, &ndr->relative_base_list, p, offset);
2117 if (ret == NDR_ERR_RANGE) {
2118 return ndr_pull_error(ndr, ret,
2119 "More than %d NDR tokens stored for relative_base_list",
2120 NDR_TOKEN_MAX_LIST_SIZE);
2122 return ret;
2126 setup the current base for relative pointers for the pull
2127 called in the NDR_BUFFERS stage
2129 _PUBLIC_ enum ndr_err_code ndr_pull_setup_relative_base_offset2(struct ndr_pull *ndr, const void *p)
2131 return ndr_token_retrieve(&ndr->relative_base_list, p, &ndr->relative_base_offset);
2135 pull a relative object - stage1
2136 called during SCALARS processing
2138 _PUBLIC_ enum ndr_err_code ndr_pull_relative_ptr1(struct ndr_pull *ndr, const void *p, uint32_t rel_offset)
2140 enum ndr_err_code ret;
2141 rel_offset += ndr->relative_base_offset;
2142 if (rel_offset < ndr->relative_base_offset) {
2143 return ndr_pull_error(ndr,
2144 NDR_ERR_INVALID_POINTER,
2145 "Overflow rel_offset=%" PRIu32 " + "
2146 "relative_base_offset=%" PRIu32,
2147 rel_offset,
2148 ndr->relative_base_offset);
2150 if (rel_offset > ndr->data_size) {
2151 return ndr_pull_error(ndr, NDR_ERR_BUFSIZE,
2152 "ndr_pull_relative_ptr1 rel_offset(%"PRIu32") > ndr->data_size(%"PRIu32")",
2153 rel_offset, ndr->data_size);
2155 ret = ndr_token_store(ndr, &ndr->relative_list, p, rel_offset);
2156 if (ret == NDR_ERR_RANGE) {
2157 return ndr_pull_error(ndr, ret,
2158 "More than %d NDR tokens stored for relative_list",
2159 NDR_TOKEN_MAX_LIST_SIZE);
2161 return ret;
2165 pull a relative object - stage2
2166 called during BUFFERS processing
2168 _PUBLIC_ enum ndr_err_code ndr_pull_relative_ptr2(struct ndr_pull *ndr, const void *p)
2170 uint32_t rel_offset;
2171 NDR_CHECK(ndr_token_retrieve(&ndr->relative_list, p, &rel_offset));
2172 return ndr_pull_set_offset(ndr, rel_offset);
2175 _PUBLIC_ const char *ndr_map_error2string(enum ndr_err_code ndr_err)
2177 const char *ret = "Unknown error";
2179 switch (ndr_err) {
2180 case NDR_ERR_SUCCESS:
2181 ret = "Success";
2182 break;
2183 case NDR_ERR_ARRAY_SIZE:
2184 ret = "Bad Array Size";
2185 break;
2186 case NDR_ERR_BAD_SWITCH:
2187 ret = "Bad Switch";
2188 break;
2189 case NDR_ERR_OFFSET:
2190 ret = "Offset Error";
2191 break;
2192 case NDR_ERR_RELATIVE:
2193 ret = "Relative Pointer Error";
2194 break;
2195 case NDR_ERR_CHARCNV:
2196 ret = "Character Conversion Error";
2197 break;
2198 case NDR_ERR_LENGTH:
2199 ret = "Length Error";
2200 break;
2201 case NDR_ERR_SUBCONTEXT:
2202 ret = "Subcontext Error";
2203 break;
2204 case NDR_ERR_COMPRESSION:
2205 ret = "Compression Error";
2206 break;
2207 case NDR_ERR_STRING:
2208 ret = "String Error";
2209 break;
2210 case NDR_ERR_VALIDATE:
2211 ret = "Validate Error";
2212 break;
2213 case NDR_ERR_BUFSIZE:
2214 ret = "Buffer Size Error";
2215 break;
2216 case NDR_ERR_ALLOC:
2217 ret = "Allocation Error";
2218 break;
2219 case NDR_ERR_RANGE:
2220 ret = "Range Error";
2221 break;
2222 case NDR_ERR_TOKEN:
2223 ret = "Token Error";
2224 break;
2225 case NDR_ERR_IPV4ADDRESS:
2226 ret = "IPv4 Address Error";
2227 break;
2228 case NDR_ERR_INVALID_POINTER:
2229 ret = "Invalid Pointer";
2230 break;
2231 case NDR_ERR_UNREAD_BYTES:
2232 ret = "Unread Bytes";
2233 break;
2234 case NDR_ERR_NDR64:
2235 ret = "NDR64 assertion error";
2236 break;
2237 case NDR_ERR_INCOMPLETE_BUFFER:
2238 ret = "Incomplete Buffer";
2239 break;
2240 case NDR_ERR_MAX_RECURSION_EXCEEDED:
2241 ret = "Maximum Recursion Exceeded";
2242 break;
2243 case NDR_ERR_UNDERFLOW:
2244 ret = "Underflow";
2245 break;
2246 case NDR_ERR_IPV6ADDRESS:
2247 ret = "Invalid IPv6 address";
2248 break;
2249 case NDR_ERR_FLAGS:
2250 ret = "Invalid NDR flags";
2251 break;
2253 return ret;