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 "librpc/ndr/ndr_private.h"
33 #include "../lib/util/dlinklist.h"
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
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
)
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
;
97 _PUBLIC_
enum ndr_err_code
ndr_pull_append(struct ndr_pull
*ndr
, DATA_BLOB
*blob
)
99 enum ndr_err_code ndr_err
;
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
) {
111 ndr_err
= NDR_ERR_SUCCESS
;
115 if (ndr
->data_size
== 0) {
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
);
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
);
138 return ndr_pull_error(ndr
, NDR_ERR_ALLOC
, "%s", __location__
);
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
)
151 enum ndr_err_code ndr_err
;
153 if (ndr
->relative_base_offset
!= 0) {
154 return ndr_pull_error(ndr
, NDR_ERR_RELATIVE
,
157 if (ndr
->relative_highest_offset
!= 0) {
158 return ndr_pull_error(ndr
, NDR_ERR_RELATIVE
,
161 if (ndr
->relative_list
.count
!= 0) {
162 return ndr_pull_error(ndr
, NDR_ERR_RELATIVE
,
165 if (ndr
->relative_base_list
.count
!= 0) {
166 return ndr_pull_error(ndr
, NDR_ERR_RELATIVE
,
171 * we need to keep up to 7 bytes
172 * in order to get the alignment right.
174 skip
= ndr
->offset
& 0xFFFFFFF8;
177 return NDR_ERR_SUCCESS
;
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.
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
);
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
)
219 if (ndr
->offset
> ndr
->data_size
) {
220 return ndr_pull_error(ndr
, NDR_ERR_BUFSIZE
,
221 "ndr_pull_set_offset %"PRIu32
" failed",
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
);
238 ndr
->alloc_size
= NDR_BASE_MARSHALL_SIZE
;
239 ndr
->data
= talloc_array(ndr
, uint8_t, ndr
->alloc_size
);
248 /* return a DATA_BLOB structure for the current ndr_push marshalled data */
249 _PUBLIC_ DATA_BLOB
ndr_push_blob(struct ndr_push
*ndr
)
252 blob
= data_blob_const(ndr
->data
, ndr
->offset
);
253 if (ndr
->alloc_size
> ndr
->offset
) {
254 ndr
->data
[ndr
->offset
] = 0;
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
,
273 if (ndr
->fixed_buf_size
) {
274 if (ndr
->alloc_size
>= size
) {
275 return NDR_ERR_SUCCESS
;
277 return ndr_push_error(ndr
,
279 "Overflow of fixed buffer in "
280 "push_expand to %"PRIu32
,
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
);
297 return ndr_push_error(ndr
, NDR_ERR_ALLOC
, "Failed to push_expand to %"PRIu32
,
301 return NDR_ERR_SUCCESS
;
304 _PUBLIC_
void ndr_print_debugc_helper(struct ndr_print
*ndr
, const char *format
, ...)
312 va_start(ap
, format
);
313 ret
= vasprintf(&s
, format
, ap
);
320 dbgc_class
= *(int *)ndr
->private_data
;
322 if (ndr
->no_newline
) {
323 DEBUGADDC(dbgc_class
, 1,("%s", s
));
328 for (i
=0;i
<ndr
->depth
;i
++) {
329 DEBUGADDC(dbgc_class
, 1,(" "));
332 DEBUGADDC(dbgc_class
, 1,("%s\n", s
));
336 _PUBLIC_
void ndr_print_debug_helper(struct ndr_print
*ndr
, const char *format
, ...)
343 va_start(ap
, format
);
344 ret
= vasprintf(&s
, format
, ap
);
351 if (ndr
->no_newline
) {
352 DEBUGADD(1,("%s", s
));
357 for (i
=0;i
<ndr
->depth
;i
++) {
361 DEBUGADD(1,("%s\n", s
));
365 _PUBLIC_
void ndr_print_printf_helper(struct ndr_print
*ndr
, const char *format
, ...)
370 if (!ndr
->no_newline
) {
371 for (i
=0;i
<ndr
->depth
;i
++) {
376 va_start(ap
, format
);
379 if (!ndr
->no_newline
) {
384 _PUBLIC_
void ndr_print_string_helper(struct ndr_print
*ndr
, const char *format
, ...)
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
,
400 if (!ndr
->no_newline
) {
401 ndr
->private_data
= talloc_asprintf_append_buffer((char *)ndr
->private_data
,
407 a useful helper function for printing idl structures via DEBUGC()
409 _PUBLIC_
void ndr_print_debugc(int dbgc_class
, ndr_print_fn_t fn
, const char *name
, void *ptr
)
411 struct ndr_print
*ndr
;
413 DEBUGC(dbgc_class
, 1,(" "));
415 ndr
= talloc_zero(NULL
, struct ndr_print
);
417 ndr
->private_data
= &dbgc_class
;
418 ndr
->print
= ndr_print_debugc_helper
;
421 #ifdef DEBUG_PASSWORD
422 if (CHECK_DEBUGLVL(100)) {
423 ndr
->print_secrets
= true;
432 a useful helper function for printing idl structures via DEBUG()
434 _PUBLIC_
bool ndr_print_debug(int level
,
438 const char *location
,
439 const char *function
)
441 struct ndr_print
*ndr
;
444 ndr
= talloc_zero(NULL
, struct ndr_print
);
445 if (!ndr
) return false;
446 ndr
->private_data
= talloc_strdup(ndr
, "");
447 if (ndr
->private_data
== NULL
) {
450 ndr
->print
= ndr_print_string_helper
;
453 #ifdef DEBUG_PASSWORD
454 if (CHECK_DEBUGLVL(100)) {
455 ndr
->print_secrets
= true;
460 DEBUGLF(level
, (" %s", (char *)ndr
->private_data
), location
, function
);
469 a useful helper function for printing idl unions via DEBUG()
471 _PUBLIC_
void ndr_print_union_debug(ndr_print_fn_t fn
, const char *name
, uint32_t level
, void *ptr
)
473 struct ndr_print
*ndr
;
477 ndr
= talloc_zero(NULL
, struct ndr_print
);
479 ndr
->print
= ndr_print_debug_helper
;
482 #ifdef DEBUG_PASSWORD
483 if (CHECK_DEBUGLVL(100)) {
484 ndr
->print_secrets
= true;
488 ndr_print_set_switch_value(ndr
, ptr
, level
);
494 a useful helper function for printing idl function calls via DEBUG()
496 _PUBLIC_
void ndr_print_function_debug(ndr_print_function_t fn
, const char *name
, ndr_flags_type flags
, void *ptr
)
498 struct ndr_print
*ndr
;
502 ndr
= talloc_zero(NULL
, struct ndr_print
);
504 ndr
->print
= ndr_print_debug_helper
;
507 #ifdef DEBUG_PASSWORD
508 if (CHECK_DEBUGLVL(100)) {
509 ndr
->print_secrets
= true;
513 fn(ndr
, name
, flags
, ptr
);
518 a useful helper function for printing idl structures to a string
520 _PUBLIC_
char *ndr_print_struct_string(TALLOC_CTX
*mem_ctx
, ndr_print_fn_t fn
, const char *name
, void *ptr
)
522 struct ndr_print
*ndr
;
525 ndr
= talloc_zero(mem_ctx
, struct ndr_print
);
526 if (!ndr
) return NULL
;
527 ndr
->private_data
= talloc_strdup(ndr
, "");
528 if (!ndr
->private_data
) {
531 ndr
->print
= ndr_print_string_helper
;
536 ret
= talloc_steal(mem_ctx
, (char *)ndr
->private_data
);
543 a useful helper function for printing idl unions to a string
545 _PUBLIC_
char *ndr_print_union_string(TALLOC_CTX
*mem_ctx
, ndr_print_fn_t fn
, const char *name
, uint32_t level
, void *ptr
)
547 struct ndr_print
*ndr
;
550 ndr
= talloc_zero(mem_ctx
, struct ndr_print
);
551 if (!ndr
) return NULL
;
552 ndr
->private_data
= talloc_strdup(ndr
, "");
553 if (!ndr
->private_data
) {
556 ndr
->print
= ndr_print_string_helper
;
559 ndr_print_set_switch_value(ndr
, ptr
, level
);
561 ret
= talloc_steal(mem_ctx
, (char *)ndr
->private_data
);
568 a useful helper function for printing idl function calls to a string
570 _PUBLIC_
char *ndr_print_function_string(TALLOC_CTX
*mem_ctx
,
571 ndr_print_function_t fn
, const char *name
,
572 ndr_flags_type flags
, void *ptr
)
574 struct ndr_print
*ndr
;
577 ndr
= talloc_zero(mem_ctx
, struct ndr_print
);
578 if (!ndr
) return NULL
;
579 ndr
->private_data
= talloc_strdup(ndr
, "");
580 if (!ndr
->private_data
) {
583 ndr
->print
= ndr_print_string_helper
;
586 fn(ndr
, name
, flags
, ptr
);
587 ret
= talloc_steal(mem_ctx
, (char *)ndr
->private_data
);
593 _PUBLIC_
void ndr_set_flags(libndr_flags
*pflags
, libndr_flags new_flags
)
595 /* the big/little endian flags are inter-dependent */
596 if (new_flags
& LIBNDR_FLAG_LITTLE_ENDIAN
) {
597 (*pflags
) &= ~LIBNDR_FLAG_BIGENDIAN
;
598 (*pflags
) &= ~LIBNDR_FLAG_NDR64
;
600 if (new_flags
& LIBNDR_FLAG_BIGENDIAN
) {
601 (*pflags
) &= ~LIBNDR_FLAG_LITTLE_ENDIAN
;
602 (*pflags
) &= ~LIBNDR_FLAG_NDR64
;
604 if (new_flags
& LIBNDR_ALIGN_FLAGS
) {
605 /* Ensure we only have the passed-in
606 align flag set in the new_flags,
607 remove any old align flag. */
608 (*pflags
) &= ~LIBNDR_ALIGN_FLAGS
;
610 if (new_flags
& LIBNDR_FLAG_NO_RELATIVE_REVERSE
) {
611 (*pflags
) &= ~LIBNDR_FLAG_RELATIVE_REVERSE
;
613 (*pflags
) |= new_flags
;
617 return and possibly log an NDR error
619 _PUBLIC_
enum ndr_err_code
_ndr_pull_error(struct ndr_pull
*ndr
,
620 enum ndr_err_code ndr_err
,
621 const char *function
,
622 const char *location
,
623 const char *format
, ...)
629 if (ndr
->flags
& LIBNDR_FLAG_INCOMPLETE_BUFFER
) {
631 case NDR_ERR_BUFSIZE
:
632 return NDR_ERR_INCOMPLETE_BUFFER
;
638 va_start(ap
, format
);
639 ret
= vasprintf(&s
, format
, ap
);
643 return NDR_ERR_ALLOC
;
646 D_WARNING("%s: ndr_pull_error(%s): %s at %s\n",
648 ndr_map_error2string(ndr_err
),
658 return and possibly log an NDR error
660 _PUBLIC_
enum ndr_err_code
_ndr_push_error(struct ndr_push
*ndr
,
661 enum ndr_err_code ndr_err
,
662 const char *function
,
663 const char *location
,
664 const char *format
, ...)
670 va_start(ap
, format
);
671 ret
= vasprintf(&s
, format
, ap
);
675 return NDR_ERR_ALLOC
;
678 D_WARNING("%s: ndr_push_error(%s): %s at %s\n",
680 ndr_map_error2string(ndr_err
),
690 handle subcontext buffers, which in midl land are user-marshalled, but
691 we use magic in pidl to make them easier to cope with
693 _PUBLIC_
enum ndr_err_code
ndr_pull_subcontext_start(struct ndr_pull
*ndr
,
694 struct ndr_pull
**_subndr
,
698 struct ndr_pull
*subndr
;
699 uint32_t r_content_size
;
700 bool force_le
= false;
701 bool force_be
= false;
703 switch (header_size
) {
705 uint32_t content_size
= ndr
->data_size
- ndr
->offset
;
707 content_size
= size_is
;
709 r_content_size
= content_size
;
714 uint16_t content_size
;
715 NDR_CHECK(ndr_pull_uint16(ndr
, NDR_SCALARS
, &content_size
));
716 if (size_is
>= 0 && size_is
!= content_size
) {
717 return ndr_pull_error(ndr
, NDR_ERR_SUBCONTEXT
, "Bad subcontext (PULL) size_is(%zd) (0x%04zx) mismatch content_size %"PRIu16
" (0x%04"PRIx16
")",
722 r_content_size
= content_size
;
727 uint32_t content_size
;
728 NDR_CHECK(ndr_pull_uint3264(ndr
, NDR_SCALARS
, &content_size
));
729 if (size_is
>= 0 && size_is
!= content_size
) {
730 return ndr_pull_error(ndr
, NDR_ERR_SUBCONTEXT
, "Bad subcontext (PULL) size_is(%zd) (0x%08zx) mismatch content_size %"PRIu32
" (0x%08"PRIx32
")",
735 r_content_size
= content_size
;
740 * Common Type Header for the Serialization Stream
741 * See [MS-RPCE] 2.2.6 Type Serialization Version 1
747 uint32_t content_size
;
751 NDR_CHECK(ndr_pull_uint8(ndr
, NDR_SCALARS
, &version
));
754 return ndr_pull_error(ndr
, NDR_ERR_SUBCONTEXT
,
755 "Bad subcontext (PULL) Common Type Header version %"PRIu8
" != 1",
763 NDR_CHECK(ndr_pull_uint8(ndr
, NDR_SCALARS
, &drep
));
766 } else if (drep
== 0x00) {
769 return ndr_pull_error(ndr
, NDR_ERR_SUBCONTEXT
,
770 "Bad subcontext (PULL) Common Type Header invalid drep 0x%02"PRIX8
,
774 /* length of the "Private Header for Constructed Type" */
775 NDR_CHECK(ndr_pull_uint16(ndr
, NDR_SCALARS
, &hdrlen
));
777 return ndr_pull_error(ndr
, NDR_ERR_SUBCONTEXT
,
778 "Bad subcontext (PULL) Common Type Header length %"PRIu16
" != 8",
782 /* filler should be ignored */
783 NDR_CHECK(ndr_pull_uint32(ndr
, NDR_SCALARS
, &filler
));
786 * Private Header for Constructed Type
788 /* length - will be updated later */
789 NDR_CHECK(ndr_pull_uint32(ndr
, NDR_SCALARS
, &content_size
));
790 if (size_is
>= 0 && size_is
!= content_size
) {
791 return ndr_pull_error(ndr
, NDR_ERR_SUBCONTEXT
, "Bad subcontext (PULL) size_is(%zd) mismatch content_size %"PRIu32
,
792 size_is
, content_size
);
794 /* the content size must be a multiple of 8 */
795 if ((content_size
% 8) != 0) {
796 return ndr_pull_error(ndr
, NDR_ERR_SUBCONTEXT
,
797 "Bad subcontext (PULL) size_is(%zd) not padded to 8 content_size %"PRIu32
,
798 size_is
, content_size
);
800 r_content_size
= content_size
;
803 NDR_CHECK(ndr_pull_uint32(ndr
, NDR_SCALARS
, &reserved
));
808 * a shallow copy like subcontext
809 * useful for DCERPC pipe chunks.
811 subndr
= talloc_zero(ndr
, struct ndr_pull
);
812 NDR_ERR_HAVE_NO_MEMORY(subndr
);
814 subndr
->flags
= ndr
->flags
;
815 subndr
->current_mem_ctx
= ndr
->current_mem_ctx
;
816 subndr
->data
= ndr
->data
;
817 subndr
->offset
= ndr
->offset
;
818 subndr
->data_size
= ndr
->data_size
;
821 return NDR_ERR_SUCCESS
;
824 return ndr_pull_error(ndr
, NDR_ERR_SUBCONTEXT
, "Bad subcontext (PULL) header_size %zu",
828 NDR_PULL_NEED_BYTES(ndr
, r_content_size
);
830 subndr
= talloc_zero(ndr
, struct ndr_pull
);
831 NDR_ERR_HAVE_NO_MEMORY(subndr
);
832 subndr
->flags
= ndr
->flags
& ~LIBNDR_FLAG_NDR64
;
833 subndr
->current_mem_ctx
= ndr
->current_mem_ctx
;
835 subndr
->data
= ndr
->data
+ ndr
->offset
;
837 subndr
->data_size
= r_content_size
;
840 ndr_set_flags(&ndr
->flags
, LIBNDR_FLAG_LITTLE_ENDIAN
);
841 } else if (force_be
) {
842 ndr_set_flags(&ndr
->flags
, LIBNDR_FLAG_BIGENDIAN
);
846 return NDR_ERR_SUCCESS
;
849 _PUBLIC_
enum ndr_err_code
ndr_pull_subcontext_end(struct ndr_pull
*ndr
,
850 struct ndr_pull
*subndr
,
855 uint32_t highest_ofs
;
857 if (header_size
== 0xFFFFFFFF) {
858 advance
= subndr
->offset
- ndr
->offset
;
859 } else if (size_is
>= 0) {
861 } else if (header_size
> 0) {
862 advance
= subndr
->data_size
;
864 advance
= subndr
->offset
;
867 if (subndr
->offset
> ndr
->relative_highest_offset
) {
868 highest_ofs
= subndr
->offset
;
870 highest_ofs
= subndr
->relative_highest_offset
;
872 if (!(subndr
->flags
& LIBNDR_FLAG_SUBCONTEXT_NO_UNREAD_BYTES
)) {
874 * avoid an error unless SUBCONTEXT_NO_UNREAD_BYTES is specified
876 highest_ofs
= advance
;
878 if (highest_ofs
< advance
) {
879 return ndr_pull_error(subndr
, NDR_ERR_UNREAD_BYTES
,
880 "not all bytes consumed ofs[%"PRIu32
"] advance[%"PRIu32
"]",
881 highest_ofs
, advance
);
884 NDR_CHECK(ndr_pull_advance(ndr
, advance
));
885 return NDR_ERR_SUCCESS
;
888 _PUBLIC_
enum ndr_err_code
ndr_push_subcontext_start(struct ndr_push
*ndr
,
889 struct ndr_push
**_subndr
,
893 struct ndr_push
*subndr
;
895 subndr
= ndr_push_init_ctx(ndr
);
896 NDR_ERR_HAVE_NO_MEMORY(subndr
);
897 subndr
->flags
= ndr
->flags
& ~LIBNDR_FLAG_NDR64
;
900 enum ndr_err_code status
;
902 status
= ndr_push_zero(subndr
, size_is
);
903 if (!NDR_ERR_CODE_IS_SUCCESS(status
)) {
908 subndr
->relative_end_offset
= size_is
;
912 return NDR_ERR_SUCCESS
;
916 push a subcontext header
918 _PUBLIC_
enum ndr_err_code
ndr_push_subcontext_end(struct ndr_push
*ndr
,
919 struct ndr_push
*subndr
,
926 padding_len
= size_is
- subndr
->offset
;
927 if (padding_len
< 0) {
928 return ndr_push_error(ndr
, NDR_ERR_SUBCONTEXT
, "Bad subcontext (PUSH) content_size %"PRIu32
" is larger than size_is(%zd)",
929 subndr
->offset
, size_is
);
931 subndr
->offset
= size_is
;
934 switch (header_size
) {
939 NDR_CHECK(ndr_push_uint16(ndr
, NDR_SCALARS
, subndr
->offset
));
943 NDR_CHECK(ndr_push_uint3264(ndr
, NDR_SCALARS
, subndr
->offset
));
948 * Common Type Header for the Serialization Stream
949 * See [MS-RPCE] 2.2.6 Type Serialization Version 1
951 padding_len
= NDR_ROUND(subndr
->offset
, 8) - subndr
->offset
;
952 if (padding_len
> 0) {
953 NDR_CHECK(ndr_push_zero(subndr
, padding_len
));
957 NDR_CHECK(ndr_push_uint8(ndr
, NDR_SCALARS
, 1));
963 NDR_CHECK(ndr_push_uint8(ndr
, NDR_SCALARS
, NDR_BE(ndr
)?0x00:0x10));
965 /* length of the "Private Header for Constructed Type" */
966 NDR_CHECK(ndr_push_uint16(ndr
, NDR_SCALARS
, 8));
969 NDR_CHECK(ndr_push_uint32(ndr
, NDR_SCALARS
, 0xCCCCCCCC));
972 * Private Header for Constructed Type
974 /* length - will be updated later */
975 NDR_CHECK(ndr_push_uint32(ndr
, NDR_SCALARS
, subndr
->offset
));
978 NDR_CHECK(ndr_push_uint32(ndr
, NDR_SCALARS
, 0));
982 return ndr_push_error(ndr
, NDR_ERR_SUBCONTEXT
, "Bad subcontext header size %zu",
986 NDR_CHECK(ndr_push_bytes(ndr
, subndr
->data
, subndr
->offset
));
987 return NDR_ERR_SUCCESS
;
997 store a token in the ndr context, for later retrieval
999 _PUBLIC_
enum ndr_err_code
ndr_token_store(TALLOC_CTX
*mem_ctx
,
1000 struct ndr_token_list
*list
,
1004 if (list
->tokens
== NULL
) {
1005 list
->tokens
= talloc_array(mem_ctx
, struct ndr_token
, 10);
1006 if (list
->tokens
== NULL
) {
1007 NDR_ERR_HAVE_NO_MEMORY(list
->tokens
);
1010 struct ndr_token
*new_tokens
= NULL
;
1011 uint32_t alloc_count
= talloc_array_length(list
->tokens
);
1014 * Check every time we have not allocated too many
1015 * tokens. This ensures developer sanity when
1016 * debugging the boundary condition
1018 if (list
->count
>= NDR_TOKEN_MAX_LIST_SIZE
) {
1019 return NDR_ERR_RANGE
;
1021 if (list
->count
== alloc_count
) {
1024 * Double the list, until we start in chunks
1027 uint32_t increment
= MIN(list
->count
, 1000);
1028 new_alloc
= alloc_count
+ increment
;
1029 if (new_alloc
< alloc_count
) {
1030 return NDR_ERR_RANGE
;
1032 new_tokens
= talloc_realloc(mem_ctx
, list
->tokens
,
1033 struct ndr_token
, new_alloc
);
1034 NDR_ERR_HAVE_NO_MEMORY(new_tokens
);
1035 list
->tokens
= new_tokens
;
1038 list
->tokens
[list
->count
].key
= key
;
1039 list
->tokens
[list
->count
].value
= value
;
1041 return NDR_ERR_SUCCESS
;
1045 retrieve a token from a ndr context, using cmp_fn to match the tokens
1047 static enum ndr_err_code
ndr_token_find(struct ndr_token_list
*list
,
1050 comparison_fn_t _cmp_fn
,
1053 struct ndr_token
*tokens
= list
->tokens
;
1055 for (i
= list
->count
- 1; i
< list
->count
; i
--) {
1056 if (_cmp_fn(tokens
[i
].key
, key
) == 0) {
1058 *v
= tokens
[i
].value
;
1059 return NDR_ERR_SUCCESS
;
1062 return NDR_ERR_TOKEN
;
1065 _PUBLIC_
enum ndr_err_code
ndr_token_peek_cmp_fn(struct ndr_token_list
*list
,
1068 comparison_fn_t _cmp_fn
)
1071 return ndr_token_find(list
, key
, v
, _cmp_fn
, &i
);
1074 static int token_cmp_ptr(const void *a
, const void *b
)
1076 return (a
== b
) ? 0 : 1;
1080 retrieve a token from a ndr context
1082 _PUBLIC_
enum ndr_err_code
ndr_token_retrieve(struct ndr_token_list
*list
,
1083 const void *key
, uint32_t *v
)
1085 enum ndr_err_code err
;
1089 err
= ndr_token_find(list
, key
, v
, token_cmp_ptr
, &i
);
1090 if (!NDR_ERR_CODE_IS_SUCCESS(err
)) {
1094 last
= list
->count
- 1;
1096 list
->tokens
[i
] = list
->tokens
[last
];
1100 return NDR_ERR_SUCCESS
;
1104 peek at but don't removed a token from a ndr context
1106 _PUBLIC_
enum ndr_err_code
ndr_token_peek(struct ndr_token_list
*list
,
1107 const void *key
, uint32_t *v
)
1110 return ndr_token_find(list
, key
, v
, token_cmp_ptr
, &i
);
1114 pull an array size field and add it to the array_size_list token list
1116 _PUBLIC_
enum ndr_err_code
ndr_pull_array_size(struct ndr_pull
*ndr
, const void *p
)
1118 enum ndr_err_code ret
;
1120 NDR_CHECK(ndr_pull_uint3264(ndr
, NDR_SCALARS
, &size
));
1121 ret
= ndr_token_store(ndr
, &ndr
->array_size_list
, p
, size
);
1122 if (ret
== NDR_ERR_RANGE
) {
1123 return ndr_pull_error(ndr
, ret
,
1124 "More than %d NDR tokens stored for array_size",
1125 NDR_TOKEN_MAX_LIST_SIZE
);
1131 get the stored array size field
1133 _PUBLIC_
enum ndr_err_code
ndr_get_array_size(struct ndr_pull
*ndr
, const void *p
, uint32_t *size
)
1135 return ndr_token_peek(&ndr
->array_size_list
, p
, size
);
1139 get and remove from the stored list the stored array size field
1141 _PUBLIC_
enum ndr_err_code
ndr_steal_array_size(struct ndr_pull
*ndr
, const void *p
, uint32_t *size
)
1143 return ndr_token_retrieve(&ndr
->array_size_list
, p
, size
);
1147 * check the stored array size field and remove from the stored list
1148 * (the array_size NDR token list). We try to remove when possible to
1149 * avoid the list growing towards the bounds check
1151 _PUBLIC_
enum ndr_err_code
ndr_check_steal_array_size(struct ndr_pull
*ndr
, const void *p
, uint32_t size
)
1154 NDR_CHECK(ndr_steal_array_size(ndr
, p
, &stored
));
1155 if (stored
!= size
) {
1156 return ndr_pull_error(ndr
, NDR_ERR_ARRAY_SIZE
,
1157 "Bad array size - got %u expected %u\n",
1160 return NDR_ERR_SUCCESS
;
1164 * check the stored array size field (leaving it on the array_size
1167 _PUBLIC_
enum ndr_err_code
ndr_check_array_size(struct ndr_pull
*ndr
, const void *p
, uint32_t size
)
1170 NDR_CHECK(ndr_get_array_size(ndr
, p
, &stored
));
1171 if (stored
!= size
) {
1172 return ndr_pull_error(ndr
, NDR_ERR_ARRAY_SIZE
,
1173 "Bad array size - got %"PRIu32
" expected %"PRIu32
"\n",
1176 return NDR_ERR_SUCCESS
;
1180 pull an array length field and add it to the array_length_list token list
1182 _PUBLIC_
enum ndr_err_code
ndr_pull_array_length(struct ndr_pull
*ndr
, const void *p
)
1184 enum ndr_err_code ret
;
1185 uint32_t length
, offset
;
1186 NDR_CHECK(ndr_pull_uint3264(ndr
, NDR_SCALARS
, &offset
));
1188 return ndr_pull_error(ndr
, NDR_ERR_ARRAY_SIZE
,
1189 "non-zero array offset %"PRIu32
"\n", offset
);
1191 NDR_CHECK(ndr_pull_uint3264(ndr
, NDR_SCALARS
, &length
));
1192 ret
= ndr_token_store(ndr
, &ndr
->array_length_list
, p
, length
);
1193 if (ret
== NDR_ERR_RANGE
) {
1194 return ndr_pull_error(ndr
, ret
,
1195 "More than %d NDR tokens stored for array_length_list",
1196 NDR_TOKEN_MAX_LIST_SIZE
);
1202 get the stored array length field
1204 _PUBLIC_
enum ndr_err_code
ndr_get_array_length(struct ndr_pull
*ndr
, const void *p
, uint32_t *length
)
1206 return ndr_token_peek(&ndr
->array_length_list
, p
, length
);
1210 * check the stored array length field and remove from the stored list
1211 * (the array_size NDR token list). We try to remove when possible to
1212 * avoid the list growing towards the bounds check
1214 _PUBLIC_
enum ndr_err_code
ndr_steal_array_length(struct ndr_pull
*ndr
, const void *p
, uint32_t *length
)
1216 return ndr_token_retrieve(&ndr
->array_length_list
, p
, length
);
1219 check the stored array length field, removing it from the list
1221 _PUBLIC_
enum ndr_err_code
ndr_check_steal_array_length(struct ndr_pull
*ndr
, const void *p
, uint32_t length
)
1224 NDR_CHECK(ndr_steal_array_length(ndr
, p
, &stored
));
1225 if (stored
!= length
) {
1226 return ndr_pull_error(ndr
, NDR_ERR_ARRAY_SIZE
,
1227 "Bad array length: got %"PRIu32
" expected %"PRIu32
"\n",
1230 return NDR_ERR_SUCCESS
;
1233 _PUBLIC_
enum ndr_err_code
ndr_push_pipe_chunk_trailer(struct ndr_push
*ndr
, ndr_flags_type ndr_flags
, uint32_t count
)
1235 if (ndr
->flags
& LIBNDR_FLAG_NDR64
) {
1236 int64_t tmp
= 0 - (int64_t)count
;
1237 uint64_t ncount
= tmp
;
1239 NDR_CHECK(ndr_push_hyper(ndr
, ndr_flags
, ncount
));
1242 return NDR_ERR_SUCCESS
;
1245 _PUBLIC_
enum ndr_err_code
ndr_check_pipe_chunk_trailer(struct ndr_pull
*ndr
, ndr_flags_type ndr_flags
, uint32_t count
)
1247 if (ndr
->flags
& LIBNDR_FLAG_NDR64
) {
1248 int64_t tmp
= 0 - (int64_t)count
;
1249 uint64_t ncount1
= tmp
;
1252 NDR_CHECK(ndr_pull_hyper(ndr
, ndr_flags
, &ncount2
));
1253 if (ncount1
== ncount2
) {
1254 return NDR_ERR_SUCCESS
;
1257 return ndr_pull_error(ndr
, NDR_ERR_ARRAY_SIZE
,
1258 "Bad pipe trailer[%"PRIu64
" should be %"PRIu64
"] size was %"PRIu32
"\"",
1264 return NDR_ERR_SUCCESS
;
1268 store a switch value
1270 _PUBLIC_
enum ndr_err_code
ndr_push_set_switch_value(struct ndr_push
*ndr
, const void *p
, uint32_t val
)
1272 enum ndr_err_code ret
=
1273 ndr_token_store(ndr
, &ndr
->switch_list
, p
, val
);
1274 if (ret
== NDR_ERR_RANGE
) {
1275 return ndr_push_error(ndr
, ret
,
1276 "More than %d NDR tokens stored for switch_list",
1277 NDR_TOKEN_MAX_LIST_SIZE
);
1282 _PUBLIC_
enum ndr_err_code
ndr_pull_set_switch_value(struct ndr_pull
*ndr
, const void *p
, uint32_t val
)
1285 enum ndr_err_code ret
=
1286 ndr_token_store(ndr
, &ndr
->switch_list
, p
, val
);
1287 if (ret
== NDR_ERR_RANGE
) {
1288 return ndr_pull_error(ndr
, ret
,
1289 "More than %d NDR tokens stored for switch_list",
1290 NDR_TOKEN_MAX_LIST_SIZE
);
1295 _PUBLIC_
enum ndr_err_code
ndr_print_set_switch_value(struct ndr_print
*ndr
, const void *p
, uint32_t val
)
1297 return ndr_token_store(ndr
, &ndr
->switch_list
, p
, val
);
1300 /* retrieve a switch value (for push) and remove it from the list */
1301 _PUBLIC_
enum ndr_err_code
ndr_push_steal_switch_value(struct ndr_push
*ndr
,
1305 return ndr_token_retrieve(&ndr
->switch_list
, p
, v
);
1308 /* retrieve a switch value and remove it from the list */
1309 _PUBLIC_
uint32_t ndr_print_steal_switch_value(struct ndr_print
*ndr
, const void *p
)
1311 enum ndr_err_code status
;
1314 status
= ndr_token_retrieve(&ndr
->switch_list
, p
, &v
);
1315 if (!NDR_ERR_CODE_IS_SUCCESS(status
)) {
1322 /* retrieve a switch value and remove it from the list */
1323 _PUBLIC_
enum ndr_err_code
ndr_pull_steal_switch_value(struct ndr_pull
*ndr
,
1327 return ndr_token_retrieve(&ndr
->switch_list
, p
, v
);
1331 pull a struct from a blob using NDR
1333 _PUBLIC_
enum ndr_err_code
ndr_pull_struct_blob(const DATA_BLOB
*blob
, TALLOC_CTX
*mem_ctx
, void *p
,
1334 ndr_pull_flags_fn_t fn
)
1336 struct ndr_pull
*ndr
;
1337 ndr
= ndr_pull_init_blob(blob
, mem_ctx
);
1338 NDR_ERR_HAVE_NO_MEMORY(ndr
);
1339 NDR_CHECK_FREE(fn(ndr
, NDR_SCALARS
|NDR_BUFFERS
, p
));
1341 return NDR_ERR_SUCCESS
;
1345 pull a struct from a blob using NDR - failing if all bytes are not consumed
1347 _PUBLIC_
enum ndr_err_code
ndr_pull_struct_blob_all(const DATA_BLOB
*blob
, TALLOC_CTX
*mem_ctx
,
1348 void *p
, ndr_pull_flags_fn_t fn
)
1350 struct ndr_pull
*ndr
;
1351 uint32_t highest_ofs
;
1352 ndr
= ndr_pull_init_blob(blob
, mem_ctx
);
1353 NDR_ERR_HAVE_NO_MEMORY(ndr
);
1354 NDR_CHECK_FREE(fn(ndr
, NDR_SCALARS
|NDR_BUFFERS
, p
));
1355 if (ndr
->offset
> ndr
->relative_highest_offset
) {
1356 highest_ofs
= ndr
->offset
;
1358 highest_ofs
= ndr
->relative_highest_offset
;
1360 if (highest_ofs
< ndr
->data_size
) {
1361 enum ndr_err_code ret
;
1362 ret
= ndr_pull_error(ndr
, NDR_ERR_UNREAD_BYTES
,
1363 "not all bytes consumed ofs[%"PRIu32
"] size[%"PRIu32
"]",
1364 highest_ofs
, ndr
->data_size
);
1369 return NDR_ERR_SUCCESS
;
1373 * pull a struct from a blob using NDR
1375 * This only works for structures with NO allocated memory, like
1376 * objectSID and GUID. This helps because we parse these a lot.
1378 _PUBLIC_
enum ndr_err_code
ndr_pull_struct_blob_noalloc(const uint8_t *buf
,
1381 ndr_pull_flags_fn_t fn
,
1385 * We init this structure on the stack here, to avoid a
1386 * talloc() as otherwise this call to the fn() is assured not
1387 * to be doing any allocation, eg SIDs and GUIDs.
1389 * This allows us to keep the safety of the PIDL-generated
1390 * code without the talloc() overhead.
1392 struct ndr_pull ndr
= {
1393 .data
= discard_const_p(uint8_t, buf
),
1394 .data_size
= buflen
,
1395 .current_mem_ctx
= (void *)-1,
1398 NDR_CHECK(fn(&ndr
, NDR_SCALARS
|NDR_BUFFERS
, p
));
1399 *consumed
= MAX(ndr
.offset
, ndr
.relative_highest_offset
);
1401 return NDR_ERR_SUCCESS
;
1405 pull a struct from a blob using NDR - failing if all bytes are not consumed
1407 This only works for structures with NO allocated memory, like
1408 objectSID and GUID. This helps because we parse these a lot.
1410 _PUBLIC_
enum ndr_err_code
1411 ndr_pull_struct_blob_all_noalloc(const DATA_BLOB
*blob
,
1413 ndr_pull_flags_fn_t fn
)
1416 enum ndr_err_code ndr_err
;
1418 ndr_err
= ndr_pull_struct_blob_noalloc(blob
->data
,
1423 if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err
)) {
1427 if (consumed
< blob
->length
) {
1428 D_WARNING("not all bytes consumed ofs[%zu] size[%zu]",
1431 return NDR_ERR_UNREAD_BYTES
;
1434 return NDR_ERR_SUCCESS
;
1438 pull a union from a blob using NDR, given the union discriminator
1440 _PUBLIC_
enum ndr_err_code
ndr_pull_union_blob(const DATA_BLOB
*blob
, TALLOC_CTX
*mem_ctx
,
1442 uint32_t level
, ndr_pull_flags_fn_t fn
)
1444 struct ndr_pull
*ndr
;
1445 ndr
= ndr_pull_init_blob(blob
, mem_ctx
);
1446 NDR_ERR_HAVE_NO_MEMORY(ndr
);
1447 NDR_CHECK_FREE(ndr_pull_set_switch_value(ndr
, p
, level
));
1448 NDR_CHECK_FREE(fn(ndr
, NDR_SCALARS
|NDR_BUFFERS
, p
));
1450 return NDR_ERR_SUCCESS
;
1454 pull a union from a blob using NDR, given the union discriminator,
1455 failing if all bytes are not consumed
1457 _PUBLIC_
enum ndr_err_code
ndr_pull_union_blob_all(const DATA_BLOB
*blob
, TALLOC_CTX
*mem_ctx
,
1459 uint32_t level
, 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(ndr_pull_set_switch_value(ndr
, p
, level
));
1466 NDR_CHECK_FREE(fn(ndr
, NDR_SCALARS
|NDR_BUFFERS
, p
));
1467 if (ndr
->offset
> ndr
->relative_highest_offset
) {
1468 highest_ofs
= ndr
->offset
;
1470 highest_ofs
= ndr
->relative_highest_offset
;
1472 if (highest_ofs
< ndr
->data_size
) {
1473 enum ndr_err_code ret
;
1474 ret
= ndr_pull_error(ndr
, NDR_ERR_UNREAD_BYTES
,
1475 "not all bytes consumed ofs[%"PRIu32
"] size[%"PRIu32
"]",
1476 highest_ofs
, ndr
->data_size
);
1481 return NDR_ERR_SUCCESS
;
1485 push a struct to a blob using NDR
1487 _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
)
1489 struct ndr_push
*ndr
;
1490 ndr
= ndr_push_init_ctx(mem_ctx
);
1491 NDR_ERR_HAVE_NO_MEMORY(ndr
);
1493 NDR_CHECK_FREE(fn(ndr
, NDR_SCALARS
|NDR_BUFFERS
, p
));
1495 *blob
= ndr_push_blob(ndr
);
1496 talloc_steal(mem_ctx
, blob
->data
);
1499 return NDR_ERR_SUCCESS
;
1503 push a struct into a provided blob using NDR.
1505 We error because we want to have the performance issue (extra
1506 talloc() calls) show up as an error, not just slower code. This is
1507 used for things like GUIDs, which we expect to be a fixed size, and
1508 SIDs that we can pre-calculate the size for.
1510 _PUBLIC_
enum ndr_err_code
ndr_push_struct_into_fixed_blob(
1511 DATA_BLOB
*blob
, const void *p
, ndr_push_flags_fn_t fn
)
1513 struct ndr_push ndr
= {
1515 .alloc_size
= blob
->length
,
1516 .fixed_buf_size
= true
1519 NDR_CHECK(fn(&ndr
, NDR_SCALARS
|NDR_BUFFERS
, p
));
1521 if (ndr
.offset
!= blob
->length
) {
1522 return ndr_push_error(&ndr
, NDR_ERR_BUFSIZE
,
1523 "buffer was either too large or small "
1524 "ofs[%"PRIu32
"] size[%zu]",
1525 ndr
.offset
, blob
->length
);
1528 return NDR_ERR_SUCCESS
;
1532 push a union to a blob using NDR
1534 _PUBLIC_
enum ndr_err_code
ndr_push_union_blob(DATA_BLOB
*blob
, TALLOC_CTX
*mem_ctx
, void *p
,
1535 uint32_t level
, ndr_push_flags_fn_t fn
)
1537 struct ndr_push
*ndr
;
1538 ndr
= ndr_push_init_ctx(mem_ctx
);
1539 NDR_ERR_HAVE_NO_MEMORY(ndr
);
1541 NDR_CHECK_FREE(ndr_push_set_switch_value(ndr
, p
, level
));
1542 NDR_CHECK_FREE(fn(ndr
, NDR_SCALARS
|NDR_BUFFERS
, p
));
1544 *blob
= ndr_push_blob(ndr
);
1545 talloc_steal(mem_ctx
, blob
->data
);
1548 return NDR_ERR_SUCCESS
;
1552 generic ndr_size_*() handler for structures
1554 _PUBLIC_
size_t ndr_size_struct(const void *p
, libndr_flags flags
, ndr_push_flags_fn_t push
)
1556 struct ndr_push
*ndr
;
1557 enum ndr_err_code status
;
1560 /* avoid recursion */
1561 if (flags
& LIBNDR_FLAG_NO_NDR_SIZE
) return 0;
1563 /* Avoid following a NULL pointer */
1568 ndr
= ndr_push_init_ctx(NULL
);
1570 ndr
->flags
|= flags
| LIBNDR_FLAG_NO_NDR_SIZE
;
1571 status
= push(ndr
, NDR_SCALARS
|NDR_BUFFERS
, discard_const(p
));
1572 if (!NDR_ERR_CODE_IS_SUCCESS(status
)) {
1582 generic ndr_size_*() handler for unions
1584 _PUBLIC_
size_t ndr_size_union(const void *p
, libndr_flags flags
, uint32_t level
, ndr_push_flags_fn_t push
)
1586 struct ndr_push
*ndr
;
1587 enum ndr_err_code status
;
1590 /* avoid recursion */
1591 if (flags
& LIBNDR_FLAG_NO_NDR_SIZE
) return 0;
1593 /* Avoid following a NULL pointer */
1598 ndr
= ndr_push_init_ctx(NULL
);
1600 ndr
->flags
|= flags
| LIBNDR_FLAG_NO_NDR_SIZE
;
1602 status
= ndr_push_set_switch_value(ndr
, p
, level
);
1603 if (!NDR_ERR_CODE_IS_SUCCESS(status
)) {
1607 status
= push(ndr
, NDR_SCALARS
|NDR_BUFFERS
, p
);
1608 if (!NDR_ERR_CODE_IS_SUCCESS(status
)) {
1618 get the current base for relative pointers for the push
1620 _PUBLIC_
uint32_t ndr_push_get_relative_base_offset(struct ndr_push
*ndr
)
1622 return ndr
->relative_base_offset
;
1626 restore the old base for relative pointers for the push
1628 _PUBLIC_
void ndr_push_restore_relative_base_offset(struct ndr_push
*ndr
, uint32_t offset
)
1630 ndr
->relative_base_offset
= offset
;
1634 setup the current base for relative pointers for the push
1635 called in the NDR_SCALAR stage
1637 _PUBLIC_
enum ndr_err_code
ndr_push_setup_relative_base_offset1(struct ndr_push
*ndr
, const void *p
, uint32_t offset
)
1639 enum ndr_err_code ret
;
1640 ndr
->relative_base_offset
= offset
;
1641 ret
= ndr_token_store(ndr
, &ndr
->relative_base_list
, p
, offset
);
1642 if (ret
== NDR_ERR_RANGE
) {
1643 return ndr_push_error(ndr
, ret
,
1644 "More than %d NDR tokens stored for relative_base_list",
1645 NDR_TOKEN_MAX_LIST_SIZE
);
1651 setup the current base for relative pointers for the push
1652 called in the NDR_BUFFERS stage
1654 _PUBLIC_
enum ndr_err_code
ndr_push_setup_relative_base_offset2(struct ndr_push
*ndr
, const void *p
)
1656 return ndr_token_retrieve(&ndr
->relative_base_list
, p
, &ndr
->relative_base_offset
);
1660 push a relative object - stage1
1661 this is called during SCALARS processing
1663 _PUBLIC_
enum ndr_err_code
ndr_push_relative_ptr1(struct ndr_push
*ndr
, const void *p
)
1665 enum ndr_err_code ret
;
1667 NDR_CHECK(ndr_push_uint32(ndr
, NDR_SCALARS
, 0));
1668 return NDR_ERR_SUCCESS
;
1670 NDR_CHECK(ndr_push_align(ndr
, 4));
1671 ret
= ndr_token_store(ndr
, &ndr
->relative_list
, p
, ndr
->offset
);
1672 if (ret
== NDR_ERR_RANGE
) {
1673 return ndr_push_error(ndr
, ret
,
1674 "More than %d NDR tokens stored for relative_list",
1675 NDR_TOKEN_MAX_LIST_SIZE
);
1678 return ndr_push_uint32(ndr
, NDR_SCALARS
, UINT32_MAX
);
1682 push a short relative object - stage1
1683 this is called during SCALARS processing
1685 _PUBLIC_
enum ndr_err_code
ndr_push_short_relative_ptr1(struct ndr_push
*ndr
, const void *p
)
1687 enum ndr_err_code ret
;
1689 NDR_CHECK(ndr_push_uint16(ndr
, NDR_SCALARS
, 0));
1690 return NDR_ERR_SUCCESS
;
1692 NDR_CHECK(ndr_push_align(ndr
, 2));
1693 ret
= ndr_token_store(ndr
, &ndr
->relative_list
, p
, ndr
->offset
);
1694 if (ret
== NDR_ERR_RANGE
) {
1695 return ndr_push_error(ndr
, ret
,
1696 "More than %d NDR tokens stored for relative_list",
1697 NDR_TOKEN_MAX_LIST_SIZE
);
1700 return ndr_push_uint16(ndr
, NDR_SCALARS
, 0xFFFF);
1703 push a relative object - stage2
1704 this is called during buffers processing
1706 static enum ndr_err_code
ndr_push_relative_ptr2(struct ndr_push
*ndr
, const void *p
)
1708 uint32_t save_offset
;
1709 uint32_t ptr_offset
= 0xFFFFFFFF;
1711 return NDR_ERR_SUCCESS
;
1713 save_offset
= ndr
->offset
;
1714 NDR_CHECK(ndr_token_retrieve(&ndr
->relative_list
, p
, &ptr_offset
));
1715 if (ptr_offset
> ndr
->offset
) {
1716 return ndr_push_error(ndr
, NDR_ERR_BUFSIZE
,
1717 "ndr_push_relative_ptr2 ptr_offset(%"PRIu32
") > ndr->offset(%"PRIu32
")",
1718 ptr_offset
, ndr
->offset
);
1720 ndr
->offset
= ptr_offset
;
1721 if (save_offset
< ndr
->relative_base_offset
) {
1722 return ndr_push_error(ndr
, NDR_ERR_BUFSIZE
,
1723 "ndr_push_relative_ptr2 save_offset(%"PRIu32
") < ndr->relative_base_offset(%"PRIu32
")",
1724 save_offset
, ndr
->relative_base_offset
);
1726 NDR_CHECK(ndr_push_uint32(ndr
, NDR_SCALARS
, save_offset
- ndr
->relative_base_offset
));
1727 ndr
->offset
= save_offset
;
1728 return NDR_ERR_SUCCESS
;
1731 push a short relative object - stage2
1732 this is called during buffers processing
1734 _PUBLIC_
enum ndr_err_code
ndr_push_short_relative_ptr2(struct ndr_push
*ndr
, const void *p
)
1736 uint32_t save_offset
;
1737 uint32_t ptr_offset
= 0xFFFF;
1738 uint32_t relative_offset
;
1743 return NDR_ERR_SUCCESS
;
1746 if (ndr
->offset
< ndr
->relative_base_offset
) {
1747 return ndr_push_error(ndr
, NDR_ERR_BUFSIZE
,
1748 "ndr_push_relative_ptr2 ndr->offset(%"PRIu32
") < ndr->relative_base_offset(%"PRIu32
")",
1749 ndr
->offset
, ndr
->relative_base_offset
);
1752 relative_offset
= ndr
->offset
- ndr
->relative_base_offset
;
1754 if (ndr
->flags
& LIBNDR_FLAG_NOALIGN
) {
1756 } else if (ndr
->flags
& LIBNDR_FLAG_ALIGN2
) {
1758 } else if (ndr
->flags
& LIBNDR_FLAG_ALIGN4
) {
1760 } else if (ndr
->flags
& LIBNDR_FLAG_ALIGN8
) {
1764 pad
= ndr_align_size(relative_offset
, align
);
1766 NDR_CHECK(ndr_push_zero(ndr
, pad
));
1769 relative_offset
= ndr
->offset
- ndr
->relative_base_offset
;
1770 if (relative_offset
> UINT16_MAX
) {
1771 return ndr_push_error(ndr
, NDR_ERR_BUFSIZE
,
1772 "ndr_push_relative_ptr2 relative_offset(%"PRIu32
") > UINT16_MAX",
1776 save_offset
= ndr
->offset
;
1777 NDR_CHECK(ndr_token_retrieve(&ndr
->relative_list
, p
, &ptr_offset
));
1778 if (ptr_offset
> ndr
->offset
) {
1779 return ndr_push_error(ndr
, NDR_ERR_BUFSIZE
,
1780 "ndr_push_short_relative_ptr2 ptr_offset(%"PRIu32
") > ndr->offset(%"PRIu32
")",
1781 ptr_offset
, ndr
->offset
);
1783 ndr
->offset
= ptr_offset
;
1784 NDR_CHECK(ndr_push_uint16(ndr
, NDR_SCALARS
, relative_offset
));
1785 ndr
->offset
= save_offset
;
1786 return NDR_ERR_SUCCESS
;
1790 push a relative object - stage2 start
1791 this is called during buffers processing
1793 _PUBLIC_
enum ndr_err_code
ndr_push_relative_ptr2_start(struct ndr_push
*ndr
, const void *p
)
1795 enum ndr_err_code ret
;
1797 return NDR_ERR_SUCCESS
;
1799 if (!(ndr
->flags
& LIBNDR_FLAG_RELATIVE_REVERSE
)) {
1800 uint32_t relative_offset
;
1804 if (ndr
->offset
< ndr
->relative_base_offset
) {
1805 return ndr_push_error(ndr
, NDR_ERR_BUFSIZE
,
1806 "ndr_push_relative_ptr2_start ndr->offset(%"PRIu32
") < ndr->relative_base_offset(%"PRIu32
")",
1807 ndr
->offset
, ndr
->relative_base_offset
);
1810 relative_offset
= ndr
->offset
- ndr
->relative_base_offset
;
1812 if (ndr
->flags
& LIBNDR_FLAG_NOALIGN
) {
1814 } else if (ndr
->flags
& LIBNDR_FLAG_ALIGN2
) {
1816 } else if (ndr
->flags
& LIBNDR_FLAG_ALIGN4
) {
1818 } else if (ndr
->flags
& LIBNDR_FLAG_ALIGN8
) {
1822 pad
= ndr_align_size(relative_offset
, align
);
1824 NDR_CHECK(ndr_push_zero(ndr
, pad
));
1827 return ndr_push_relative_ptr2(ndr
, p
);
1829 if (ndr
->relative_end_offset
== -1) {
1830 return ndr_push_error(ndr
, NDR_ERR_RELATIVE
,
1831 "ndr_push_relative_ptr2_start RELATIVE_REVERSE flag set and relative_end_offset %"PRIu32
,
1832 ndr
->relative_end_offset
);
1834 ret
= ndr_token_store(ndr
,
1835 &ndr
->relative_begin_list
,
1838 if (ret
== NDR_ERR_RANGE
) {
1839 return ndr_push_error(ndr
, ret
,
1840 "More than %d NDR tokens stored for array_size",
1841 NDR_TOKEN_MAX_LIST_SIZE
);
1847 push a relative object - stage2 end
1848 this is called during buffers processing
1850 _PUBLIC_
enum ndr_err_code
ndr_push_relative_ptr2_end(struct ndr_push
*ndr
, const void *p
)
1852 uint32_t begin_offset
= 0xFFFFFFFF;
1854 uint32_t correct_offset
= 0;
1859 return NDR_ERR_SUCCESS
;
1862 if (!(ndr
->flags
& LIBNDR_FLAG_RELATIVE_REVERSE
)) {
1863 return NDR_ERR_SUCCESS
;
1866 if (ndr
->flags
& LIBNDR_FLAG_NO_NDR_SIZE
) {
1867 /* better say more than calculation a too small buffer */
1868 NDR_PUSH_ALIGN(ndr
, 8);
1869 return NDR_ERR_SUCCESS
;
1872 if (ndr
->relative_end_offset
< ndr
->offset
) {
1873 return ndr_push_error(ndr
, NDR_ERR_RELATIVE
,
1874 "ndr_push_relative_ptr2_end:"
1875 "relative_end_offset %"PRIu32
" < offset %"PRIu32
,
1876 ndr
->relative_end_offset
, ndr
->offset
);
1879 NDR_CHECK(ndr_token_retrieve(&ndr
->relative_begin_list
, p
, &begin_offset
));
1881 /* we have marshalled a buffer, see how long it was */
1882 len
= ndr
->offset
- begin_offset
;
1885 return ndr_push_error(ndr
, NDR_ERR_RELATIVE
,
1886 "ndr_push_relative_ptr2_end:"
1887 "offset %"PRIu32
" - begin_offset %"PRIu32
" < 0",
1888 ndr
->offset
, begin_offset
);
1891 if (ndr
->relative_end_offset
< len
) {
1892 return ndr_push_error(ndr
, NDR_ERR_RELATIVE
,
1893 "ndr_push_relative_ptr2_end:"
1894 "relative_end_offset %"PRIu32
" < len %zd",
1898 /* the reversed offset is at the end of the main buffer */
1899 correct_offset
= ndr
->relative_end_offset
- len
;
1901 if (ndr
->flags
& LIBNDR_FLAG_NOALIGN
) {
1903 } else if (ndr
->flags
& LIBNDR_FLAG_ALIGN2
) {
1905 } else if (ndr
->flags
& LIBNDR_FLAG_ALIGN4
) {
1907 } else if (ndr
->flags
& LIBNDR_FLAG_ALIGN8
) {
1911 pad
= ndr_align_size(correct_offset
, align
);
1913 correct_offset
+= pad
;
1914 correct_offset
-= align
;
1917 if (correct_offset
< begin_offset
) {
1918 return ndr_push_error(ndr
, NDR_ERR_RELATIVE
,
1919 "ndr_push_relative_ptr2_end: "
1920 "correct_offset %"PRIu32
" < begin_offset %"PRIu32
,
1921 correct_offset
, begin_offset
);
1925 uint32_t clear_size
= correct_offset
- begin_offset
;
1927 clear_size
= MIN(clear_size
, len
);
1929 /* now move the marshalled buffer to the end of the main buffer */
1930 memmove(ndr
->data
+ correct_offset
, ndr
->data
+ begin_offset
, len
);
1933 /* and wipe out old buffer within the main buffer */
1934 memset(ndr
->data
+ begin_offset
, '\0', clear_size
);
1938 /* and set the end offset for the next buffer */
1939 ndr
->relative_end_offset
= correct_offset
;
1941 /* finally write the offset to the main buffer */
1942 ndr
->offset
= correct_offset
;
1943 NDR_CHECK(ndr_push_relative_ptr2(ndr
, p
));
1945 /* restore to where we were in the main buffer */
1946 ndr
->offset
= begin_offset
;
1948 return NDR_ERR_SUCCESS
;
1952 get the current base for relative pointers for the pull
1954 _PUBLIC_
uint32_t ndr_pull_get_relative_base_offset(struct ndr_pull
*ndr
)
1956 return ndr
->relative_base_offset
;
1960 restore the old base for relative pointers for the pull
1962 _PUBLIC_
void ndr_pull_restore_relative_base_offset(struct ndr_pull
*ndr
, uint32_t offset
)
1964 ndr
->relative_base_offset
= offset
;
1968 setup the current base for relative pointers for the pull
1969 called in the NDR_SCALAR stage
1971 _PUBLIC_
enum ndr_err_code
ndr_pull_setup_relative_base_offset1(struct ndr_pull
*ndr
, const void *p
, uint32_t offset
)
1973 enum ndr_err_code ret
;
1974 ndr
->relative_base_offset
= offset
;
1975 ret
= ndr_token_store(ndr
, &ndr
->relative_base_list
, p
, offset
);
1976 if (ret
== NDR_ERR_RANGE
) {
1977 return ndr_pull_error(ndr
, ret
,
1978 "More than %d NDR tokens stored for relative_base_list",
1979 NDR_TOKEN_MAX_LIST_SIZE
);
1985 setup the current base for relative pointers for the pull
1986 called in the NDR_BUFFERS stage
1988 _PUBLIC_
enum ndr_err_code
ndr_pull_setup_relative_base_offset2(struct ndr_pull
*ndr
, const void *p
)
1990 return ndr_token_retrieve(&ndr
->relative_base_list
, p
, &ndr
->relative_base_offset
);
1994 pull a relative object - stage1
1995 called during SCALARS processing
1997 _PUBLIC_
enum ndr_err_code
ndr_pull_relative_ptr1(struct ndr_pull
*ndr
, const void *p
, uint32_t rel_offset
)
1999 enum ndr_err_code ret
;
2000 rel_offset
+= ndr
->relative_base_offset
;
2001 if (rel_offset
> ndr
->data_size
) {
2002 return ndr_pull_error(ndr
, NDR_ERR_BUFSIZE
,
2003 "ndr_pull_relative_ptr1 rel_offset(%"PRIu32
") > ndr->data_size(%"PRIu32
")",
2004 rel_offset
, ndr
->data_size
);
2006 ret
= ndr_token_store(ndr
, &ndr
->relative_list
, p
, rel_offset
);
2007 if (ret
== NDR_ERR_RANGE
) {
2008 return ndr_pull_error(ndr
, ret
,
2009 "More than %d NDR tokens stored for relative_list",
2010 NDR_TOKEN_MAX_LIST_SIZE
);
2016 pull a relative object - stage2
2017 called during BUFFERS processing
2019 _PUBLIC_
enum ndr_err_code
ndr_pull_relative_ptr2(struct ndr_pull
*ndr
, const void *p
)
2021 uint32_t rel_offset
;
2022 NDR_CHECK(ndr_token_retrieve(&ndr
->relative_list
, p
, &rel_offset
));
2023 return ndr_pull_set_offset(ndr
, rel_offset
);
2026 _PUBLIC_
const char *ndr_map_error2string(enum ndr_err_code ndr_err
)
2028 const char *ret
= "Unknown error";
2031 case NDR_ERR_SUCCESS
:
2034 case NDR_ERR_ARRAY_SIZE
:
2035 ret
= "Bad Array Size";
2037 case NDR_ERR_BAD_SWITCH
:
2040 case NDR_ERR_OFFSET
:
2041 ret
= "Offset Error";
2043 case NDR_ERR_RELATIVE
:
2044 ret
= "Relative Pointer Error";
2046 case NDR_ERR_CHARCNV
:
2047 ret
= "Character Conversion Error";
2049 case NDR_ERR_LENGTH
:
2050 ret
= "Length Error";
2052 case NDR_ERR_SUBCONTEXT
:
2053 ret
= "Subcontext Error";
2055 case NDR_ERR_COMPRESSION
:
2056 ret
= "Compression Error";
2058 case NDR_ERR_STRING
:
2059 ret
= "String Error";
2061 case NDR_ERR_VALIDATE
:
2062 ret
= "Validate Error";
2064 case NDR_ERR_BUFSIZE
:
2065 ret
= "Buffer Size Error";
2068 ret
= "Allocation Error";
2071 ret
= "Range Error";
2074 ret
= "Token Error";
2076 case NDR_ERR_IPV4ADDRESS
:
2077 ret
= "IPv4 Address Error";
2079 case NDR_ERR_INVALID_POINTER
:
2080 ret
= "Invalid Pointer";
2082 case NDR_ERR_UNREAD_BYTES
:
2083 ret
= "Unread Bytes";
2086 ret
= "NDR64 assertion error";
2088 case NDR_ERR_INCOMPLETE_BUFFER
:
2089 ret
= "Incomplete Buffer";
2091 case NDR_ERR_MAX_RECURSION_EXCEEDED
:
2092 ret
= "Maximum Recursion Exceeded";
2094 case NDR_ERR_UNDERFLOW
:
2097 case NDR_ERR_IPV6ADDRESS
:
2098 ret
= "Invalid IPv6 address";
2101 ret
= "Invalid NDR flags";