2 Unix SMB/CIFS implementation.
6 Copyright (C) Andrew Tridgell 2003
7 Copyright (C) Jelmer Vernooij 2005-2008
9 This program is free software; you can redistribute it and/or modify
10 it under the terms of the GNU General Public License as published by
11 the Free Software Foundation; either version 3 of the License, or
12 (at your option) any later version.
14 This program is distributed in the hope that it will be useful,
15 but WITHOUT ANY WARRANTY; without even the implied warranty of
16 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17 GNU General Public License for more details.
19 You should have received a copy of the GNU General Public License
20 along with this program. If not, see <http://www.gnu.org/licenses/>.
24 this provides the core routines for NDR parsing functions
26 see http://www.opengroup.org/onlinepubs/9629399/chap14.htm for details
31 #include "librpc/ndr/libndr.h"
32 #include "../lib/util/dlinklist.h"
35 #define DBGC_CLASS DBGC_RPC_PARSE
37 #define NDR_BASE_MARSHALL_SIZE 1024
40 * This value is arbitary, but designed to reduce the memory a client
41 * can allocate and the work the client can force in processing a
44 * In an ideal world this would be controlled by range() restrictions
45 * on array sizes and careful IDL construction to avoid arbitary
46 * linked lists, but this is a backstop for now.
48 #define NDR_TOKEN_MAX_LIST_SIZE 65535
50 /* this guid indicates NDR encoding in a protocol tower */
51 const struct ndr_syntax_id ndr_transfer_syntax_ndr
= {
52 { 0x8a885d04, 0x1ceb, 0x11c9, {0x9f, 0xe8}, {0x08,0x00,0x2b,0x10,0x48,0x60} },
56 const struct ndr_syntax_id ndr_transfer_syntax_ndr64
= {
57 { 0x71710533, 0xbeba, 0x4937, {0x83, 0x19}, {0xb5,0xdb,0xef,0x9c,0xcc,0x36} },
61 const struct ndr_syntax_id ndr_syntax_id_null
= {
62 { 0, 0, 0, { 0, 0 }, { 0, 0, 0, 0, 0, 0 } },
67 work out the number of bytes needed to align on a n byte boundary
69 _PUBLIC_
size_t ndr_align_size(uint32_t offset
, size_t n
)
71 if ((offset
& (n
-1)) == 0) return 0;
72 return n
- (offset
& (n
-1));
76 initialise a ndr parse structure from a data blob
78 _PUBLIC_
struct ndr_pull
*ndr_pull_init_blob(const DATA_BLOB
*blob
, TALLOC_CTX
*mem_ctx
)
82 ndr
= talloc_zero(mem_ctx
, struct ndr_pull
);
83 if (!ndr
) return NULL
;
84 ndr
->current_mem_ctx
= mem_ctx
;
86 ndr
->data
= blob
->data
;
87 ndr
->data_size
= blob
->length
;
92 _PUBLIC_
enum ndr_err_code
ndr_pull_append(struct ndr_pull
*ndr
, DATA_BLOB
*blob
)
94 enum ndr_err_code ndr_err
;
99 if (blob
->length
== 0) {
100 return NDR_ERR_SUCCESS
;
103 ndr_err
= ndr_token_retrieve(&ndr
->array_size_list
, ndr
, &append
);
104 if (ndr_err
== NDR_ERR_TOKEN
) {
106 ndr_err
= NDR_ERR_SUCCESS
;
110 if (ndr
->data_size
== 0) {
115 if (append
== UINT32_MAX
) {
117 * append == UINT32_MAX means that
118 * ndr->data is either NULL or a valid
119 * talloc child of ndr, which means
120 * we can use data_blob_append() without
121 * data_blob_talloc() of the existing callers data
123 b
= data_blob_const(ndr
->data
, ndr
->data_size
);
125 b
= data_blob_talloc(ndr
, ndr
->data
, ndr
->data_size
);
126 if (b
.data
== NULL
) {
127 return ndr_pull_error(ndr
, NDR_ERR_ALLOC
, "%s", __location__
);
131 ok
= data_blob_append(ndr
, &b
, blob
->data
, blob
->length
);
133 return ndr_pull_error(ndr
, NDR_ERR_ALLOC
, "%s", __location__
);
137 ndr
->data_size
= b
.length
;
139 return ndr_token_store(ndr
, &ndr
->array_size_list
, ndr
, UINT32_MAX
);
142 _PUBLIC_
enum ndr_err_code
ndr_pull_pop(struct ndr_pull
*ndr
)
147 if (ndr
->relative_base_offset
!= 0) {
148 return ndr_pull_error(ndr
, NDR_ERR_RELATIVE
,
151 if (ndr
->relative_highest_offset
!= 0) {
152 return ndr_pull_error(ndr
, NDR_ERR_RELATIVE
,
155 if (ndr
->relative_list
.count
!= 0) {
156 return ndr_pull_error(ndr
, NDR_ERR_RELATIVE
,
159 if (ndr
->relative_base_list
.count
!= 0) {
160 return ndr_pull_error(ndr
, NDR_ERR_RELATIVE
,
165 * we need to keep up to 7 bytes
166 * in order to get the aligment right.
168 skip
= ndr
->offset
& 0xFFFFFFF8;
171 return NDR_ERR_SUCCESS
;
175 ndr
->data_size
-= skip
;
177 append
= ndr_token_peek(&ndr
->array_size_list
, ndr
);
178 if (append
!= UINT32_MAX
) {
180 * here we assume, that ndr->data is not a
181 * talloc child of ndr.
184 return NDR_ERR_SUCCESS
;
187 memmove(ndr
->data
, ndr
->data
+ skip
, ndr
->data_size
);
189 ndr
->data
= talloc_realloc(ndr
, ndr
->data
, uint8_t, ndr
->data_size
);
190 if (ndr
->data_size
!= 0 && ndr
->data
== NULL
) {
191 return ndr_pull_error(ndr
, NDR_ERR_ALLOC
, "%s", __location__
);
194 return NDR_ERR_SUCCESS
;
198 advance by 'size' bytes
200 _PUBLIC_
enum ndr_err_code
ndr_pull_advance(struct ndr_pull
*ndr
, uint32_t size
)
202 NDR_PULL_NEED_BYTES(ndr
, size
);
204 return NDR_ERR_SUCCESS
;
208 set the parse offset to 'ofs'
210 static enum ndr_err_code
ndr_pull_set_offset(struct ndr_pull
*ndr
, uint32_t ofs
)
213 if (ndr
->offset
> ndr
->data_size
) {
214 return ndr_pull_error(ndr
, NDR_ERR_BUFSIZE
,
215 "ndr_pull_set_offset %u failed",
218 return NDR_ERR_SUCCESS
;
221 /* create a ndr_push structure, ready for some marshalling */
222 _PUBLIC_
struct ndr_push
*ndr_push_init_ctx(TALLOC_CTX
*mem_ctx
)
224 struct ndr_push
*ndr
;
226 ndr
= talloc_zero(mem_ctx
, struct ndr_push
);
232 ndr
->alloc_size
= NDR_BASE_MARSHALL_SIZE
;
233 ndr
->data
= talloc_array(ndr
, uint8_t, ndr
->alloc_size
);
242 /* return a DATA_BLOB structure for the current ndr_push marshalled data */
243 _PUBLIC_ DATA_BLOB
ndr_push_blob(struct ndr_push
*ndr
)
246 blob
= data_blob_const(ndr
->data
, ndr
->offset
);
247 if (ndr
->alloc_size
> ndr
->offset
) {
248 ndr
->data
[ndr
->offset
] = 0;
255 expand the available space in the buffer to ndr->offset + extra_size
257 _PUBLIC_
enum ndr_err_code
ndr_push_expand(struct ndr_push
*ndr
, uint32_t extra_size
)
259 uint32_t size
= extra_size
+ ndr
->offset
;
261 if (size
< ndr
->offset
) {
262 /* extra_size overflowed the offset */
263 return ndr_push_error(ndr
, NDR_ERR_BUFSIZE
, "Overflow in push_expand to %u",
267 if (ndr
->fixed_buf_size
) {
268 if (ndr
->alloc_size
>= size
) {
269 return NDR_ERR_SUCCESS
;
271 return ndr_push_error(ndr
,
273 "Overflow of fixed buffer in "
278 if (ndr
->alloc_size
> size
) {
279 return NDR_ERR_SUCCESS
;
282 ndr
->alloc_size
+= NDR_BASE_MARSHALL_SIZE
;
283 if (size
+1 > ndr
->alloc_size
) {
284 ndr
->alloc_size
= size
+1;
286 ndr
->data
= talloc_realloc(ndr
, ndr
->data
, uint8_t, ndr
->alloc_size
);
288 return ndr_push_error(ndr
, NDR_ERR_ALLOC
, "Failed to push_expand to %u",
292 return NDR_ERR_SUCCESS
;
295 _PUBLIC_
void ndr_print_debugc_helper(struct ndr_print
*ndr
, const char *format
, ...)
303 va_start(ap
, format
);
304 ret
= vasprintf(&s
, format
, ap
);
311 dbgc_class
= *(int *)ndr
->private_data
;
313 if (ndr
->no_newline
) {
314 DEBUGADDC(dbgc_class
, 1,("%s", s
));
319 for (i
=0;i
<ndr
->depth
;i
++) {
320 DEBUGADDC(dbgc_class
, 1,(" "));
323 DEBUGADDC(dbgc_class
, 1,("%s\n", s
));
327 _PUBLIC_
void ndr_print_debug_helper(struct ndr_print
*ndr
, const char *format
, ...)
334 va_start(ap
, format
);
335 ret
= vasprintf(&s
, format
, ap
);
342 if (ndr
->no_newline
) {
343 DEBUGADD(1,("%s", s
));
348 for (i
=0;i
<ndr
->depth
;i
++) {
352 DEBUGADD(1,("%s\n", s
));
356 _PUBLIC_
void ndr_print_printf_helper(struct ndr_print
*ndr
, const char *format
, ...)
361 if (!ndr
->no_newline
) {
362 for (i
=0;i
<ndr
->depth
;i
++) {
367 va_start(ap
, format
);
370 if (!ndr
->no_newline
) {
375 _PUBLIC_
void ndr_print_string_helper(struct ndr_print
*ndr
, const char *format
, ...)
380 if (!ndr
->no_newline
) {
381 for (i
=0;i
<ndr
->depth
;i
++) {
382 ndr
->private_data
= talloc_asprintf_append_buffer(
383 (char *)ndr
->private_data
, " ");
387 va_start(ap
, format
);
388 ndr
->private_data
= talloc_vasprintf_append_buffer((char *)ndr
->private_data
,
391 if (!ndr
->no_newline
) {
392 ndr
->private_data
= talloc_asprintf_append_buffer((char *)ndr
->private_data
,
398 a useful helper function for printing idl structures via DEBUGC()
400 _PUBLIC_
void ndr_print_debugc(int dbgc_class
, ndr_print_fn_t fn
, const char *name
, void *ptr
)
402 struct ndr_print
*ndr
;
404 DEBUGC(dbgc_class
, 1,(" "));
406 ndr
= talloc_zero(NULL
, struct ndr_print
);
408 ndr
->private_data
= &dbgc_class
;
409 ndr
->print
= ndr_print_debugc_helper
;
412 #ifdef DEBUG_PASSWORD
413 if (CHECK_DEBUGLVL(100)) {
414 ndr
->print_secrets
= true;
423 a useful helper function for printing idl structures via DEBUG()
425 _PUBLIC_
void ndr_print_debug(ndr_print_fn_t fn
, const char *name
, void *ptr
)
427 struct ndr_print
*ndr
;
431 ndr
= talloc_zero(NULL
, struct ndr_print
);
433 ndr
->print
= ndr_print_debug_helper
;
436 #ifdef DEBUG_PASSWORD
437 if (CHECK_DEBUGLVL(100)) {
438 ndr
->print_secrets
= true;
447 a useful helper function for printing idl unions via DEBUG()
449 _PUBLIC_
void ndr_print_union_debug(ndr_print_fn_t fn
, const char *name
, uint32_t level
, void *ptr
)
451 struct ndr_print
*ndr
;
455 ndr
= talloc_zero(NULL
, struct ndr_print
);
457 ndr
->print
= ndr_print_debug_helper
;
460 #ifdef DEBUG_PASSWORD
461 if (CHECK_DEBUGLVL(100)) {
462 ndr
->print_secrets
= true;
466 ndr_print_set_switch_value(ndr
, ptr
, level
);
472 a useful helper function for printing idl function calls via DEBUG()
474 _PUBLIC_
void ndr_print_function_debug(ndr_print_function_t fn
, const char *name
, int flags
, void *ptr
)
476 struct ndr_print
*ndr
;
480 ndr
= talloc_zero(NULL
, struct ndr_print
);
482 ndr
->print
= ndr_print_debug_helper
;
485 #ifdef DEBUG_PASSWORD
486 if (CHECK_DEBUGLVL(100)) {
487 ndr
->print_secrets
= true;
491 fn(ndr
, name
, flags
, ptr
);
496 a useful helper function for printing idl structures to a string
498 _PUBLIC_
char *ndr_print_struct_string(TALLOC_CTX
*mem_ctx
, ndr_print_fn_t fn
, const char *name
, void *ptr
)
500 struct ndr_print
*ndr
;
503 ndr
= talloc_zero(mem_ctx
, struct ndr_print
);
504 if (!ndr
) return NULL
;
505 ndr
->private_data
= talloc_strdup(ndr
, "");
506 if (!ndr
->private_data
) {
509 ndr
->print
= ndr_print_string_helper
;
514 ret
= talloc_steal(mem_ctx
, (char *)ndr
->private_data
);
521 a useful helper function for printing idl unions to a string
523 _PUBLIC_
char *ndr_print_union_string(TALLOC_CTX
*mem_ctx
, ndr_print_fn_t fn
, const char *name
, uint32_t level
, void *ptr
)
525 struct ndr_print
*ndr
;
528 ndr
= talloc_zero(mem_ctx
, struct ndr_print
);
529 if (!ndr
) return NULL
;
530 ndr
->private_data
= talloc_strdup(ndr
, "");
531 if (!ndr
->private_data
) {
534 ndr
->print
= ndr_print_string_helper
;
537 ndr_print_set_switch_value(ndr
, ptr
, level
);
539 ret
= talloc_steal(mem_ctx
, (char *)ndr
->private_data
);
546 a useful helper function for printing idl function calls to a string
548 _PUBLIC_
char *ndr_print_function_string(TALLOC_CTX
*mem_ctx
,
549 ndr_print_function_t fn
, const char *name
,
550 int flags
, void *ptr
)
552 struct ndr_print
*ndr
;
555 ndr
= talloc_zero(mem_ctx
, struct ndr_print
);
556 if (!ndr
) return NULL
;
557 ndr
->private_data
= talloc_strdup(ndr
, "");
558 if (!ndr
->private_data
) {
561 ndr
->print
= ndr_print_string_helper
;
564 fn(ndr
, name
, flags
, ptr
);
565 ret
= talloc_steal(mem_ctx
, (char *)ndr
->private_data
);
571 _PUBLIC_
void ndr_set_flags(uint32_t *pflags
, uint32_t new_flags
)
573 /* the big/little endian flags are inter-dependent */
574 if (new_flags
& LIBNDR_FLAG_LITTLE_ENDIAN
) {
575 (*pflags
) &= ~LIBNDR_FLAG_BIGENDIAN
;
576 (*pflags
) &= ~LIBNDR_FLAG_NDR64
;
578 if (new_flags
& LIBNDR_FLAG_BIGENDIAN
) {
579 (*pflags
) &= ~LIBNDR_FLAG_LITTLE_ENDIAN
;
580 (*pflags
) &= ~LIBNDR_FLAG_NDR64
;
582 if (new_flags
& LIBNDR_ALIGN_FLAGS
) {
583 /* Ensure we only have the passed-in
584 align flag set in the new_flags,
585 remove any old align flag. */
586 (*pflags
) &= ~LIBNDR_ALIGN_FLAGS
;
588 if (new_flags
& LIBNDR_FLAG_NO_RELATIVE_REVERSE
) {
589 (*pflags
) &= ~LIBNDR_FLAG_RELATIVE_REVERSE
;
591 (*pflags
) |= new_flags
;
595 return and possibly log an NDR error
597 _PUBLIC_
enum ndr_err_code
_ndr_pull_error(struct ndr_pull
*ndr
,
598 enum ndr_err_code ndr_err
,
599 const char *function
,
600 const char *location
,
601 const char *format
, ...)
607 if (ndr
->flags
& LIBNDR_FLAG_INCOMPLETE_BUFFER
) {
609 case NDR_ERR_BUFSIZE
:
610 return NDR_ERR_INCOMPLETE_BUFFER
;
616 va_start(ap
, format
);
617 ret
= vasprintf(&s
, format
, ap
);
621 return NDR_ERR_ALLOC
;
624 D_WARNING("%s: ndr_pull_error(%s): %s at %s\n",
626 ndr_map_error2string(ndr_err
),
636 return and possibly log an NDR error
638 _PUBLIC_
enum ndr_err_code
_ndr_push_error(struct ndr_push
*ndr
,
639 enum ndr_err_code ndr_err
,
640 const char *function
,
641 const char *location
,
642 const char *format
, ...)
648 va_start(ap
, format
);
649 ret
= vasprintf(&s
, format
, ap
);
653 return NDR_ERR_ALLOC
;
656 D_WARNING("%s: ndr_push_error(%s): %s at %s\n",
658 ndr_map_error2string(ndr_err
),
668 handle subcontext buffers, which in midl land are user-marshalled, but
669 we use magic in pidl to make them easier to cope with
671 _PUBLIC_
enum ndr_err_code
ndr_pull_subcontext_start(struct ndr_pull
*ndr
,
672 struct ndr_pull
**_subndr
,
676 struct ndr_pull
*subndr
;
677 uint32_t r_content_size
;
678 bool force_le
= false;
679 bool force_be
= false;
681 switch (header_size
) {
683 uint32_t content_size
= ndr
->data_size
- ndr
->offset
;
685 content_size
= size_is
;
687 r_content_size
= content_size
;
692 uint16_t content_size
;
693 NDR_CHECK(ndr_pull_uint16(ndr
, NDR_SCALARS
, &content_size
));
694 if (size_is
>= 0 && size_is
!= content_size
) {
695 return ndr_pull_error(ndr
, NDR_ERR_SUBCONTEXT
, "Bad subcontext (PULL) size_is(%d) (0x%04x) mismatch content_size %d (0x%04x)",
696 (int)size_is
, (int)size_is
,
700 r_content_size
= content_size
;
705 uint32_t content_size
;
706 NDR_CHECK(ndr_pull_uint3264(ndr
, NDR_SCALARS
, &content_size
));
707 if (size_is
>= 0 && size_is
!= content_size
) {
708 return ndr_pull_error(ndr
, NDR_ERR_SUBCONTEXT
, "Bad subcontext (PULL) size_is(%d) (0x%08x) mismatch content_size %d (0x%08x)",
709 (int)size_is
, (int)size_is
,
713 r_content_size
= content_size
;
718 * Common Type Header for the Serialization Stream
719 * See [MS-RPCE] 2.2.6 Type Serialization Version 1
725 uint32_t content_size
;
729 NDR_CHECK(ndr_pull_uint8(ndr
, NDR_SCALARS
, &version
));
732 return ndr_pull_error(ndr
, NDR_ERR_SUBCONTEXT
,
733 "Bad subcontext (PULL) Common Type Header version %d != 1",
741 NDR_CHECK(ndr_pull_uint8(ndr
, NDR_SCALARS
, &drep
));
744 } else if (drep
== 0x00) {
747 return ndr_pull_error(ndr
, NDR_ERR_SUBCONTEXT
,
748 "Bad subcontext (PULL) Common Type Header invalid drep 0x%02X",
752 /* length of the "Private Header for Constructed Type" */
753 NDR_CHECK(ndr_pull_uint16(ndr
, NDR_SCALARS
, &hdrlen
));
755 return ndr_pull_error(ndr
, NDR_ERR_SUBCONTEXT
,
756 "Bad subcontext (PULL) Common Type Header length %d != 8",
760 /* filler should be ignored */
761 NDR_CHECK(ndr_pull_uint32(ndr
, NDR_SCALARS
, &filler
));
764 * Private Header for Constructed Type
766 /* length - will be updated latter */
767 NDR_CHECK(ndr_pull_uint32(ndr
, NDR_SCALARS
, &content_size
));
768 if (size_is
>= 0 && size_is
!= content_size
) {
769 return ndr_pull_error(ndr
, NDR_ERR_SUBCONTEXT
, "Bad subcontext (PULL) size_is(%d) mismatch content_size %d",
770 (int)size_is
, (int)content_size
);
772 /* the content size must be a multiple of 8 */
773 if ((content_size
% 8) != 0) {
774 return ndr_pull_error(ndr
, NDR_ERR_SUBCONTEXT
,
775 "Bad subcontext (PULL) size_is(%d) not padded to 8 content_size %d",
776 (int)size_is
, (int)content_size
);
778 r_content_size
= content_size
;
781 NDR_CHECK(ndr_pull_uint32(ndr
, NDR_SCALARS
, &reserved
));
786 * a shallow copy like subcontext
787 * useful for DCERPC pipe chunks.
789 subndr
= talloc_zero(ndr
, struct ndr_pull
);
790 NDR_ERR_HAVE_NO_MEMORY(subndr
);
792 subndr
->flags
= ndr
->flags
;
793 subndr
->current_mem_ctx
= ndr
->current_mem_ctx
;
794 subndr
->data
= ndr
->data
;
795 subndr
->offset
= ndr
->offset
;
796 subndr
->data_size
= ndr
->data_size
;
799 return NDR_ERR_SUCCESS
;
802 return ndr_pull_error(ndr
, NDR_ERR_SUBCONTEXT
, "Bad subcontext (PULL) header_size %d",
806 NDR_PULL_NEED_BYTES(ndr
, r_content_size
);
808 subndr
= talloc_zero(ndr
, struct ndr_pull
);
809 NDR_ERR_HAVE_NO_MEMORY(subndr
);
810 subndr
->flags
= ndr
->flags
& ~LIBNDR_FLAG_NDR64
;
811 subndr
->current_mem_ctx
= ndr
->current_mem_ctx
;
813 subndr
->data
= ndr
->data
+ ndr
->offset
;
815 subndr
->data_size
= r_content_size
;
818 ndr_set_flags(&ndr
->flags
, LIBNDR_FLAG_LITTLE_ENDIAN
);
819 } else if (force_be
) {
820 ndr_set_flags(&ndr
->flags
, LIBNDR_FLAG_BIGENDIAN
);
824 return NDR_ERR_SUCCESS
;
827 _PUBLIC_
enum ndr_err_code
ndr_pull_subcontext_end(struct ndr_pull
*ndr
,
828 struct ndr_pull
*subndr
,
833 uint32_t highest_ofs
;
835 if (header_size
== 0xFFFFFFFF) {
836 advance
= subndr
->offset
- ndr
->offset
;
837 } else if (size_is
>= 0) {
839 } else if (header_size
> 0) {
840 advance
= subndr
->data_size
;
842 advance
= subndr
->offset
;
845 if (subndr
->offset
> ndr
->relative_highest_offset
) {
846 highest_ofs
= subndr
->offset
;
848 highest_ofs
= subndr
->relative_highest_offset
;
850 if (!(subndr
->flags
& LIBNDR_FLAG_SUBCONTEXT_NO_UNREAD_BYTES
)) {
852 * avoid an error unless SUBCONTEXT_NO_UNREAD_BYTES is specified
854 highest_ofs
= advance
;
856 if (highest_ofs
< advance
) {
857 return ndr_pull_error(subndr
, NDR_ERR_UNREAD_BYTES
,
858 "not all bytes consumed ofs[%u] advance[%u]",
859 highest_ofs
, advance
);
862 NDR_CHECK(ndr_pull_advance(ndr
, advance
));
863 return NDR_ERR_SUCCESS
;
866 _PUBLIC_
enum ndr_err_code
ndr_push_subcontext_start(struct ndr_push
*ndr
,
867 struct ndr_push
**_subndr
,
871 struct ndr_push
*subndr
;
873 subndr
= ndr_push_init_ctx(ndr
);
874 NDR_ERR_HAVE_NO_MEMORY(subndr
);
875 subndr
->flags
= ndr
->flags
& ~LIBNDR_FLAG_NDR64
;
878 NDR_CHECK(ndr_push_zero(subndr
, size_is
));
880 subndr
->relative_end_offset
= size_is
;
884 return NDR_ERR_SUCCESS
;
888 push a subcontext header
890 _PUBLIC_
enum ndr_err_code
ndr_push_subcontext_end(struct ndr_push
*ndr
,
891 struct ndr_push
*subndr
,
898 padding_len
= size_is
- subndr
->offset
;
899 if (padding_len
< 0) {
900 return ndr_push_error(ndr
, NDR_ERR_SUBCONTEXT
, "Bad subcontext (PUSH) content_size %d is larger than size_is(%d)",
901 (int)subndr
->offset
, (int)size_is
);
903 subndr
->offset
= size_is
;
906 switch (header_size
) {
911 NDR_CHECK(ndr_push_uint16(ndr
, NDR_SCALARS
, subndr
->offset
));
915 NDR_CHECK(ndr_push_uint3264(ndr
, NDR_SCALARS
, subndr
->offset
));
920 * Common Type Header for the Serialization Stream
921 * See [MS-RPCE] 2.2.6 Type Serialization Version 1
923 padding_len
= NDR_ROUND(subndr
->offset
, 8) - subndr
->offset
;
924 if (padding_len
> 0) {
925 NDR_CHECK(ndr_push_zero(subndr
, padding_len
));
929 NDR_CHECK(ndr_push_uint8(ndr
, NDR_SCALARS
, 1));
935 NDR_CHECK(ndr_push_uint8(ndr
, NDR_SCALARS
, NDR_BE(ndr
)?0x00:0x10));
937 /* length of the "Private Header for Constructed Type" */
938 NDR_CHECK(ndr_push_uint16(ndr
, NDR_SCALARS
, 8));
941 NDR_CHECK(ndr_push_uint32(ndr
, NDR_SCALARS
, 0xCCCCCCCC));
944 * Private Header for Constructed Type
946 /* length - will be updated latter */
947 NDR_CHECK(ndr_push_uint32(ndr
, NDR_SCALARS
, subndr
->offset
));
950 NDR_CHECK(ndr_push_uint32(ndr
, NDR_SCALARS
, 0));
954 return ndr_push_error(ndr
, NDR_ERR_SUBCONTEXT
, "Bad subcontext header size %d",
958 NDR_CHECK(ndr_push_bytes(ndr
, subndr
->data
, subndr
->offset
));
959 return NDR_ERR_SUCCESS
;
969 store a token in the ndr context, for later retrieval
971 _PUBLIC_
enum ndr_err_code
ndr_token_store(TALLOC_CTX
*mem_ctx
,
972 struct ndr_token_list
*list
,
976 if (list
->tokens
== NULL
) {
977 list
->tokens
= talloc_array(mem_ctx
, struct ndr_token
, 10);
978 if (list
->tokens
== NULL
) {
979 NDR_ERR_HAVE_NO_MEMORY(list
->tokens
);
982 struct ndr_token
*new_tokens
= NULL
;
983 uint32_t alloc_count
= talloc_array_length(list
->tokens
);
986 * Check every time we have not allocated too many
987 * tokens. This ensures developer sanity when
988 * debugging the boundary condition
990 if (list
->count
>= NDR_TOKEN_MAX_LIST_SIZE
) {
991 return NDR_ERR_RANGE
;
993 if (list
->count
== alloc_count
) {
996 * Double the list, until we start in chunks
999 unsigned increment
= MIN(list
->count
, 1000);
1000 new_alloc
= alloc_count
+ increment
;
1001 if (new_alloc
< alloc_count
) {
1002 return NDR_ERR_RANGE
;
1004 new_tokens
= talloc_realloc(mem_ctx
, list
->tokens
,
1005 struct ndr_token
, new_alloc
);
1006 NDR_ERR_HAVE_NO_MEMORY(new_tokens
);
1007 list
->tokens
= new_tokens
;
1010 list
->tokens
[list
->count
].key
= key
;
1011 list
->tokens
[list
->count
].value
= value
;
1013 return NDR_ERR_SUCCESS
;
1017 retrieve a token from a ndr context, using cmp_fn to match the tokens
1019 _PUBLIC_
enum ndr_err_code
ndr_token_retrieve_cmp_fn(struct ndr_token_list
*list
,
1020 const void *key
, uint32_t *v
,
1021 comparison_fn_t _cmp_fn
,
1024 struct ndr_token
*tokens
= list
->tokens
;
1027 for (i
= list
->count
- 1; i
< list
->count
; i
--) {
1028 if (_cmp_fn(tokens
[i
].key
, key
) == 0) {
1033 for (i
= list
->count
- 1; i
< list
->count
; i
--) {
1034 if (tokens
[i
].key
== key
) {
1039 return NDR_ERR_TOKEN
;
1041 *v
= tokens
[i
].value
;
1043 if (i
!= list
->count
- 1) {
1044 tokens
[i
] = tokens
[list
->count
- 1];
1048 return NDR_ERR_SUCCESS
;
1052 retrieve a token from a ndr context
1054 _PUBLIC_
enum ndr_err_code
ndr_token_retrieve(struct ndr_token_list
*list
,
1055 const void *key
, uint32_t *v
)
1057 return ndr_token_retrieve_cmp_fn(list
, key
, v
, NULL
, true);
1061 peek at but don't removed a token from a ndr context
1063 _PUBLIC_
uint32_t ndr_token_peek(struct ndr_token_list
*list
, const void *key
)
1066 struct ndr_token
*tokens
= list
->tokens
;
1068 for (i
= list
->count
- 1; i
< list
->count
; i
--) {
1069 if (tokens
[i
].key
== key
) {
1070 return tokens
[i
].value
;
1078 pull an array size field and add it to the array_size_list token list
1080 _PUBLIC_
enum ndr_err_code
ndr_pull_array_size(struct ndr_pull
*ndr
, const void *p
)
1082 enum ndr_err_code ret
;
1084 NDR_CHECK(ndr_pull_uint3264(ndr
, NDR_SCALARS
, &size
));
1085 ret
= ndr_token_store(ndr
, &ndr
->array_size_list
, p
, size
);
1086 if (ret
== NDR_ERR_RANGE
) {
1087 return ndr_pull_error(ndr
, ret
,
1088 "More than %d NDR tokens stored for array_size",
1089 NDR_TOKEN_MAX_LIST_SIZE
);
1095 get the stored array size field
1097 _PUBLIC_
uint32_t ndr_get_array_size(struct ndr_pull
*ndr
, const void *p
)
1099 return ndr_token_peek(&ndr
->array_size_list
, p
);
1103 check the stored array size field
1105 _PUBLIC_
enum ndr_err_code
ndr_check_array_size(struct ndr_pull
*ndr
, void *p
, uint32_t size
)
1108 stored
= ndr_token_peek(&ndr
->array_size_list
, p
);
1109 if (stored
!= size
) {
1110 return ndr_pull_error(ndr
, NDR_ERR_ARRAY_SIZE
,
1111 "Bad array size - got %u expected %u\n",
1114 return NDR_ERR_SUCCESS
;
1118 pull an array length field and add it to the array_length_list token list
1120 _PUBLIC_
enum ndr_err_code
ndr_pull_array_length(struct ndr_pull
*ndr
, const void *p
)
1122 enum ndr_err_code ret
;
1123 uint32_t length
, offset
;
1124 NDR_CHECK(ndr_pull_uint3264(ndr
, NDR_SCALARS
, &offset
));
1126 return ndr_pull_error(ndr
, NDR_ERR_ARRAY_SIZE
,
1127 "non-zero array offset %u\n", offset
);
1129 NDR_CHECK(ndr_pull_uint3264(ndr
, NDR_SCALARS
, &length
));
1130 ret
= ndr_token_store(ndr
, &ndr
->array_length_list
, p
, length
);
1131 if (ret
== NDR_ERR_RANGE
) {
1132 return ndr_pull_error(ndr
, ret
,
1133 "More than %d NDR tokens stored for array_length_list",
1134 NDR_TOKEN_MAX_LIST_SIZE
);
1140 get the stored array length field
1142 _PUBLIC_
uint32_t ndr_get_array_length(struct ndr_pull
*ndr
, const void *p
)
1144 return ndr_token_peek(&ndr
->array_length_list
, p
);
1148 check the stored array length field
1150 _PUBLIC_
enum ndr_err_code
ndr_check_array_length(struct ndr_pull
*ndr
, void *p
, uint32_t length
)
1153 stored
= ndr_token_peek(&ndr
->array_length_list
, p
);
1154 if (stored
!= length
) {
1155 return ndr_pull_error(ndr
, NDR_ERR_ARRAY_SIZE
,
1156 "Bad array length - got %u expected %u\n",
1159 return NDR_ERR_SUCCESS
;
1162 _PUBLIC_
enum ndr_err_code
ndr_push_pipe_chunk_trailer(struct ndr_push
*ndr
, int ndr_flags
, uint32_t count
)
1164 if (ndr
->flags
& LIBNDR_FLAG_NDR64
) {
1165 int64_t tmp
= 0 - (int64_t)count
;
1166 uint64_t ncount
= tmp
;
1168 NDR_CHECK(ndr_push_hyper(ndr
, ndr_flags
, ncount
));
1171 return NDR_ERR_SUCCESS
;
1174 _PUBLIC_
enum ndr_err_code
ndr_check_pipe_chunk_trailer(struct ndr_pull
*ndr
, int ndr_flags
, uint32_t count
)
1176 if (ndr
->flags
& LIBNDR_FLAG_NDR64
) {
1177 int64_t tmp
= 0 - (int64_t)count
;
1178 uint64_t ncount1
= tmp
;
1181 NDR_CHECK(ndr_pull_hyper(ndr
, ndr_flags
, &ncount2
));
1182 if (ncount1
== ncount2
) {
1183 return NDR_ERR_SUCCESS
;
1186 return ndr_pull_error(ndr
, NDR_ERR_ARRAY_SIZE
,
1187 "Bad pipe trailer[%lld should be %lld] size was %lu\"",
1188 (unsigned long long)ncount2
,
1189 (unsigned long long)ncount1
,
1190 (unsigned long)count
);
1193 return NDR_ERR_SUCCESS
;
1197 store a switch value
1199 _PUBLIC_
enum ndr_err_code
ndr_push_set_switch_value(struct ndr_push
*ndr
, const void *p
, uint32_t val
)
1201 enum ndr_err_code ret
=
1202 ndr_token_store(ndr
, &ndr
->switch_list
, p
, val
);
1203 if (ret
== NDR_ERR_RANGE
) {
1204 return ndr_push_error(ndr
, ret
,
1205 "More than %d NDR tokens stored for switch_list",
1206 NDR_TOKEN_MAX_LIST_SIZE
);
1211 _PUBLIC_
enum ndr_err_code
ndr_pull_set_switch_value(struct ndr_pull
*ndr
, const void *p
, uint32_t val
)
1214 enum ndr_err_code ret
=
1215 ndr_token_store(ndr
, &ndr
->switch_list
, p
, val
);
1216 if (ret
== NDR_ERR_RANGE
) {
1217 return ndr_pull_error(ndr
, ret
,
1218 "More than %d NDR tokens stored for switch_list",
1219 NDR_TOKEN_MAX_LIST_SIZE
);
1224 _PUBLIC_
enum ndr_err_code
ndr_print_set_switch_value(struct ndr_print
*ndr
, const void *p
, uint32_t val
)
1226 return ndr_token_store(ndr
, &ndr
->switch_list
, p
, val
);
1229 /* retrieve a switch value (for push) and remove it from the list */
1230 _PUBLIC_
enum ndr_err_code
ndr_push_steal_switch_value(struct ndr_push
*ndr
,
1234 return ndr_token_retrieve(&ndr
->switch_list
, p
, v
);
1237 /* retrieve a switch value and remove it from the list */
1238 _PUBLIC_
uint32_t ndr_print_steal_switch_value(struct ndr_print
*ndr
, const void *p
)
1240 enum ndr_err_code status
;
1243 status
= ndr_token_retrieve(&ndr
->switch_list
, p
, &v
);
1244 if (!NDR_ERR_CODE_IS_SUCCESS(status
)) {
1251 /* retrieve a switch value and remove it from the list */
1252 _PUBLIC_
enum ndr_err_code
ndr_pull_steal_switch_value(struct ndr_pull
*ndr
,
1256 return ndr_token_retrieve(&ndr
->switch_list
, p
, v
);
1260 pull a struct from a blob using NDR
1262 _PUBLIC_
enum ndr_err_code
ndr_pull_struct_blob(const DATA_BLOB
*blob
, TALLOC_CTX
*mem_ctx
, void *p
,
1263 ndr_pull_flags_fn_t fn
)
1265 struct ndr_pull
*ndr
;
1266 ndr
= ndr_pull_init_blob(blob
, mem_ctx
);
1267 NDR_ERR_HAVE_NO_MEMORY(ndr
);
1268 NDR_CHECK_FREE(fn(ndr
, NDR_SCALARS
|NDR_BUFFERS
, p
));
1270 return NDR_ERR_SUCCESS
;
1274 pull a struct from a blob using NDR - failing if all bytes are not consumed
1276 _PUBLIC_
enum ndr_err_code
ndr_pull_struct_blob_all(const DATA_BLOB
*blob
, TALLOC_CTX
*mem_ctx
,
1277 void *p
, ndr_pull_flags_fn_t fn
)
1279 struct ndr_pull
*ndr
;
1280 uint32_t highest_ofs
;
1281 ndr
= ndr_pull_init_blob(blob
, mem_ctx
);
1282 NDR_ERR_HAVE_NO_MEMORY(ndr
);
1283 NDR_CHECK_FREE(fn(ndr
, NDR_SCALARS
|NDR_BUFFERS
, p
));
1284 if (ndr
->offset
> ndr
->relative_highest_offset
) {
1285 highest_ofs
= ndr
->offset
;
1287 highest_ofs
= ndr
->relative_highest_offset
;
1289 if (highest_ofs
< ndr
->data_size
) {
1290 enum ndr_err_code ret
;
1291 ret
= ndr_pull_error(ndr
, NDR_ERR_UNREAD_BYTES
,
1292 "not all bytes consumed ofs[%u] size[%u]",
1293 highest_ofs
, ndr
->data_size
);
1298 return NDR_ERR_SUCCESS
;
1302 pull a struct from a blob using NDR - failing if all bytes are not consumed
1304 This only works for structures with NO allocated memory, like
1305 objectSID and GUID. This helps because we parse these a lot.
1307 _PUBLIC_
enum ndr_err_code
ndr_pull_struct_blob_all_noalloc(const DATA_BLOB
*blob
,
1308 void *p
, ndr_pull_flags_fn_t fn
)
1311 * We init this structure on the stack here, to avoid a
1312 * talloc() as otherwise this call to the fn() is assured not
1313 * to be doing any allocation, eg SIDs and GUIDs.
1315 * This allows us to keep the safety of the PIDL-generated
1316 * code without the talloc() overhead.
1318 struct ndr_pull ndr
= {
1320 .data_size
= blob
->length
,
1321 .current_mem_ctx
= (void *)-1
1323 uint32_t highest_ofs
;
1324 NDR_CHECK(fn(&ndr
, NDR_SCALARS
|NDR_BUFFERS
, p
));
1325 highest_ofs
= MAX(ndr
.offset
, ndr
.relative_highest_offset
);
1326 if (highest_ofs
< ndr
.data_size
) {
1327 enum ndr_err_code ret
;
1328 ret
= ndr_pull_error(
1330 NDR_ERR_UNREAD_BYTES
,
1331 "not all bytes consumed ofs[%"PRIu32
"] "
1337 return NDR_ERR_SUCCESS
;
1341 pull a union from a blob using NDR, given the union discriminator
1343 _PUBLIC_
enum ndr_err_code
ndr_pull_union_blob(const DATA_BLOB
*blob
, TALLOC_CTX
*mem_ctx
,
1345 uint32_t level
, ndr_pull_flags_fn_t fn
)
1347 struct ndr_pull
*ndr
;
1348 ndr
= ndr_pull_init_blob(blob
, mem_ctx
);
1349 NDR_ERR_HAVE_NO_MEMORY(ndr
);
1350 NDR_CHECK_FREE(ndr_pull_set_switch_value(ndr
, p
, level
));
1351 NDR_CHECK_FREE(fn(ndr
, NDR_SCALARS
|NDR_BUFFERS
, p
));
1353 return NDR_ERR_SUCCESS
;
1357 pull a union from a blob using NDR, given the union discriminator,
1358 failing if all bytes are not consumed
1360 _PUBLIC_
enum ndr_err_code
ndr_pull_union_blob_all(const DATA_BLOB
*blob
, TALLOC_CTX
*mem_ctx
,
1362 uint32_t level
, ndr_pull_flags_fn_t fn
)
1364 struct ndr_pull
*ndr
;
1365 uint32_t highest_ofs
;
1366 ndr
= ndr_pull_init_blob(blob
, mem_ctx
);
1367 NDR_ERR_HAVE_NO_MEMORY(ndr
);
1368 NDR_CHECK_FREE(ndr_pull_set_switch_value(ndr
, p
, level
));
1369 NDR_CHECK_FREE(fn(ndr
, NDR_SCALARS
|NDR_BUFFERS
, p
));
1370 if (ndr
->offset
> ndr
->relative_highest_offset
) {
1371 highest_ofs
= ndr
->offset
;
1373 highest_ofs
= ndr
->relative_highest_offset
;
1375 if (highest_ofs
< ndr
->data_size
) {
1376 enum ndr_err_code ret
;
1377 ret
= ndr_pull_error(ndr
, NDR_ERR_UNREAD_BYTES
,
1378 "not all bytes consumed ofs[%u] size[%u]",
1379 highest_ofs
, ndr
->data_size
);
1384 return NDR_ERR_SUCCESS
;
1388 push a struct to a blob using NDR
1390 _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
)
1392 struct ndr_push
*ndr
;
1393 ndr
= ndr_push_init_ctx(mem_ctx
);
1394 NDR_ERR_HAVE_NO_MEMORY(ndr
);
1396 NDR_CHECK(fn(ndr
, NDR_SCALARS
|NDR_BUFFERS
, p
));
1398 *blob
= ndr_push_blob(ndr
);
1399 talloc_steal(mem_ctx
, blob
->data
);
1402 return NDR_ERR_SUCCESS
;
1406 push a struct into a provided blob using NDR.
1408 We error because we want to have the performance issue (extra
1409 talloc() calls) show up as an error, not just slower code. This is
1410 used for things like GUIDs, which we expect to be a fixed size, and
1411 SIDs that we can pre-calculate the size for.
1413 _PUBLIC_
enum ndr_err_code
ndr_push_struct_into_fixed_blob(
1414 DATA_BLOB
*blob
, const void *p
, ndr_push_flags_fn_t fn
)
1416 struct ndr_push ndr
= {
1418 .alloc_size
= blob
->length
,
1419 .fixed_buf_size
= true
1422 NDR_CHECK(fn(&ndr
, NDR_SCALARS
|NDR_BUFFERS
, p
));
1424 if (ndr
.offset
!= blob
->length
) {
1425 return ndr_push_error(&ndr
, NDR_ERR_BUFSIZE
,
1426 "buffer was either to large or small "
1427 "ofs[%u] size[%zu]",
1428 ndr
.offset
, blob
->length
);
1431 return NDR_ERR_SUCCESS
;
1435 push a union to a blob using NDR
1437 _PUBLIC_
enum ndr_err_code
ndr_push_union_blob(DATA_BLOB
*blob
, TALLOC_CTX
*mem_ctx
, void *p
,
1438 uint32_t level
, ndr_push_flags_fn_t fn
)
1440 struct ndr_push
*ndr
;
1441 ndr
= ndr_push_init_ctx(mem_ctx
);
1442 NDR_ERR_HAVE_NO_MEMORY(ndr
);
1444 NDR_CHECK(ndr_push_set_switch_value(ndr
, p
, level
));
1445 NDR_CHECK(fn(ndr
, NDR_SCALARS
|NDR_BUFFERS
, p
));
1447 *blob
= ndr_push_blob(ndr
);
1448 talloc_steal(mem_ctx
, blob
->data
);
1451 return NDR_ERR_SUCCESS
;
1455 generic ndr_size_*() handler for structures
1457 _PUBLIC_
size_t ndr_size_struct(const void *p
, int flags
, ndr_push_flags_fn_t push
)
1459 struct ndr_push
*ndr
;
1460 enum ndr_err_code status
;
1463 /* avoid recursion */
1464 if (flags
& LIBNDR_FLAG_NO_NDR_SIZE
) return 0;
1466 /* Avoid following a NULL pointer */
1471 ndr
= ndr_push_init_ctx(NULL
);
1473 ndr
->flags
|= flags
| LIBNDR_FLAG_NO_NDR_SIZE
;
1474 status
= push(ndr
, NDR_SCALARS
|NDR_BUFFERS
, discard_const(p
));
1475 if (!NDR_ERR_CODE_IS_SUCCESS(status
)) {
1485 generic ndr_size_*() handler for unions
1487 _PUBLIC_
size_t ndr_size_union(const void *p
, int flags
, uint32_t level
, ndr_push_flags_fn_t push
)
1489 struct ndr_push
*ndr
;
1490 enum ndr_err_code status
;
1493 /* avoid recursion */
1494 if (flags
& LIBNDR_FLAG_NO_NDR_SIZE
) return 0;
1496 /* Avoid following a NULL pointer */
1501 ndr
= ndr_push_init_ctx(NULL
);
1503 ndr
->flags
|= flags
| LIBNDR_FLAG_NO_NDR_SIZE
;
1505 status
= ndr_push_set_switch_value(ndr
, p
, level
);
1506 if (!NDR_ERR_CODE_IS_SUCCESS(status
)) {
1510 status
= push(ndr
, NDR_SCALARS
|NDR_BUFFERS
, p
);
1511 if (!NDR_ERR_CODE_IS_SUCCESS(status
)) {
1521 get the current base for relative pointers for the push
1523 _PUBLIC_
uint32_t ndr_push_get_relative_base_offset(struct ndr_push
*ndr
)
1525 return ndr
->relative_base_offset
;
1529 restore the old base for relative pointers for the push
1531 _PUBLIC_
void ndr_push_restore_relative_base_offset(struct ndr_push
*ndr
, uint32_t offset
)
1533 ndr
->relative_base_offset
= offset
;
1537 setup the current base for relative pointers for the push
1538 called in the NDR_SCALAR stage
1540 _PUBLIC_
enum ndr_err_code
ndr_push_setup_relative_base_offset1(struct ndr_push
*ndr
, const void *p
, uint32_t offset
)
1542 enum ndr_err_code ret
;
1543 ndr
->relative_base_offset
= offset
;
1544 ret
= ndr_token_store(ndr
, &ndr
->relative_base_list
, p
, offset
);
1545 if (ret
== NDR_ERR_RANGE
) {
1546 return ndr_push_error(ndr
, ret
,
1547 "More than %d NDR tokens stored for relative_base_list",
1548 NDR_TOKEN_MAX_LIST_SIZE
);
1554 setup the current base for relative pointers for the push
1555 called in the NDR_BUFFERS stage
1557 _PUBLIC_
enum ndr_err_code
ndr_push_setup_relative_base_offset2(struct ndr_push
*ndr
, const void *p
)
1559 return ndr_token_retrieve(&ndr
->relative_base_list
, p
, &ndr
->relative_base_offset
);
1563 push a relative object - stage1
1564 this is called during SCALARS processing
1566 _PUBLIC_
enum ndr_err_code
ndr_push_relative_ptr1(struct ndr_push
*ndr
, const void *p
)
1568 enum ndr_err_code ret
;
1570 NDR_CHECK(ndr_push_uint32(ndr
, NDR_SCALARS
, 0));
1571 return NDR_ERR_SUCCESS
;
1573 NDR_CHECK(ndr_push_align(ndr
, 4));
1574 ret
= ndr_token_store(ndr
, &ndr
->relative_list
, p
, ndr
->offset
);
1575 if (ret
== NDR_ERR_RANGE
) {
1576 return ndr_push_error(ndr
, ret
,
1577 "More than %d NDR tokens stored for relative_list",
1578 NDR_TOKEN_MAX_LIST_SIZE
);
1581 return ndr_push_uint32(ndr
, NDR_SCALARS
, 0xFFFFFFFF);
1585 push a short relative object - stage1
1586 this is called during SCALARS processing
1588 _PUBLIC_
enum ndr_err_code
ndr_push_short_relative_ptr1(struct ndr_push
*ndr
, const void *p
)
1590 enum ndr_err_code ret
;
1592 NDR_CHECK(ndr_push_uint16(ndr
, NDR_SCALARS
, 0));
1593 return NDR_ERR_SUCCESS
;
1595 NDR_CHECK(ndr_push_align(ndr
, 2));
1596 ret
= ndr_token_store(ndr
, &ndr
->relative_list
, p
, ndr
->offset
);
1597 if (ret
== NDR_ERR_RANGE
) {
1598 return ndr_push_error(ndr
, ret
,
1599 "More than %d NDR tokens stored for relative_list",
1600 NDR_TOKEN_MAX_LIST_SIZE
);
1603 return ndr_push_uint16(ndr
, NDR_SCALARS
, 0xFFFF);
1606 push a relative object - stage2
1607 this is called during buffers processing
1609 static enum ndr_err_code
ndr_push_relative_ptr2(struct ndr_push
*ndr
, const void *p
)
1611 uint32_t save_offset
;
1612 uint32_t ptr_offset
= 0xFFFFFFFF;
1614 return NDR_ERR_SUCCESS
;
1616 save_offset
= ndr
->offset
;
1617 NDR_CHECK(ndr_token_retrieve(&ndr
->relative_list
, p
, &ptr_offset
));
1618 if (ptr_offset
> ndr
->offset
) {
1619 return ndr_push_error(ndr
, NDR_ERR_BUFSIZE
,
1620 "ndr_push_relative_ptr2 ptr_offset(%u) > ndr->offset(%u)",
1621 ptr_offset
, ndr
->offset
);
1623 ndr
->offset
= ptr_offset
;
1624 if (save_offset
< ndr
->relative_base_offset
) {
1625 return ndr_push_error(ndr
, NDR_ERR_BUFSIZE
,
1626 "ndr_push_relative_ptr2 save_offset(%u) < ndr->relative_base_offset(%u)",
1627 save_offset
, ndr
->relative_base_offset
);
1629 NDR_CHECK(ndr_push_uint32(ndr
, NDR_SCALARS
, save_offset
- ndr
->relative_base_offset
));
1630 ndr
->offset
= save_offset
;
1631 return NDR_ERR_SUCCESS
;
1634 push a short relative object - stage2
1635 this is called during buffers processing
1637 _PUBLIC_
enum ndr_err_code
ndr_push_short_relative_ptr2(struct ndr_push
*ndr
, const void *p
)
1639 uint32_t save_offset
;
1640 uint32_t ptr_offset
= 0xFFFF;
1641 uint32_t relative_offset
;
1646 return NDR_ERR_SUCCESS
;
1649 if (ndr
->offset
< ndr
->relative_base_offset
) {
1650 return ndr_push_error(ndr
, NDR_ERR_BUFSIZE
,
1651 "ndr_push_relative_ptr2 ndr->offset(%u) < ndr->relative_base_offset(%u)",
1652 ndr
->offset
, ndr
->relative_base_offset
);
1655 relative_offset
= ndr
->offset
- ndr
->relative_base_offset
;
1657 if (ndr
->flags
& LIBNDR_FLAG_NOALIGN
) {
1659 } else if (ndr
->flags
& LIBNDR_FLAG_ALIGN2
) {
1661 } else if (ndr
->flags
& LIBNDR_FLAG_ALIGN4
) {
1663 } else if (ndr
->flags
& LIBNDR_FLAG_ALIGN8
) {
1667 pad
= ndr_align_size(relative_offset
, align
);
1669 NDR_CHECK(ndr_push_zero(ndr
, pad
));
1672 relative_offset
= ndr
->offset
- ndr
->relative_base_offset
;
1673 if (relative_offset
> UINT16_MAX
) {
1674 return ndr_push_error(ndr
, NDR_ERR_BUFSIZE
,
1675 "ndr_push_relative_ptr2 relative_offset(%u) > UINT16_MAX",
1679 save_offset
= ndr
->offset
;
1680 NDR_CHECK(ndr_token_retrieve(&ndr
->relative_list
, p
, &ptr_offset
));
1681 if (ptr_offset
> ndr
->offset
) {
1682 return ndr_push_error(ndr
, NDR_ERR_BUFSIZE
,
1683 "ndr_push_short_relative_ptr2 ptr_offset(%u) > ndr->offset(%u)",
1684 ptr_offset
, ndr
->offset
);
1686 ndr
->offset
= ptr_offset
;
1687 NDR_CHECK(ndr_push_uint16(ndr
, NDR_SCALARS
, relative_offset
));
1688 ndr
->offset
= save_offset
;
1689 return NDR_ERR_SUCCESS
;
1693 push a relative object - stage2 start
1694 this is called during buffers processing
1696 _PUBLIC_
enum ndr_err_code
ndr_push_relative_ptr2_start(struct ndr_push
*ndr
, const void *p
)
1698 enum ndr_err_code ret
;
1700 return NDR_ERR_SUCCESS
;
1702 if (!(ndr
->flags
& LIBNDR_FLAG_RELATIVE_REVERSE
)) {
1703 uint32_t relative_offset
;
1707 if (ndr
->offset
< ndr
->relative_base_offset
) {
1708 return ndr_push_error(ndr
, NDR_ERR_BUFSIZE
,
1709 "ndr_push_relative_ptr2_start ndr->offset(%u) < ndr->relative_base_offset(%u)",
1710 ndr
->offset
, ndr
->relative_base_offset
);
1713 relative_offset
= ndr
->offset
- ndr
->relative_base_offset
;
1715 if (ndr
->flags
& LIBNDR_FLAG_NOALIGN
) {
1717 } else if (ndr
->flags
& LIBNDR_FLAG_ALIGN2
) {
1719 } else if (ndr
->flags
& LIBNDR_FLAG_ALIGN4
) {
1721 } else if (ndr
->flags
& LIBNDR_FLAG_ALIGN8
) {
1725 pad
= ndr_align_size(relative_offset
, align
);
1727 NDR_CHECK(ndr_push_zero(ndr
, pad
));
1730 return ndr_push_relative_ptr2(ndr
, p
);
1732 if (ndr
->relative_end_offset
== -1) {
1733 return ndr_push_error(ndr
, NDR_ERR_RELATIVE
,
1734 "ndr_push_relative_ptr2_start RELATIVE_REVERSE flag set and relative_end_offset %d",
1735 ndr
->relative_end_offset
);
1737 ret
= ndr_token_store(ndr
,
1738 &ndr
->relative_begin_list
,
1741 if (ret
== NDR_ERR_RANGE
) {
1742 return ndr_push_error(ndr
, ret
,
1743 "More than %d NDR tokens stored for array_size",
1744 NDR_TOKEN_MAX_LIST_SIZE
);
1750 push a relative object - stage2 end
1751 this is called during buffers processing
1753 _PUBLIC_
enum ndr_err_code
ndr_push_relative_ptr2_end(struct ndr_push
*ndr
, const void *p
)
1755 uint32_t begin_offset
= 0xFFFFFFFF;
1757 uint32_t correct_offset
= 0;
1762 return NDR_ERR_SUCCESS
;
1765 if (!(ndr
->flags
& LIBNDR_FLAG_RELATIVE_REVERSE
)) {
1766 return NDR_ERR_SUCCESS
;
1769 if (ndr
->flags
& LIBNDR_FLAG_NO_NDR_SIZE
) {
1770 /* better say more than calculation a too small buffer */
1771 NDR_PUSH_ALIGN(ndr
, 8);
1772 return NDR_ERR_SUCCESS
;
1775 if (ndr
->relative_end_offset
< ndr
->offset
) {
1776 return ndr_push_error(ndr
, NDR_ERR_RELATIVE
,
1777 "ndr_push_relative_ptr2_end:"
1778 "relative_end_offset %u < offset %u",
1779 ndr
->relative_end_offset
, ndr
->offset
);
1782 NDR_CHECK(ndr_token_retrieve(&ndr
->relative_begin_list
, p
, &begin_offset
));
1784 /* we have marshalled a buffer, see how long it was */
1785 len
= ndr
->offset
- begin_offset
;
1788 return ndr_push_error(ndr
, NDR_ERR_RELATIVE
,
1789 "ndr_push_relative_ptr2_end:"
1790 "offset %u - begin_offset %u < 0",
1791 ndr
->offset
, begin_offset
);
1794 if (ndr
->relative_end_offset
< len
) {
1795 return ndr_push_error(ndr
, NDR_ERR_RELATIVE
,
1796 "ndr_push_relative_ptr2_end:"
1797 "relative_end_offset %u < len %lld",
1798 ndr
->offset
, (long long)len
);
1801 /* the reversed offset is at the end of the main buffer */
1802 correct_offset
= ndr
->relative_end_offset
- len
;
1804 if (ndr
->flags
& LIBNDR_FLAG_NOALIGN
) {
1806 } else if (ndr
->flags
& LIBNDR_FLAG_ALIGN2
) {
1808 } else if (ndr
->flags
& LIBNDR_FLAG_ALIGN4
) {
1810 } else if (ndr
->flags
& LIBNDR_FLAG_ALIGN8
) {
1814 pad
= ndr_align_size(correct_offset
, align
);
1816 correct_offset
+= pad
;
1817 correct_offset
-= align
;
1820 if (correct_offset
< begin_offset
) {
1821 return ndr_push_error(ndr
, NDR_ERR_RELATIVE
,
1822 "ndr_push_relative_ptr2_end: "
1823 "correct_offset %u < begin_offset %u",
1824 correct_offset
, begin_offset
);
1828 uint32_t clear_size
= correct_offset
- begin_offset
;
1830 clear_size
= MIN(clear_size
, len
);
1832 /* now move the marshalled buffer to the end of the main buffer */
1833 memmove(ndr
->data
+ correct_offset
, ndr
->data
+ begin_offset
, len
);
1836 /* and wipe out old buffer within the main buffer */
1837 memset(ndr
->data
+ begin_offset
, '\0', clear_size
);
1841 /* and set the end offset for the next buffer */
1842 ndr
->relative_end_offset
= correct_offset
;
1844 /* finally write the offset to the main buffer */
1845 ndr
->offset
= correct_offset
;
1846 NDR_CHECK(ndr_push_relative_ptr2(ndr
, p
));
1848 /* restore to where we were in the main buffer */
1849 ndr
->offset
= begin_offset
;
1851 return NDR_ERR_SUCCESS
;
1855 get the current base for relative pointers for the pull
1857 _PUBLIC_
uint32_t ndr_pull_get_relative_base_offset(struct ndr_pull
*ndr
)
1859 return ndr
->relative_base_offset
;
1863 restore the old base for relative pointers for the pull
1865 _PUBLIC_
void ndr_pull_restore_relative_base_offset(struct ndr_pull
*ndr
, uint32_t offset
)
1867 ndr
->relative_base_offset
= offset
;
1871 setup the current base for relative pointers for the pull
1872 called in the NDR_SCALAR stage
1874 _PUBLIC_
enum ndr_err_code
ndr_pull_setup_relative_base_offset1(struct ndr_pull
*ndr
, const void *p
, uint32_t offset
)
1876 enum ndr_err_code ret
;
1877 ndr
->relative_base_offset
= offset
;
1878 ret
= ndr_token_store(ndr
, &ndr
->relative_base_list
, p
, offset
);
1879 if (ret
== NDR_ERR_RANGE
) {
1880 return ndr_pull_error(ndr
, ret
,
1881 "More than %d NDR tokens stored for relative_base_list",
1882 NDR_TOKEN_MAX_LIST_SIZE
);
1888 setup the current base for relative pointers for the pull
1889 called in the NDR_BUFFERS stage
1891 _PUBLIC_
enum ndr_err_code
ndr_pull_setup_relative_base_offset2(struct ndr_pull
*ndr
, const void *p
)
1893 return ndr_token_retrieve(&ndr
->relative_base_list
, p
, &ndr
->relative_base_offset
);
1897 pull a relative object - stage1
1898 called during SCALARS processing
1900 _PUBLIC_
enum ndr_err_code
ndr_pull_relative_ptr1(struct ndr_pull
*ndr
, const void *p
, uint32_t rel_offset
)
1902 enum ndr_err_code ret
;
1903 rel_offset
+= ndr
->relative_base_offset
;
1904 if (rel_offset
> ndr
->data_size
) {
1905 return ndr_pull_error(ndr
, NDR_ERR_BUFSIZE
,
1906 "ndr_pull_relative_ptr1 rel_offset(%u) > ndr->data_size(%u)",
1907 rel_offset
, ndr
->data_size
);
1909 ret
= ndr_token_store(ndr
, &ndr
->relative_list
, p
, rel_offset
);
1910 if (ret
== NDR_ERR_RANGE
) {
1911 return ndr_pull_error(ndr
, ret
,
1912 "More than %d NDR tokens stored for relative_list",
1913 NDR_TOKEN_MAX_LIST_SIZE
);
1919 pull a relative object - stage2
1920 called during BUFFERS processing
1922 _PUBLIC_
enum ndr_err_code
ndr_pull_relative_ptr2(struct ndr_pull
*ndr
, const void *p
)
1924 uint32_t rel_offset
;
1925 NDR_CHECK(ndr_token_retrieve(&ndr
->relative_list
, p
, &rel_offset
));
1926 return ndr_pull_set_offset(ndr
, rel_offset
);
1929 static const struct {
1930 enum ndr_err_code err
;
1932 } ndr_err_code_strings
[] = {
1933 { NDR_ERR_SUCCESS
, "Success" },
1934 { NDR_ERR_ARRAY_SIZE
, "Bad Array Size" },
1935 { NDR_ERR_BAD_SWITCH
, "Bad Switch" },
1936 { NDR_ERR_OFFSET
, "Offset Error" },
1937 { NDR_ERR_RELATIVE
, "Relative Pointer Error" },
1938 { NDR_ERR_CHARCNV
, "Character Conversion Error" },
1939 { NDR_ERR_LENGTH
, "Length Error" },
1940 { NDR_ERR_SUBCONTEXT
, "Subcontext Error" },
1941 { NDR_ERR_COMPRESSION
, "Compression Error" },
1942 { NDR_ERR_STRING
, "String Error" },
1943 { NDR_ERR_VALIDATE
, "Validate Error" },
1944 { NDR_ERR_BUFSIZE
, "Buffer Size Error" },
1945 { NDR_ERR_ALLOC
, "Allocation Error" },
1946 { NDR_ERR_RANGE
, "Range Error" },
1947 { NDR_ERR_TOKEN
, "Token Error" },
1948 { NDR_ERR_IPV4ADDRESS
, "IPv4 Address Error" },
1949 { NDR_ERR_INVALID_POINTER
, "Invalid Pointer" },
1950 { NDR_ERR_UNREAD_BYTES
, "Unread Bytes" },
1951 { NDR_ERR_NDR64
, "NDR64 assertion error" },
1952 { NDR_ERR_INCOMPLETE_BUFFER
, "Incomplete Buffer" },
1953 { NDR_ERR_MAX_RECURSION_EXCEEDED
, "Maximum Recursion Exceeded" },
1954 { NDR_ERR_UNDERFLOW
, "Underflow" },
1958 _PUBLIC_
const char *ndr_map_error2string(enum ndr_err_code ndr_err
)
1961 for (i
= 0; ndr_err_code_strings
[i
].string
!= NULL
; i
++) {
1962 if (ndr_err_code_strings
[i
].err
== ndr_err
)
1963 return ndr_err_code_strings
[i
].string
;
1965 return "Unknown error";