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"
34 #define NDR_BASE_MARSHALL_SIZE 1024
36 /* this guid indicates NDR encoding in a protocol tower */
37 const struct ndr_syntax_id ndr_transfer_syntax_ndr
= {
38 { 0x8a885d04, 0x1ceb, 0x11c9, {0x9f, 0xe8}, {0x08,0x00,0x2b,0x10,0x48,0x60} },
42 const struct ndr_syntax_id ndr_transfer_syntax_ndr64
= {
43 { 0x71710533, 0xbeba, 0x4937, {0x83, 0x19}, {0xb5,0xdb,0xef,0x9c,0xcc,0x36} },
47 const struct ndr_syntax_id ndr_syntax_id_null
= {
48 { 0, 0, 0, { 0, 0 }, { 0, 0, 0, 0, 0, 0 } },
53 work out the number of bytes needed to align on a n byte boundary
55 _PUBLIC_
size_t ndr_align_size(uint32_t offset
, size_t n
)
57 if ((offset
& (n
-1)) == 0) return 0;
58 return n
- (offset
& (n
-1));
62 initialise a ndr parse structure from a data blob
64 _PUBLIC_
struct ndr_pull
*ndr_pull_init_blob(const DATA_BLOB
*blob
, TALLOC_CTX
*mem_ctx
)
68 ndr
= talloc_zero(mem_ctx
, struct ndr_pull
);
69 if (!ndr
) return NULL
;
70 ndr
->current_mem_ctx
= mem_ctx
;
72 ndr
->data
= blob
->data
;
73 ndr
->data_size
= blob
->length
;
79 advance by 'size' bytes
81 _PUBLIC_
enum ndr_err_code
ndr_pull_advance(struct ndr_pull
*ndr
, uint32_t size
)
84 if (ndr
->offset
> ndr
->data_size
) {
85 return ndr_pull_error(ndr
, NDR_ERR_BUFSIZE
,
86 "ndr_pull_advance by %u failed",
89 return NDR_ERR_SUCCESS
;
93 set the parse offset to 'ofs'
95 static enum ndr_err_code
ndr_pull_set_offset(struct ndr_pull
*ndr
, uint32_t ofs
)
98 if (ndr
->offset
> ndr
->data_size
) {
99 return ndr_pull_error(ndr
, NDR_ERR_BUFSIZE
,
100 "ndr_pull_set_offset %u failed",
103 return NDR_ERR_SUCCESS
;
106 /* create a ndr_push structure, ready for some marshalling */
107 _PUBLIC_
struct ndr_push
*ndr_push_init_ctx(TALLOC_CTX
*mem_ctx
)
109 struct ndr_push
*ndr
;
111 ndr
= talloc_zero(mem_ctx
, struct ndr_push
);
117 ndr
->alloc_size
= NDR_BASE_MARSHALL_SIZE
;
118 ndr
->data
= talloc_array(ndr
, uint8_t, ndr
->alloc_size
);
127 /* return a DATA_BLOB structure for the current ndr_push marshalled data */
128 _PUBLIC_ DATA_BLOB
ndr_push_blob(struct ndr_push
*ndr
)
131 blob
= data_blob_const(ndr
->data
, ndr
->offset
);
132 if (ndr
->alloc_size
> ndr
->offset
) {
133 ndr
->data
[ndr
->offset
] = 0;
140 expand the available space in the buffer to ndr->offset + extra_size
142 _PUBLIC_
enum ndr_err_code
ndr_push_expand(struct ndr_push
*ndr
, uint32_t extra_size
)
144 uint32_t size
= extra_size
+ ndr
->offset
;
146 if (size
< ndr
->offset
) {
147 /* extra_size overflowed the offset */
148 return ndr_push_error(ndr
, NDR_ERR_BUFSIZE
, "Overflow in push_expand to %u",
152 if (ndr
->alloc_size
> size
) {
153 return NDR_ERR_SUCCESS
;
156 ndr
->alloc_size
+= NDR_BASE_MARSHALL_SIZE
;
157 if (size
+1 > ndr
->alloc_size
) {
158 ndr
->alloc_size
= size
+1;
160 ndr
->data
= talloc_realloc(ndr
, ndr
->data
, uint8_t, ndr
->alloc_size
);
162 return ndr_push_error(ndr
, NDR_ERR_ALLOC
, "Failed to push_expand to %u",
166 return NDR_ERR_SUCCESS
;
169 _PUBLIC_
void ndr_print_debugc_helper(struct ndr_print
*ndr
, const char *format
, ...)
177 va_start(ap
, format
);
178 ret
= vasprintf(&s
, format
, ap
);
185 dbgc_class
= *(int *)ndr
->private_data
;
187 if (ndr
->no_newline
) {
188 DEBUGADDC(dbgc_class
, 1,("%s", s
));
193 for (i
=0;i
<ndr
->depth
;i
++) {
194 DEBUGADDC(dbgc_class
, 1,(" "));
197 DEBUGADDC(dbgc_class
, 1,("%s\n", s
));
201 _PUBLIC_
void ndr_print_debug_helper(struct ndr_print
*ndr
, const char *format
, ...)
208 va_start(ap
, format
);
209 ret
= vasprintf(&s
, format
, ap
);
216 if (ndr
->no_newline
) {
217 DEBUGADD(1,("%s", s
));
222 for (i
=0;i
<ndr
->depth
;i
++) {
226 DEBUGADD(1,("%s\n", s
));
230 _PUBLIC_
void ndr_print_printf_helper(struct ndr_print
*ndr
, const char *format
, ...)
235 if (!ndr
->no_newline
) {
236 for (i
=0;i
<ndr
->depth
;i
++) {
241 va_start(ap
, format
);
244 if (!ndr
->no_newline
) {
249 _PUBLIC_
void ndr_print_string_helper(struct ndr_print
*ndr
, const char *format
, ...)
254 if (!ndr
->no_newline
) {
255 for (i
=0;i
<ndr
->depth
;i
++) {
256 ndr
->private_data
= talloc_asprintf_append_buffer(
257 (char *)ndr
->private_data
, " ");
261 va_start(ap
, format
);
262 ndr
->private_data
= talloc_vasprintf_append_buffer((char *)ndr
->private_data
,
265 if (!ndr
->no_newline
) {
266 ndr
->private_data
= talloc_asprintf_append_buffer((char *)ndr
->private_data
,
272 a useful helper function for printing idl structures via DEBUGC()
274 _PUBLIC_
void ndr_print_debugc(int dbgc_class
, ndr_print_fn_t fn
, const char *name
, void *ptr
)
276 struct ndr_print
*ndr
;
278 DEBUGC(dbgc_class
, 1,(" "));
280 ndr
= talloc_zero(NULL
, struct ndr_print
);
282 ndr
->private_data
= &dbgc_class
;
283 ndr
->print
= ndr_print_debugc_helper
;
291 a useful helper function for printing idl structures via DEBUG()
293 _PUBLIC_
void ndr_print_debug(ndr_print_fn_t fn
, const char *name
, void *ptr
)
295 struct ndr_print
*ndr
;
299 ndr
= talloc_zero(NULL
, struct ndr_print
);
301 ndr
->print
= ndr_print_debug_helper
;
309 a useful helper function for printing idl unions via DEBUG()
311 _PUBLIC_
void ndr_print_union_debug(ndr_print_fn_t fn
, const char *name
, uint32_t level
, void *ptr
)
313 struct ndr_print
*ndr
;
317 ndr
= talloc_zero(NULL
, struct ndr_print
);
319 ndr
->print
= ndr_print_debug_helper
;
322 ndr_print_set_switch_value(ndr
, ptr
, level
);
328 a useful helper function for printing idl function calls via DEBUG()
330 _PUBLIC_
void ndr_print_function_debug(ndr_print_function_t fn
, const char *name
, int flags
, void *ptr
)
332 struct ndr_print
*ndr
;
336 ndr
= talloc_zero(NULL
, struct ndr_print
);
338 ndr
->print
= ndr_print_debug_helper
;
342 fn(ndr
, name
, flags
, ptr
);
347 a useful helper function for printing idl structures to a string
349 _PUBLIC_
char *ndr_print_struct_string(TALLOC_CTX
*mem_ctx
, ndr_print_fn_t fn
, const char *name
, void *ptr
)
351 struct ndr_print
*ndr
;
354 ndr
= talloc_zero(mem_ctx
, struct ndr_print
);
355 if (!ndr
) return NULL
;
356 ndr
->private_data
= talloc_strdup(ndr
, "");
357 if (!ndr
->private_data
) {
360 ndr
->print
= ndr_print_string_helper
;
365 ret
= talloc_steal(mem_ctx
, (char *)ndr
->private_data
);
372 a useful helper function for printing idl unions to a string
374 _PUBLIC_
char *ndr_print_union_string(TALLOC_CTX
*mem_ctx
, ndr_print_fn_t fn
, const char *name
, uint32_t level
, void *ptr
)
376 struct ndr_print
*ndr
;
379 ndr
= talloc_zero(mem_ctx
, struct ndr_print
);
380 if (!ndr
) return NULL
;
381 ndr
->private_data
= talloc_strdup(ndr
, "");
382 if (!ndr
->private_data
) {
385 ndr
->print
= ndr_print_string_helper
;
388 ndr_print_set_switch_value(ndr
, ptr
, level
);
390 ret
= talloc_steal(mem_ctx
, (char *)ndr
->private_data
);
397 a useful helper function for printing idl function calls to a string
399 _PUBLIC_
char *ndr_print_function_string(TALLOC_CTX
*mem_ctx
,
400 ndr_print_function_t fn
, const char *name
,
401 int flags
, void *ptr
)
403 struct ndr_print
*ndr
;
406 ndr
= talloc_zero(mem_ctx
, struct ndr_print
);
407 if (!ndr
) return NULL
;
408 ndr
->private_data
= talloc_strdup(ndr
, "");
409 if (!ndr
->private_data
) {
412 ndr
->print
= ndr_print_string_helper
;
415 fn(ndr
, name
, flags
, ptr
);
416 ret
= talloc_steal(mem_ctx
, (char *)ndr
->private_data
);
422 _PUBLIC_
void ndr_set_flags(uint32_t *pflags
, uint32_t new_flags
)
424 /* the big/little endian flags are inter-dependent */
425 if (new_flags
& LIBNDR_FLAG_LITTLE_ENDIAN
) {
426 (*pflags
) &= ~LIBNDR_FLAG_BIGENDIAN
;
427 (*pflags
) &= ~LIBNDR_FLAG_NDR64
;
429 if (new_flags
& LIBNDR_FLAG_BIGENDIAN
) {
430 (*pflags
) &= ~LIBNDR_FLAG_LITTLE_ENDIAN
;
431 (*pflags
) &= ~LIBNDR_FLAG_NDR64
;
433 if (new_flags
& LIBNDR_ALIGN_FLAGS
) {
434 /* Ensure we only have the passed-in
435 align flag set in the new_flags,
436 remove any old align flag. */
437 (*pflags
) &= ~LIBNDR_ALIGN_FLAGS
;
439 if (new_flags
& LIBNDR_FLAG_NO_RELATIVE_REVERSE
) {
440 (*pflags
) &= ~LIBNDR_FLAG_RELATIVE_REVERSE
;
442 (*pflags
) |= new_flags
;
446 return and possibly log an NDR error
448 _PUBLIC_
enum ndr_err_code
ndr_pull_error(struct ndr_pull
*ndr
,
449 enum ndr_err_code ndr_err
,
450 const char *format
, ...)
456 va_start(ap
, format
);
457 ret
= vasprintf(&s
, format
, ap
);
461 return NDR_ERR_ALLOC
;
464 DEBUG(1,("ndr_pull_error(%u): %s\n", ndr_err
, s
));
472 return and possibly log an NDR error
474 _PUBLIC_
enum ndr_err_code
ndr_push_error(struct ndr_push
*ndr
,
475 enum ndr_err_code ndr_err
,
476 const char *format
, ...)
482 va_start(ap
, format
);
483 ret
= vasprintf(&s
, format
, ap
);
487 return NDR_ERR_ALLOC
;
490 DEBUG(1,("ndr_push_error(%u): %s\n", ndr_err
, s
));
498 handle subcontext buffers, which in midl land are user-marshalled, but
499 we use magic in pidl to make them easier to cope with
501 _PUBLIC_
enum ndr_err_code
ndr_pull_subcontext_start(struct ndr_pull
*ndr
,
502 struct ndr_pull
**_subndr
,
506 struct ndr_pull
*subndr
;
507 uint32_t r_content_size
;
508 bool force_le
= false;
509 bool force_be
= false;
511 switch (header_size
) {
513 uint32_t content_size
= ndr
->data_size
- ndr
->offset
;
515 content_size
= size_is
;
517 r_content_size
= content_size
;
522 uint16_t content_size
;
523 NDR_CHECK(ndr_pull_uint16(ndr
, NDR_SCALARS
, &content_size
));
524 if (size_is
>= 0 && size_is
!= content_size
) {
525 return ndr_pull_error(ndr
, NDR_ERR_SUBCONTEXT
, "Bad subcontext (PULL) size_is(%d) mismatch content_size %d",
526 (int)size_is
, (int)content_size
);
528 r_content_size
= content_size
;
533 uint32_t content_size
;
534 NDR_CHECK(ndr_pull_uint3264(ndr
, NDR_SCALARS
, &content_size
));
535 if (size_is
>= 0 && size_is
!= content_size
) {
536 return ndr_pull_error(ndr
, NDR_ERR_SUBCONTEXT
, "Bad subcontext (PULL) size_is(%d) mismatch content_size %d",
537 (int)size_is
, (int)content_size
);
539 r_content_size
= content_size
;
544 * Common Type Header for the Serialization Stream
545 * See [MS-RPCE] 2.2.6 Type Serialization Version 1
551 uint32_t content_size
;
555 NDR_CHECK(ndr_pull_uint8(ndr
, NDR_SCALARS
, &version
));
558 return ndr_pull_error(ndr
, NDR_ERR_SUBCONTEXT
,
559 "Bad subcontext (PULL) Common Type Header version %d != 1",
567 NDR_CHECK(ndr_pull_uint8(ndr
, NDR_SCALARS
, &drep
));
570 } else if (drep
== 0x00) {
573 return ndr_pull_error(ndr
, NDR_ERR_SUBCONTEXT
,
574 "Bad subcontext (PULL) Common Type Header invalid drep 0x%02X",
578 /* length of the "Private Header for Constructed Type" */
579 NDR_CHECK(ndr_pull_uint16(ndr
, NDR_SCALARS
, &hdrlen
));
581 return ndr_pull_error(ndr
, NDR_ERR_SUBCONTEXT
,
582 "Bad subcontext (PULL) Common Type Header length %d != 8",
586 /* filler should be ignored */
587 NDR_CHECK(ndr_pull_uint32(ndr
, NDR_SCALARS
, &filler
));
590 * Private Header for Constructed Type
592 /* length - will be updated latter */
593 NDR_CHECK(ndr_pull_uint32(ndr
, NDR_SCALARS
, &content_size
));
594 if (size_is
>= 0 && size_is
!= content_size
) {
595 return ndr_pull_error(ndr
, NDR_ERR_SUBCONTEXT
, "Bad subcontext (PULL) size_is(%d) mismatch content_size %d",
596 (int)size_is
, (int)content_size
);
598 /* the content size must be a multiple of 8 */
599 if ((content_size
% 8) != 0) {
600 return ndr_pull_error(ndr
, NDR_ERR_SUBCONTEXT
,
601 "Bad subcontext (PULL) size_is(%d) not padded to 8 content_size %d",
602 (int)size_is
, (int)content_size
);
604 r_content_size
= content_size
;
607 NDR_CHECK(ndr_pull_uint32(ndr
, NDR_SCALARS
, &reserved
));
611 return ndr_pull_error(ndr
, NDR_ERR_SUBCONTEXT
, "Bad subcontext (PULL) header_size %d",
615 NDR_PULL_NEED_BYTES(ndr
, r_content_size
);
617 subndr
= talloc_zero(ndr
, struct ndr_pull
);
618 NDR_ERR_HAVE_NO_MEMORY(subndr
);
619 subndr
->flags
= ndr
->flags
& ~LIBNDR_FLAG_NDR64
;
620 subndr
->current_mem_ctx
= ndr
->current_mem_ctx
;
622 subndr
->data
= ndr
->data
+ ndr
->offset
;
624 subndr
->data_size
= r_content_size
;
627 ndr_set_flags(&ndr
->flags
, LIBNDR_FLAG_LITTLE_ENDIAN
);
628 } else if (force_be
) {
629 ndr_set_flags(&ndr
->flags
, LIBNDR_FLAG_BIGENDIAN
);
633 return NDR_ERR_SUCCESS
;
636 _PUBLIC_
enum ndr_err_code
ndr_pull_subcontext_end(struct ndr_pull
*ndr
,
637 struct ndr_pull
*subndr
,
642 uint32_t highest_ofs
;
646 } else if (header_size
> 0) {
647 advance
= subndr
->data_size
;
649 advance
= subndr
->offset
;
652 if (subndr
->offset
> ndr
->relative_highest_offset
) {
653 highest_ofs
= subndr
->offset
;
655 highest_ofs
= subndr
->relative_highest_offset
;
657 if (!(subndr
->flags
& LIBNDR_FLAG_SUBCONTEXT_NO_UNREAD_BYTES
)) {
659 * avoid an error unless SUBCONTEXT_NO_UNREAD_BYTES is specified
661 highest_ofs
= advance
;
663 if (highest_ofs
< advance
) {
664 return ndr_pull_error(subndr
, NDR_ERR_UNREAD_BYTES
,
665 "not all bytes consumed ofs[%u] advance[%u]",
666 highest_ofs
, advance
);
669 NDR_CHECK(ndr_pull_advance(ndr
, advance
));
670 return NDR_ERR_SUCCESS
;
673 _PUBLIC_
enum ndr_err_code
ndr_push_subcontext_start(struct ndr_push
*ndr
,
674 struct ndr_push
**_subndr
,
678 struct ndr_push
*subndr
;
680 subndr
= ndr_push_init_ctx(ndr
);
681 NDR_ERR_HAVE_NO_MEMORY(subndr
);
682 subndr
->flags
= ndr
->flags
& ~LIBNDR_FLAG_NDR64
;
685 NDR_CHECK(ndr_push_zero(subndr
, size_is
));
687 subndr
->relative_end_offset
= size_is
;
691 return NDR_ERR_SUCCESS
;
695 push a subcontext header
697 _PUBLIC_
enum ndr_err_code
ndr_push_subcontext_end(struct ndr_push
*ndr
,
698 struct ndr_push
*subndr
,
705 padding_len
= size_is
- subndr
->offset
;
706 if (padding_len
< 0) {
707 return ndr_push_error(ndr
, NDR_ERR_SUBCONTEXT
, "Bad subcontext (PUSH) content_size %d is larger than size_is(%d)",
708 (int)subndr
->offset
, (int)size_is
);
710 subndr
->offset
= size_is
;
713 switch (header_size
) {
718 NDR_CHECK(ndr_push_uint16(ndr
, NDR_SCALARS
, subndr
->offset
));
722 NDR_CHECK(ndr_push_uint3264(ndr
, NDR_SCALARS
, subndr
->offset
));
727 * Common Type Header for the Serialization Stream
728 * See [MS-RPCE] 2.2.6 Type Serialization Version 1
730 padding_len
= NDR_ROUND(subndr
->offset
, 8) - subndr
->offset
;
731 if (padding_len
> 0) {
732 NDR_CHECK(ndr_push_zero(subndr
, padding_len
));
736 NDR_CHECK(ndr_push_uint8(ndr
, NDR_SCALARS
, 1));
742 NDR_CHECK(ndr_push_uint8(ndr
, NDR_SCALARS
, NDR_BE(ndr
)?0x00:0x10));
744 /* length of the "Private Header for Constructed Type" */
745 NDR_CHECK(ndr_push_uint16(ndr
, NDR_SCALARS
, 8));
748 NDR_CHECK(ndr_push_uint32(ndr
, NDR_SCALARS
, 0xCCCCCCCC));
751 * Private Header for Constructed Type
753 /* length - will be updated latter */
754 NDR_CHECK(ndr_push_uint32(ndr
, NDR_SCALARS
, subndr
->offset
));
757 NDR_CHECK(ndr_push_uint32(ndr
, NDR_SCALARS
, 0));
761 return ndr_push_error(ndr
, NDR_ERR_SUBCONTEXT
, "Bad subcontext header size %d",
765 NDR_CHECK(ndr_push_bytes(ndr
, subndr
->data
, subndr
->offset
));
766 return NDR_ERR_SUCCESS
;
770 store a token in the ndr context, for later retrieval
772 _PUBLIC_
enum ndr_err_code
ndr_token_store(TALLOC_CTX
*mem_ctx
,
773 struct ndr_token_list
**list
,
777 struct ndr_token_list
*tok
;
778 tok
= talloc(mem_ctx
, struct ndr_token_list
);
779 NDR_ERR_HAVE_NO_MEMORY(tok
);
782 DLIST_ADD((*list
), tok
);
783 return NDR_ERR_SUCCESS
;
787 retrieve a token from a ndr context, using cmp_fn to match the tokens
789 _PUBLIC_
enum ndr_err_code
ndr_token_retrieve_cmp_fn(struct ndr_token_list
**list
, const void *key
, uint32_t *v
,
790 comparison_fn_t _cmp_fn
, bool _remove_tok
)
792 struct ndr_token_list
*tok
;
793 for (tok
=*list
;tok
;tok
=tok
->next
) {
794 if (_cmp_fn
&& _cmp_fn(tok
->key
,key
)==0) goto found
;
795 else if (!_cmp_fn
&& tok
->key
== key
) goto found
;
797 return NDR_ERR_TOKEN
;
801 DLIST_REMOVE((*list
), tok
);
804 return NDR_ERR_SUCCESS
;
808 retrieve a token from a ndr context
810 _PUBLIC_
enum ndr_err_code
ndr_token_retrieve(struct ndr_token_list
**list
, const void *key
, uint32_t *v
)
812 return ndr_token_retrieve_cmp_fn(list
, key
, v
, NULL
, true);
816 peek at but don't removed a token from a ndr context
818 _PUBLIC_
uint32_t ndr_token_peek(struct ndr_token_list
**list
, const void *key
)
820 enum ndr_err_code status
;
823 status
= ndr_token_retrieve_cmp_fn(list
, key
, &v
, NULL
, false);
824 if (!NDR_ERR_CODE_IS_SUCCESS(status
)) {
832 pull an array size field and add it to the array_size_list token list
834 _PUBLIC_
enum ndr_err_code
ndr_pull_array_size(struct ndr_pull
*ndr
, const void *p
)
837 NDR_CHECK(ndr_pull_uint3264(ndr
, NDR_SCALARS
, &size
));
838 return ndr_token_store(ndr
, &ndr
->array_size_list
, p
, size
);
842 get the stored array size field
844 _PUBLIC_
uint32_t ndr_get_array_size(struct ndr_pull
*ndr
, const void *p
)
846 return ndr_token_peek(&ndr
->array_size_list
, p
);
850 check the stored array size field
852 _PUBLIC_
enum ndr_err_code
ndr_check_array_size(struct ndr_pull
*ndr
, void *p
, uint32_t size
)
855 stored
= ndr_token_peek(&ndr
->array_size_list
, p
);
856 if (stored
!= size
) {
857 return ndr_pull_error(ndr
, NDR_ERR_ARRAY_SIZE
,
858 "Bad array size - got %u expected %u\n",
861 return NDR_ERR_SUCCESS
;
865 pull an array length field and add it to the array_length_list token list
867 _PUBLIC_
enum ndr_err_code
ndr_pull_array_length(struct ndr_pull
*ndr
, const void *p
)
869 uint32_t length
, offset
;
870 NDR_CHECK(ndr_pull_uint3264(ndr
, NDR_SCALARS
, &offset
));
872 return ndr_pull_error(ndr
, NDR_ERR_ARRAY_SIZE
,
873 "non-zero array offset %u\n", offset
);
875 NDR_CHECK(ndr_pull_uint3264(ndr
, NDR_SCALARS
, &length
));
876 return ndr_token_store(ndr
, &ndr
->array_length_list
, p
, length
);
880 get the stored array length field
882 _PUBLIC_
uint32_t ndr_get_array_length(struct ndr_pull
*ndr
, const void *p
)
884 return ndr_token_peek(&ndr
->array_length_list
, p
);
888 check the stored array length field
890 _PUBLIC_
enum ndr_err_code
ndr_check_array_length(struct ndr_pull
*ndr
, void *p
, uint32_t length
)
893 stored
= ndr_token_peek(&ndr
->array_length_list
, p
);
894 if (stored
!= length
) {
895 return ndr_pull_error(ndr
, NDR_ERR_ARRAY_SIZE
,
896 "Bad array length - got %u expected %u\n",
899 return NDR_ERR_SUCCESS
;
902 _PUBLIC_
enum ndr_err_code
ndr_push_pipe_chunk_trailer(struct ndr_push
*ndr
, int ndr_flags
, uint32_t count
)
904 if (ndr
->flags
& LIBNDR_FLAG_NDR64
) {
905 int64_t tmp
= 0 - (int64_t)count
;
906 uint64_t ncount
= tmp
;
908 NDR_CHECK(ndr_push_hyper(ndr
, ndr_flags
, ncount
));
911 return NDR_ERR_SUCCESS
;
914 _PUBLIC_
enum ndr_err_code
ndr_check_pipe_chunk_trailer(struct ndr_pull
*ndr
, int ndr_flags
, uint32_t count
)
916 if (ndr
->flags
& LIBNDR_FLAG_NDR64
) {
917 int64_t tmp
= 0 - (int64_t)count
;
918 uint64_t ncount1
= tmp
;
921 NDR_CHECK(ndr_pull_hyper(ndr
, ndr_flags
, &ncount2
));
922 if (ncount1
== ncount2
) {
923 return NDR_ERR_SUCCESS
;
926 return ndr_pull_error(ndr
, NDR_ERR_ARRAY_SIZE
,
927 "Bad pipe trailer[%lld should be %lld] size was %lu\"",
928 (unsigned long long)ncount2
,
929 (unsigned long long)ncount1
,
930 (unsigned long)count
);
933 return NDR_ERR_SUCCESS
;
939 _PUBLIC_
enum ndr_err_code
ndr_push_set_switch_value(struct ndr_push
*ndr
, const void *p
, uint32_t val
)
941 return ndr_token_store(ndr
, &ndr
->switch_list
, p
, val
);
944 _PUBLIC_
enum ndr_err_code
ndr_pull_set_switch_value(struct ndr_pull
*ndr
, const void *p
, uint32_t val
)
946 return ndr_token_store(ndr
, &ndr
->switch_list
, p
, val
);
949 _PUBLIC_
enum ndr_err_code
ndr_print_set_switch_value(struct ndr_print
*ndr
, const void *p
, uint32_t val
)
951 return ndr_token_store(ndr
, &ndr
->switch_list
, p
, val
);
955 retrieve a switch value
957 _PUBLIC_
uint32_t ndr_push_get_switch_value(struct ndr_push
*ndr
, const void *p
)
959 return ndr_token_peek(&ndr
->switch_list
, p
);
962 _PUBLIC_
uint32_t ndr_pull_get_switch_value(struct ndr_pull
*ndr
, const void *p
)
964 return ndr_token_peek(&ndr
->switch_list
, p
);
967 _PUBLIC_
uint32_t ndr_print_get_switch_value(struct ndr_print
*ndr
, const void *p
)
969 return ndr_token_peek(&ndr
->switch_list
, p
);
973 pull a struct from a blob using NDR
975 _PUBLIC_
enum ndr_err_code
ndr_pull_struct_blob(const DATA_BLOB
*blob
, TALLOC_CTX
*mem_ctx
, void *p
,
976 ndr_pull_flags_fn_t fn
)
978 struct ndr_pull
*ndr
;
979 ndr
= ndr_pull_init_blob(blob
, mem_ctx
);
980 NDR_ERR_HAVE_NO_MEMORY(ndr
);
981 NDR_CHECK_FREE(fn(ndr
, NDR_SCALARS
|NDR_BUFFERS
, p
));
983 return NDR_ERR_SUCCESS
;
987 pull a struct from a blob using NDR - failing if all bytes are not consumed
989 _PUBLIC_
enum ndr_err_code
ndr_pull_struct_blob_all(const DATA_BLOB
*blob
, TALLOC_CTX
*mem_ctx
,
990 void *p
, ndr_pull_flags_fn_t fn
)
992 struct ndr_pull
*ndr
;
993 uint32_t highest_ofs
;
994 ndr
= ndr_pull_init_blob(blob
, mem_ctx
);
995 NDR_ERR_HAVE_NO_MEMORY(ndr
);
996 NDR_CHECK_FREE(fn(ndr
, NDR_SCALARS
|NDR_BUFFERS
, p
));
997 if (ndr
->offset
> ndr
->relative_highest_offset
) {
998 highest_ofs
= ndr
->offset
;
1000 highest_ofs
= ndr
->relative_highest_offset
;
1002 if (highest_ofs
< ndr
->data_size
) {
1003 enum ndr_err_code ret
;
1004 ret
= ndr_pull_error(ndr
, NDR_ERR_UNREAD_BYTES
,
1005 "not all bytes consumed ofs[%u] size[%u]",
1006 highest_ofs
, ndr
->data_size
);
1011 return NDR_ERR_SUCCESS
;
1015 pull a union from a blob using NDR, given the union discriminator
1017 _PUBLIC_
enum ndr_err_code
ndr_pull_union_blob(const DATA_BLOB
*blob
, TALLOC_CTX
*mem_ctx
,
1019 uint32_t level
, ndr_pull_flags_fn_t fn
)
1021 struct ndr_pull
*ndr
;
1022 ndr
= ndr_pull_init_blob(blob
, mem_ctx
);
1023 NDR_ERR_HAVE_NO_MEMORY(ndr
);
1024 NDR_CHECK_FREE(ndr_pull_set_switch_value(ndr
, p
, level
));
1025 NDR_CHECK_FREE(fn(ndr
, NDR_SCALARS
|NDR_BUFFERS
, p
));
1027 return NDR_ERR_SUCCESS
;
1031 pull a union from a blob using NDR, given the union discriminator,
1032 failing if all bytes are not consumed
1034 _PUBLIC_
enum ndr_err_code
ndr_pull_union_blob_all(const DATA_BLOB
*blob
, TALLOC_CTX
*mem_ctx
,
1036 uint32_t level
, ndr_pull_flags_fn_t fn
)
1038 struct ndr_pull
*ndr
;
1039 uint32_t highest_ofs
;
1040 ndr
= ndr_pull_init_blob(blob
, mem_ctx
);
1041 NDR_ERR_HAVE_NO_MEMORY(ndr
);
1042 NDR_CHECK_FREE(ndr_pull_set_switch_value(ndr
, p
, level
));
1043 NDR_CHECK_FREE(fn(ndr
, NDR_SCALARS
|NDR_BUFFERS
, p
));
1044 if (ndr
->offset
> ndr
->relative_highest_offset
) {
1045 highest_ofs
= ndr
->offset
;
1047 highest_ofs
= ndr
->relative_highest_offset
;
1049 if (highest_ofs
< ndr
->data_size
) {
1050 enum ndr_err_code ret
;
1051 ret
= ndr_pull_error(ndr
, NDR_ERR_UNREAD_BYTES
,
1052 "not all bytes consumed ofs[%u] size[%u]",
1053 highest_ofs
, ndr
->data_size
);
1058 return NDR_ERR_SUCCESS
;
1062 push a struct to a blob using NDR
1064 _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
)
1066 struct ndr_push
*ndr
;
1067 ndr
= ndr_push_init_ctx(mem_ctx
);
1068 NDR_ERR_HAVE_NO_MEMORY(ndr
);
1070 NDR_CHECK(fn(ndr
, NDR_SCALARS
|NDR_BUFFERS
, p
));
1072 *blob
= ndr_push_blob(ndr
);
1073 talloc_steal(mem_ctx
, blob
->data
);
1076 return NDR_ERR_SUCCESS
;
1080 push a union to a blob using NDR
1082 _PUBLIC_
enum ndr_err_code
ndr_push_union_blob(DATA_BLOB
*blob
, TALLOC_CTX
*mem_ctx
, void *p
,
1083 uint32_t level
, ndr_push_flags_fn_t fn
)
1085 struct ndr_push
*ndr
;
1086 ndr
= ndr_push_init_ctx(mem_ctx
);
1087 NDR_ERR_HAVE_NO_MEMORY(ndr
);
1089 NDR_CHECK(ndr_push_set_switch_value(ndr
, p
, level
));
1090 NDR_CHECK(fn(ndr
, NDR_SCALARS
|NDR_BUFFERS
, p
));
1092 *blob
= ndr_push_blob(ndr
);
1093 talloc_steal(mem_ctx
, blob
->data
);
1096 return NDR_ERR_SUCCESS
;
1100 generic ndr_size_*() handler for structures
1102 _PUBLIC_
size_t ndr_size_struct(const void *p
, int flags
, ndr_push_flags_fn_t push
)
1104 struct ndr_push
*ndr
;
1105 enum ndr_err_code status
;
1108 /* avoid recursion */
1109 if (flags
& LIBNDR_FLAG_NO_NDR_SIZE
) return 0;
1111 ndr
= ndr_push_init_ctx(NULL
);
1113 ndr
->flags
|= flags
| LIBNDR_FLAG_NO_NDR_SIZE
;
1114 status
= push(ndr
, NDR_SCALARS
|NDR_BUFFERS
, discard_const(p
));
1115 if (!NDR_ERR_CODE_IS_SUCCESS(status
)) {
1125 generic ndr_size_*() handler for unions
1127 _PUBLIC_
size_t ndr_size_union(const void *p
, int flags
, uint32_t level
, ndr_push_flags_fn_t push
)
1129 struct ndr_push
*ndr
;
1130 enum ndr_err_code status
;
1133 /* avoid recursion */
1134 if (flags
& LIBNDR_FLAG_NO_NDR_SIZE
) return 0;
1136 ndr
= ndr_push_init_ctx(NULL
);
1138 ndr
->flags
|= flags
| LIBNDR_FLAG_NO_NDR_SIZE
;
1140 status
= ndr_push_set_switch_value(ndr
, p
, level
);
1141 if (!NDR_ERR_CODE_IS_SUCCESS(status
)) {
1145 status
= push(ndr
, NDR_SCALARS
|NDR_BUFFERS
, p
);
1146 if (!NDR_ERR_CODE_IS_SUCCESS(status
)) {
1156 get the current base for relative pointers for the push
1158 _PUBLIC_
uint32_t ndr_push_get_relative_base_offset(struct ndr_push
*ndr
)
1160 return ndr
->relative_base_offset
;
1164 restore the old base for relative pointers for the push
1166 _PUBLIC_
void ndr_push_restore_relative_base_offset(struct ndr_push
*ndr
, uint32_t offset
)
1168 ndr
->relative_base_offset
= offset
;
1172 setup the current base for relative pointers for the push
1173 called in the NDR_SCALAR stage
1175 _PUBLIC_
enum ndr_err_code
ndr_push_setup_relative_base_offset1(struct ndr_push
*ndr
, const void *p
, uint32_t offset
)
1177 ndr
->relative_base_offset
= offset
;
1178 return ndr_token_store(ndr
, &ndr
->relative_base_list
, p
, offset
);
1182 setup the current base for relative pointers for the push
1183 called in the NDR_BUFFERS stage
1185 _PUBLIC_
enum ndr_err_code
ndr_push_setup_relative_base_offset2(struct ndr_push
*ndr
, const void *p
)
1187 return ndr_token_retrieve(&ndr
->relative_base_list
, p
, &ndr
->relative_base_offset
);
1191 push a relative object - stage1
1192 this is called during SCALARS processing
1194 _PUBLIC_
enum ndr_err_code
ndr_push_relative_ptr1(struct ndr_push
*ndr
, const void *p
)
1197 NDR_CHECK(ndr_push_uint32(ndr
, NDR_SCALARS
, 0));
1198 return NDR_ERR_SUCCESS
;
1200 NDR_CHECK(ndr_push_align(ndr
, 4));
1201 NDR_CHECK(ndr_token_store(ndr
, &ndr
->relative_list
, p
, ndr
->offset
));
1202 return ndr_push_uint32(ndr
, NDR_SCALARS
, 0xFFFFFFFF);
1206 push a short relative object - stage1
1207 this is called during SCALARS processing
1209 _PUBLIC_
enum ndr_err_code
ndr_push_short_relative_ptr1(struct ndr_push
*ndr
, const void *p
)
1212 NDR_CHECK(ndr_push_uint16(ndr
, NDR_SCALARS
, 0));
1213 return NDR_ERR_SUCCESS
;
1215 NDR_CHECK(ndr_push_align(ndr
, 2));
1216 NDR_CHECK(ndr_token_store(ndr
, &ndr
->relative_list
, p
, ndr
->offset
));
1217 return ndr_push_uint16(ndr
, NDR_SCALARS
, 0xFFFF);
1220 push a relative object - stage2
1221 this is called during buffers processing
1223 static enum ndr_err_code
ndr_push_relative_ptr2(struct ndr_push
*ndr
, const void *p
)
1225 uint32_t save_offset
;
1226 uint32_t ptr_offset
= 0xFFFFFFFF;
1228 return NDR_ERR_SUCCESS
;
1230 save_offset
= ndr
->offset
;
1231 NDR_CHECK(ndr_token_retrieve(&ndr
->relative_list
, p
, &ptr_offset
));
1232 if (ptr_offset
> ndr
->offset
) {
1233 return ndr_push_error(ndr
, NDR_ERR_BUFSIZE
,
1234 "ndr_push_relative_ptr2 ptr_offset(%u) > ndr->offset(%u)",
1235 ptr_offset
, ndr
->offset
);
1237 ndr
->offset
= ptr_offset
;
1238 if (save_offset
< ndr
->relative_base_offset
) {
1239 return ndr_push_error(ndr
, NDR_ERR_BUFSIZE
,
1240 "ndr_push_relative_ptr2 save_offset(%u) < ndr->relative_base_offset(%u)",
1241 save_offset
, ndr
->relative_base_offset
);
1243 NDR_CHECK(ndr_push_uint32(ndr
, NDR_SCALARS
, save_offset
- ndr
->relative_base_offset
));
1244 ndr
->offset
= save_offset
;
1245 return NDR_ERR_SUCCESS
;
1248 push a short relative object - stage2
1249 this is called during buffers processing
1251 _PUBLIC_
enum ndr_err_code
ndr_push_short_relative_ptr2(struct ndr_push
*ndr
, const void *p
)
1253 uint32_t save_offset
;
1254 uint32_t ptr_offset
= 0xFFFF;
1256 return NDR_ERR_SUCCESS
;
1258 save_offset
= ndr
->offset
;
1259 NDR_CHECK(ndr_token_retrieve(&ndr
->relative_list
, p
, &ptr_offset
));
1260 if (ptr_offset
> ndr
->offset
) {
1261 return ndr_push_error(ndr
, NDR_ERR_BUFSIZE
,
1262 "ndr_push_short_relative_ptr2 ptr_offset(%u) > ndr->offset(%u)",
1263 ptr_offset
, ndr
->offset
);
1265 ndr
->offset
= ptr_offset
;
1266 if (save_offset
< ndr
->relative_base_offset
) {
1267 return ndr_push_error(ndr
, NDR_ERR_BUFSIZE
,
1268 "ndr_push_relative_ptr2 save_offset(%u) < ndr->relative_base_offset(%u)",
1269 save_offset
, ndr
->relative_base_offset
);
1271 NDR_CHECK(ndr_push_uint16(ndr
, NDR_SCALARS
, save_offset
- ndr
->relative_base_offset
));
1272 ndr
->offset
= save_offset
;
1273 return NDR_ERR_SUCCESS
;
1277 push a relative object - stage2 start
1278 this is called during buffers processing
1280 _PUBLIC_
enum ndr_err_code
ndr_push_relative_ptr2_start(struct ndr_push
*ndr
, const void *p
)
1283 return NDR_ERR_SUCCESS
;
1285 if (!(ndr
->flags
& LIBNDR_FLAG_RELATIVE_REVERSE
)) {
1286 uint32_t relative_offset
;
1290 if (ndr
->offset
< ndr
->relative_base_offset
) {
1291 return ndr_push_error(ndr
, NDR_ERR_BUFSIZE
,
1292 "ndr_push_relative_ptr2_start ndr->offset(%u) < ndr->relative_base_offset(%u)",
1293 ndr
->offset
, ndr
->relative_base_offset
);
1296 relative_offset
= ndr
->offset
- ndr
->relative_base_offset
;
1298 if (ndr
->flags
& LIBNDR_FLAG_NOALIGN
) {
1300 } else if (ndr
->flags
& LIBNDR_FLAG_ALIGN2
) {
1302 } else if (ndr
->flags
& LIBNDR_FLAG_ALIGN4
) {
1304 } else if (ndr
->flags
& LIBNDR_FLAG_ALIGN8
) {
1308 pad
= ndr_align_size(relative_offset
, align
);
1310 NDR_CHECK(ndr_push_zero(ndr
, pad
));
1313 return ndr_push_relative_ptr2(ndr
, p
);
1315 if (ndr
->relative_end_offset
== -1) {
1316 return ndr_push_error(ndr
, NDR_ERR_RELATIVE
,
1317 "ndr_push_relative_ptr2_start RELATIVE_REVERSE flag set and relative_end_offset %d",
1318 ndr
->relative_end_offset
);
1320 NDR_CHECK(ndr_token_store(ndr
, &ndr
->relative_begin_list
, p
, ndr
->offset
));
1321 return NDR_ERR_SUCCESS
;
1325 push a relative object - stage2 end
1326 this is called during buffers processing
1328 _PUBLIC_
enum ndr_err_code
ndr_push_relative_ptr2_end(struct ndr_push
*ndr
, const void *p
)
1330 uint32_t begin_offset
= 0xFFFFFFFF;
1332 uint32_t correct_offset
= 0;
1337 return NDR_ERR_SUCCESS
;
1340 if (!(ndr
->flags
& LIBNDR_FLAG_RELATIVE_REVERSE
)) {
1341 return NDR_ERR_SUCCESS
;
1344 if (ndr
->flags
& LIBNDR_FLAG_NO_NDR_SIZE
) {
1345 /* better say more than calculation a too small buffer */
1346 NDR_PUSH_ALIGN(ndr
, 8);
1347 return NDR_ERR_SUCCESS
;
1350 if (ndr
->relative_end_offset
< ndr
->offset
) {
1351 return ndr_push_error(ndr
, NDR_ERR_RELATIVE
,
1352 "ndr_push_relative_ptr2_end:"
1353 "relative_end_offset %u < offset %u",
1354 ndr
->relative_end_offset
, ndr
->offset
);
1357 NDR_CHECK(ndr_token_retrieve(&ndr
->relative_begin_list
, p
, &begin_offset
));
1359 /* we have marshalled a buffer, see how long it was */
1360 len
= ndr
->offset
- begin_offset
;
1363 return ndr_push_error(ndr
, NDR_ERR_RELATIVE
,
1364 "ndr_push_relative_ptr2_end:"
1365 "offset %u - begin_offset %u < 0",
1366 ndr
->offset
, begin_offset
);
1369 if (ndr
->relative_end_offset
< len
) {
1370 return ndr_push_error(ndr
, NDR_ERR_RELATIVE
,
1371 "ndr_push_relative_ptr2_end:"
1372 "relative_end_offset %u < len %lld",
1373 ndr
->offset
, (long long)len
);
1376 /* the reversed offset is at the end of the main buffer */
1377 correct_offset
= ndr
->relative_end_offset
- len
;
1379 if (ndr
->flags
& LIBNDR_FLAG_NOALIGN
) {
1381 } else if (ndr
->flags
& LIBNDR_FLAG_ALIGN2
) {
1383 } else if (ndr
->flags
& LIBNDR_FLAG_ALIGN4
) {
1385 } else if (ndr
->flags
& LIBNDR_FLAG_ALIGN8
) {
1389 pad
= ndr_align_size(correct_offset
, align
);
1391 correct_offset
+= pad
;
1392 correct_offset
-= align
;
1395 if (correct_offset
< begin_offset
) {
1396 return ndr_push_error(ndr
, NDR_ERR_RELATIVE
,
1397 "ndr_push_relative_ptr2_end: "
1398 "correct_offset %u < begin_offset %u",
1399 correct_offset
, begin_offset
);
1403 uint32_t clear_size
= correct_offset
- begin_offset
;
1405 clear_size
= MIN(clear_size
, len
);
1407 /* now move the marshalled buffer to the end of the main buffer */
1408 memmove(ndr
->data
+ correct_offset
, ndr
->data
+ begin_offset
, len
);
1411 /* and wipe out old buffer within the main buffer */
1412 memset(ndr
->data
+ begin_offset
, '\0', clear_size
);
1416 /* and set the end offset for the next buffer */
1417 ndr
->relative_end_offset
= correct_offset
;
1419 /* finally write the offset to the main buffer */
1420 ndr
->offset
= correct_offset
;
1421 NDR_CHECK(ndr_push_relative_ptr2(ndr
, p
));
1423 /* restore to where we were in the main buffer */
1424 ndr
->offset
= begin_offset
;
1426 return NDR_ERR_SUCCESS
;
1430 get the current base for relative pointers for the pull
1432 _PUBLIC_
uint32_t ndr_pull_get_relative_base_offset(struct ndr_pull
*ndr
)
1434 return ndr
->relative_base_offset
;
1438 restore the old base for relative pointers for the pull
1440 _PUBLIC_
void ndr_pull_restore_relative_base_offset(struct ndr_pull
*ndr
, uint32_t offset
)
1442 ndr
->relative_base_offset
= offset
;
1446 setup the current base for relative pointers for the pull
1447 called in the NDR_SCALAR stage
1449 _PUBLIC_
enum ndr_err_code
ndr_pull_setup_relative_base_offset1(struct ndr_pull
*ndr
, const void *p
, uint32_t offset
)
1451 ndr
->relative_base_offset
= offset
;
1452 return ndr_token_store(ndr
, &ndr
->relative_base_list
, p
, offset
);
1456 setup the current base for relative pointers for the pull
1457 called in the NDR_BUFFERS stage
1459 _PUBLIC_
enum ndr_err_code
ndr_pull_setup_relative_base_offset2(struct ndr_pull
*ndr
, const void *p
)
1461 return ndr_token_retrieve(&ndr
->relative_base_list
, p
, &ndr
->relative_base_offset
);
1465 pull a relative object - stage1
1466 called during SCALARS processing
1468 _PUBLIC_
enum ndr_err_code
ndr_pull_relative_ptr1(struct ndr_pull
*ndr
, const void *p
, uint32_t rel_offset
)
1470 rel_offset
+= ndr
->relative_base_offset
;
1471 if (rel_offset
> ndr
->data_size
) {
1472 return ndr_pull_error(ndr
, NDR_ERR_BUFSIZE
,
1473 "ndr_pull_relative_ptr1 rel_offset(%u) > ndr->data_size(%u)",
1474 rel_offset
, ndr
->data_size
);
1476 return ndr_token_store(ndr
, &ndr
->relative_list
, p
, rel_offset
);
1480 pull a relative object - stage2
1481 called during BUFFERS processing
1483 _PUBLIC_
enum ndr_err_code
ndr_pull_relative_ptr2(struct ndr_pull
*ndr
, const void *p
)
1485 uint32_t rel_offset
;
1486 NDR_CHECK(ndr_token_retrieve(&ndr
->relative_list
, p
, &rel_offset
));
1487 return ndr_pull_set_offset(ndr
, rel_offset
);
1490 const static struct {
1491 enum ndr_err_code err
;
1493 } ndr_err_code_strings
[] = {
1494 { NDR_ERR_SUCCESS
, "Success" },
1495 { NDR_ERR_ARRAY_SIZE
, "Bad Array Size" },
1496 { NDR_ERR_BAD_SWITCH
, "Bad Switch" },
1497 { NDR_ERR_OFFSET
, "Offset Error" },
1498 { NDR_ERR_RELATIVE
, "Relative Pointer Error" },
1499 { NDR_ERR_CHARCNV
, "Character Conversion Error" },
1500 { NDR_ERR_LENGTH
, "Length Error" },
1501 { NDR_ERR_SUBCONTEXT
, "Subcontext Error" },
1502 { NDR_ERR_COMPRESSION
, "Compression Error" },
1503 { NDR_ERR_STRING
, "String Error" },
1504 { NDR_ERR_VALIDATE
, "Validate Error" },
1505 { NDR_ERR_BUFSIZE
, "Buffer Size Error" },
1506 { NDR_ERR_ALLOC
, "Allocation Error" },
1507 { NDR_ERR_RANGE
, "Range Error" },
1508 { NDR_ERR_TOKEN
, "Token Error" },
1509 { NDR_ERR_IPV4ADDRESS
, "IPv4 Address Error" },
1510 { NDR_ERR_INVALID_POINTER
, "Invalid Pointer" },
1511 { NDR_ERR_UNREAD_BYTES
, "Unread Bytes" },
1512 { NDR_ERR_NDR64
, "NDR64 assertion error" },
1516 _PUBLIC_
const char *ndr_map_error2string(enum ndr_err_code ndr_err
)
1519 for (i
= 0; ndr_err_code_strings
[i
].string
!= NULL
; i
++) {
1520 if (ndr_err_code_strings
[i
].err
== ndr_err
)
1521 return ndr_err_code_strings
[i
].string
;
1523 return "Unknown error";