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 %u 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 %u",
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 "
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 %u",
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
;
443 DEBUGLF(level
, (" "), location
, function
);
445 ndr
= talloc_zero(NULL
, struct ndr_print
);
446 if (!ndr
) return false;
447 ndr
->print
= ndr_print_debug_helper
;
450 #ifdef DEBUG_PASSWORD
451 if (CHECK_DEBUGLVL(100)) {
452 ndr
->print_secrets
= true;
462 a useful helper function for printing idl unions via DEBUG()
464 _PUBLIC_
void ndr_print_union_debug(ndr_print_fn_t fn
, const char *name
, uint32_t level
, void *ptr
)
466 struct ndr_print
*ndr
;
470 ndr
= talloc_zero(NULL
, struct ndr_print
);
472 ndr
->print
= ndr_print_debug_helper
;
475 #ifdef DEBUG_PASSWORD
476 if (CHECK_DEBUGLVL(100)) {
477 ndr
->print_secrets
= true;
481 ndr_print_set_switch_value(ndr
, ptr
, level
);
487 a useful helper function for printing idl function calls via DEBUG()
489 _PUBLIC_
void ndr_print_function_debug(ndr_print_function_t fn
, const char *name
, int flags
, void *ptr
)
491 struct ndr_print
*ndr
;
495 ndr
= talloc_zero(NULL
, struct ndr_print
);
497 ndr
->print
= ndr_print_debug_helper
;
500 #ifdef DEBUG_PASSWORD
501 if (CHECK_DEBUGLVL(100)) {
502 ndr
->print_secrets
= true;
506 fn(ndr
, name
, flags
, ptr
);
511 a useful helper function for printing idl structures to a string
513 _PUBLIC_
char *ndr_print_struct_string(TALLOC_CTX
*mem_ctx
, ndr_print_fn_t fn
, const char *name
, void *ptr
)
515 struct ndr_print
*ndr
;
518 ndr
= talloc_zero(mem_ctx
, struct ndr_print
);
519 if (!ndr
) return NULL
;
520 ndr
->private_data
= talloc_strdup(ndr
, "");
521 if (!ndr
->private_data
) {
524 ndr
->print
= ndr_print_string_helper
;
529 ret
= talloc_steal(mem_ctx
, (char *)ndr
->private_data
);
536 a useful helper function for printing idl unions to a string
538 _PUBLIC_
char *ndr_print_union_string(TALLOC_CTX
*mem_ctx
, ndr_print_fn_t fn
, const char *name
, uint32_t level
, void *ptr
)
540 struct ndr_print
*ndr
;
543 ndr
= talloc_zero(mem_ctx
, struct ndr_print
);
544 if (!ndr
) return NULL
;
545 ndr
->private_data
= talloc_strdup(ndr
, "");
546 if (!ndr
->private_data
) {
549 ndr
->print
= ndr_print_string_helper
;
552 ndr_print_set_switch_value(ndr
, ptr
, level
);
554 ret
= talloc_steal(mem_ctx
, (char *)ndr
->private_data
);
561 a useful helper function for printing idl function calls to a string
563 _PUBLIC_
char *ndr_print_function_string(TALLOC_CTX
*mem_ctx
,
564 ndr_print_function_t fn
, const char *name
,
565 int flags
, void *ptr
)
567 struct ndr_print
*ndr
;
570 ndr
= talloc_zero(mem_ctx
, struct ndr_print
);
571 if (!ndr
) return NULL
;
572 ndr
->private_data
= talloc_strdup(ndr
, "");
573 if (!ndr
->private_data
) {
576 ndr
->print
= ndr_print_string_helper
;
579 fn(ndr
, name
, flags
, ptr
);
580 ret
= talloc_steal(mem_ctx
, (char *)ndr
->private_data
);
586 _PUBLIC_
void ndr_set_flags(uint32_t *pflags
, uint32_t new_flags
)
588 /* the big/little endian flags are inter-dependent */
589 if (new_flags
& LIBNDR_FLAG_LITTLE_ENDIAN
) {
590 (*pflags
) &= ~LIBNDR_FLAG_BIGENDIAN
;
591 (*pflags
) &= ~LIBNDR_FLAG_NDR64
;
593 if (new_flags
& LIBNDR_FLAG_BIGENDIAN
) {
594 (*pflags
) &= ~LIBNDR_FLAG_LITTLE_ENDIAN
;
595 (*pflags
) &= ~LIBNDR_FLAG_NDR64
;
597 if (new_flags
& LIBNDR_ALIGN_FLAGS
) {
598 /* Ensure we only have the passed-in
599 align flag set in the new_flags,
600 remove any old align flag. */
601 (*pflags
) &= ~LIBNDR_ALIGN_FLAGS
;
603 if (new_flags
& LIBNDR_FLAG_NO_RELATIVE_REVERSE
) {
604 (*pflags
) &= ~LIBNDR_FLAG_RELATIVE_REVERSE
;
606 (*pflags
) |= new_flags
;
610 return and possibly log an NDR error
612 _PUBLIC_
enum ndr_err_code
_ndr_pull_error(struct ndr_pull
*ndr
,
613 enum ndr_err_code ndr_err
,
614 const char *function
,
615 const char *location
,
616 const char *format
, ...)
622 if (ndr
->flags
& LIBNDR_FLAG_INCOMPLETE_BUFFER
) {
624 case NDR_ERR_BUFSIZE
:
625 return NDR_ERR_INCOMPLETE_BUFFER
;
631 va_start(ap
, format
);
632 ret
= vasprintf(&s
, format
, ap
);
636 return NDR_ERR_ALLOC
;
639 D_WARNING("%s: ndr_pull_error(%s): %s at %s\n",
641 ndr_map_error2string(ndr_err
),
651 return and possibly log an NDR error
653 _PUBLIC_
enum ndr_err_code
_ndr_push_error(struct ndr_push
*ndr
,
654 enum ndr_err_code ndr_err
,
655 const char *function
,
656 const char *location
,
657 const char *format
, ...)
663 va_start(ap
, format
);
664 ret
= vasprintf(&s
, format
, ap
);
668 return NDR_ERR_ALLOC
;
671 D_WARNING("%s: ndr_push_error(%s): %s at %s\n",
673 ndr_map_error2string(ndr_err
),
683 handle subcontext buffers, which in midl land are user-marshalled, but
684 we use magic in pidl to make them easier to cope with
686 _PUBLIC_
enum ndr_err_code
ndr_pull_subcontext_start(struct ndr_pull
*ndr
,
687 struct ndr_pull
**_subndr
,
691 struct ndr_pull
*subndr
;
692 uint32_t r_content_size
;
693 bool force_le
= false;
694 bool force_be
= false;
696 switch (header_size
) {
698 uint32_t content_size
= ndr
->data_size
- ndr
->offset
;
700 content_size
= size_is
;
702 r_content_size
= content_size
;
707 uint16_t content_size
;
708 NDR_CHECK(ndr_pull_uint16(ndr
, NDR_SCALARS
, &content_size
));
709 if (size_is
>= 0 && size_is
!= content_size
) {
710 return ndr_pull_error(ndr
, NDR_ERR_SUBCONTEXT
, "Bad subcontext (PULL) size_is(%d) (0x%04x) mismatch content_size %d (0x%04x)",
711 (int)size_is
, (int)size_is
,
715 r_content_size
= content_size
;
720 uint32_t content_size
;
721 NDR_CHECK(ndr_pull_uint3264(ndr
, NDR_SCALARS
, &content_size
));
722 if (size_is
>= 0 && size_is
!= content_size
) {
723 return ndr_pull_error(ndr
, NDR_ERR_SUBCONTEXT
, "Bad subcontext (PULL) size_is(%d) (0x%08x) mismatch content_size %d (0x%08x)",
724 (int)size_is
, (int)size_is
,
728 r_content_size
= content_size
;
733 * Common Type Header for the Serialization Stream
734 * See [MS-RPCE] 2.2.6 Type Serialization Version 1
740 uint32_t content_size
;
744 NDR_CHECK(ndr_pull_uint8(ndr
, NDR_SCALARS
, &version
));
747 return ndr_pull_error(ndr
, NDR_ERR_SUBCONTEXT
,
748 "Bad subcontext (PULL) Common Type Header version %d != 1",
756 NDR_CHECK(ndr_pull_uint8(ndr
, NDR_SCALARS
, &drep
));
759 } else if (drep
== 0x00) {
762 return ndr_pull_error(ndr
, NDR_ERR_SUBCONTEXT
,
763 "Bad subcontext (PULL) Common Type Header invalid drep 0x%02X",
767 /* length of the "Private Header for Constructed Type" */
768 NDR_CHECK(ndr_pull_uint16(ndr
, NDR_SCALARS
, &hdrlen
));
770 return ndr_pull_error(ndr
, NDR_ERR_SUBCONTEXT
,
771 "Bad subcontext (PULL) Common Type Header length %d != 8",
775 /* filler should be ignored */
776 NDR_CHECK(ndr_pull_uint32(ndr
, NDR_SCALARS
, &filler
));
779 * Private Header for Constructed Type
781 /* length - will be updated latter */
782 NDR_CHECK(ndr_pull_uint32(ndr
, NDR_SCALARS
, &content_size
));
783 if (size_is
>= 0 && size_is
!= content_size
) {
784 return ndr_pull_error(ndr
, NDR_ERR_SUBCONTEXT
, "Bad subcontext (PULL) size_is(%d) mismatch content_size %d",
785 (int)size_is
, (int)content_size
);
787 /* the content size must be a multiple of 8 */
788 if ((content_size
% 8) != 0) {
789 return ndr_pull_error(ndr
, NDR_ERR_SUBCONTEXT
,
790 "Bad subcontext (PULL) size_is(%d) not padded to 8 content_size %d",
791 (int)size_is
, (int)content_size
);
793 r_content_size
= content_size
;
796 NDR_CHECK(ndr_pull_uint32(ndr
, NDR_SCALARS
, &reserved
));
801 * a shallow copy like subcontext
802 * useful for DCERPC pipe chunks.
804 subndr
= talloc_zero(ndr
, struct ndr_pull
);
805 NDR_ERR_HAVE_NO_MEMORY(subndr
);
807 subndr
->flags
= ndr
->flags
;
808 subndr
->current_mem_ctx
= ndr
->current_mem_ctx
;
809 subndr
->data
= ndr
->data
;
810 subndr
->offset
= ndr
->offset
;
811 subndr
->data_size
= ndr
->data_size
;
814 return NDR_ERR_SUCCESS
;
817 return ndr_pull_error(ndr
, NDR_ERR_SUBCONTEXT
, "Bad subcontext (PULL) header_size %d",
821 NDR_PULL_NEED_BYTES(ndr
, r_content_size
);
823 subndr
= talloc_zero(ndr
, struct ndr_pull
);
824 NDR_ERR_HAVE_NO_MEMORY(subndr
);
825 subndr
->flags
= ndr
->flags
& ~LIBNDR_FLAG_NDR64
;
826 subndr
->current_mem_ctx
= ndr
->current_mem_ctx
;
828 subndr
->data
= ndr
->data
+ ndr
->offset
;
830 subndr
->data_size
= r_content_size
;
833 ndr_set_flags(&ndr
->flags
, LIBNDR_FLAG_LITTLE_ENDIAN
);
834 } else if (force_be
) {
835 ndr_set_flags(&ndr
->flags
, LIBNDR_FLAG_BIGENDIAN
);
839 return NDR_ERR_SUCCESS
;
842 _PUBLIC_
enum ndr_err_code
ndr_pull_subcontext_end(struct ndr_pull
*ndr
,
843 struct ndr_pull
*subndr
,
848 uint32_t highest_ofs
;
850 if (header_size
== 0xFFFFFFFF) {
851 advance
= subndr
->offset
- ndr
->offset
;
852 } else if (size_is
>= 0) {
854 } else if (header_size
> 0) {
855 advance
= subndr
->data_size
;
857 advance
= subndr
->offset
;
860 if (subndr
->offset
> ndr
->relative_highest_offset
) {
861 highest_ofs
= subndr
->offset
;
863 highest_ofs
= subndr
->relative_highest_offset
;
865 if (!(subndr
->flags
& LIBNDR_FLAG_SUBCONTEXT_NO_UNREAD_BYTES
)) {
867 * avoid an error unless SUBCONTEXT_NO_UNREAD_BYTES is specified
869 highest_ofs
= advance
;
871 if (highest_ofs
< advance
) {
872 return ndr_pull_error(subndr
, NDR_ERR_UNREAD_BYTES
,
873 "not all bytes consumed ofs[%u] advance[%u]",
874 highest_ofs
, advance
);
877 NDR_CHECK(ndr_pull_advance(ndr
, advance
));
878 return NDR_ERR_SUCCESS
;
881 _PUBLIC_
enum ndr_err_code
ndr_push_subcontext_start(struct ndr_push
*ndr
,
882 struct ndr_push
**_subndr
,
886 struct ndr_push
*subndr
;
888 subndr
= ndr_push_init_ctx(ndr
);
889 NDR_ERR_HAVE_NO_MEMORY(subndr
);
890 subndr
->flags
= ndr
->flags
& ~LIBNDR_FLAG_NDR64
;
893 NDR_CHECK(ndr_push_zero(subndr
, size_is
));
895 subndr
->relative_end_offset
= size_is
;
899 return NDR_ERR_SUCCESS
;
903 push a subcontext header
905 _PUBLIC_
enum ndr_err_code
ndr_push_subcontext_end(struct ndr_push
*ndr
,
906 struct ndr_push
*subndr
,
913 padding_len
= size_is
- subndr
->offset
;
914 if (padding_len
< 0) {
915 return ndr_push_error(ndr
, NDR_ERR_SUBCONTEXT
, "Bad subcontext (PUSH) content_size %d is larger than size_is(%d)",
916 (int)subndr
->offset
, (int)size_is
);
918 subndr
->offset
= size_is
;
921 switch (header_size
) {
926 NDR_CHECK(ndr_push_uint16(ndr
, NDR_SCALARS
, subndr
->offset
));
930 NDR_CHECK(ndr_push_uint3264(ndr
, NDR_SCALARS
, subndr
->offset
));
935 * Common Type Header for the Serialization Stream
936 * See [MS-RPCE] 2.2.6 Type Serialization Version 1
938 padding_len
= NDR_ROUND(subndr
->offset
, 8) - subndr
->offset
;
939 if (padding_len
> 0) {
940 NDR_CHECK(ndr_push_zero(subndr
, padding_len
));
944 NDR_CHECK(ndr_push_uint8(ndr
, NDR_SCALARS
, 1));
950 NDR_CHECK(ndr_push_uint8(ndr
, NDR_SCALARS
, NDR_BE(ndr
)?0x00:0x10));
952 /* length of the "Private Header for Constructed Type" */
953 NDR_CHECK(ndr_push_uint16(ndr
, NDR_SCALARS
, 8));
956 NDR_CHECK(ndr_push_uint32(ndr
, NDR_SCALARS
, 0xCCCCCCCC));
959 * Private Header for Constructed Type
961 /* length - will be updated latter */
962 NDR_CHECK(ndr_push_uint32(ndr
, NDR_SCALARS
, subndr
->offset
));
965 NDR_CHECK(ndr_push_uint32(ndr
, NDR_SCALARS
, 0));
969 return ndr_push_error(ndr
, NDR_ERR_SUBCONTEXT
, "Bad subcontext header size %d",
973 NDR_CHECK(ndr_push_bytes(ndr
, subndr
->data
, subndr
->offset
));
974 return NDR_ERR_SUCCESS
;
984 store a token in the ndr context, for later retrieval
986 _PUBLIC_
enum ndr_err_code
ndr_token_store(TALLOC_CTX
*mem_ctx
,
987 struct ndr_token_list
*list
,
991 if (list
->tokens
== NULL
) {
992 list
->tokens
= talloc_array(mem_ctx
, struct ndr_token
, 10);
993 if (list
->tokens
== NULL
) {
994 NDR_ERR_HAVE_NO_MEMORY(list
->tokens
);
997 struct ndr_token
*new_tokens
= NULL
;
998 uint32_t alloc_count
= talloc_array_length(list
->tokens
);
1001 * Check every time we have not allocated too many
1002 * tokens. This ensures developer sanity when
1003 * debugging the boundary condition
1005 if (list
->count
>= NDR_TOKEN_MAX_LIST_SIZE
) {
1006 return NDR_ERR_RANGE
;
1008 if (list
->count
== alloc_count
) {
1011 * Double the list, until we start in chunks
1014 unsigned increment
= MIN(list
->count
, 1000);
1015 new_alloc
= alloc_count
+ increment
;
1016 if (new_alloc
< alloc_count
) {
1017 return NDR_ERR_RANGE
;
1019 new_tokens
= talloc_realloc(mem_ctx
, list
->tokens
,
1020 struct ndr_token
, new_alloc
);
1021 NDR_ERR_HAVE_NO_MEMORY(new_tokens
);
1022 list
->tokens
= new_tokens
;
1025 list
->tokens
[list
->count
].key
= key
;
1026 list
->tokens
[list
->count
].value
= value
;
1028 return NDR_ERR_SUCCESS
;
1032 retrieve a token from a ndr context, using cmp_fn to match the tokens
1034 _PUBLIC_
enum ndr_err_code
ndr_token_retrieve_cmp_fn(struct ndr_token_list
*list
,
1035 const void *key
, uint32_t *v
,
1036 comparison_fn_t _cmp_fn
,
1039 struct ndr_token
*tokens
= list
->tokens
;
1042 for (i
= list
->count
- 1; i
< list
->count
; i
--) {
1043 if (_cmp_fn(tokens
[i
].key
, key
) == 0) {
1048 for (i
= list
->count
- 1; i
< list
->count
; i
--) {
1049 if (tokens
[i
].key
== key
) {
1054 return NDR_ERR_TOKEN
;
1056 *v
= tokens
[i
].value
;
1058 if (i
!= list
->count
- 1) {
1059 tokens
[i
] = tokens
[list
->count
- 1];
1063 return NDR_ERR_SUCCESS
;
1067 retrieve a token from a ndr context
1069 _PUBLIC_
enum ndr_err_code
ndr_token_retrieve(struct ndr_token_list
*list
,
1070 const void *key
, uint32_t *v
)
1072 return ndr_token_retrieve_cmp_fn(list
, key
, v
, NULL
, true);
1076 peek at but don't removed a token from a ndr context
1078 _PUBLIC_
enum ndr_err_code
ndr_token_peek(struct ndr_token_list
*list
,
1079 const void *key
, uint32_t *v
)
1081 return ndr_token_retrieve_cmp_fn(list
, key
, v
, NULL
, false);
1085 pull an array size field and add it to the array_size_list token list
1087 _PUBLIC_
enum ndr_err_code
ndr_pull_array_size(struct ndr_pull
*ndr
, const void *p
)
1089 enum ndr_err_code ret
;
1091 NDR_CHECK(ndr_pull_uint3264(ndr
, NDR_SCALARS
, &size
));
1092 ret
= ndr_token_store(ndr
, &ndr
->array_size_list
, p
, size
);
1093 if (ret
== NDR_ERR_RANGE
) {
1094 return ndr_pull_error(ndr
, ret
,
1095 "More than %d NDR tokens stored for array_size",
1096 NDR_TOKEN_MAX_LIST_SIZE
);
1102 get the stored array size field
1104 _PUBLIC_
enum ndr_err_code
ndr_get_array_size(struct ndr_pull
*ndr
, const void *p
, uint32_t *size
)
1106 return ndr_token_peek(&ndr
->array_size_list
, p
, size
);
1110 get and remove from the stored list the stored array size field
1112 _PUBLIC_
enum ndr_err_code
ndr_steal_array_size(struct ndr_pull
*ndr
, const void *p
, uint32_t *size
)
1114 return ndr_token_retrieve(&ndr
->array_size_list
, p
, size
);
1118 * check the stored array size field and remove from the stored list
1119 * (the array_size NDR token list). We try to remove when possible to
1120 * avoid the list growing towards the bounds check
1122 _PUBLIC_
enum ndr_err_code
ndr_check_steal_array_size(struct ndr_pull
*ndr
, const void *p
, uint32_t size
)
1125 NDR_CHECK(ndr_steal_array_size(ndr
, p
, &stored
));
1126 if (stored
!= size
) {
1127 return ndr_pull_error(ndr
, NDR_ERR_ARRAY_SIZE
,
1128 "Bad array size - got %u expected %u\n",
1131 return NDR_ERR_SUCCESS
;
1135 * check the stored array size field (leaving it on the array_size
1138 _PUBLIC_
enum ndr_err_code
ndr_check_array_size(struct ndr_pull
*ndr
, const void *p
, uint32_t size
)
1141 NDR_CHECK(ndr_get_array_size(ndr
, p
, &stored
));
1142 if (stored
!= size
) {
1143 return ndr_pull_error(ndr
, NDR_ERR_ARRAY_SIZE
,
1144 "Bad array size - got %u expected %u\n",
1147 return NDR_ERR_SUCCESS
;
1151 pull an array length field and add it to the array_length_list token list
1153 _PUBLIC_
enum ndr_err_code
ndr_pull_array_length(struct ndr_pull
*ndr
, const void *p
)
1155 enum ndr_err_code ret
;
1156 uint32_t length
, offset
;
1157 NDR_CHECK(ndr_pull_uint3264(ndr
, NDR_SCALARS
, &offset
));
1159 return ndr_pull_error(ndr
, NDR_ERR_ARRAY_SIZE
,
1160 "non-zero array offset %u\n", offset
);
1162 NDR_CHECK(ndr_pull_uint3264(ndr
, NDR_SCALARS
, &length
));
1163 ret
= ndr_token_store(ndr
, &ndr
->array_length_list
, p
, length
);
1164 if (ret
== NDR_ERR_RANGE
) {
1165 return ndr_pull_error(ndr
, ret
,
1166 "More than %d NDR tokens stored for array_length_list",
1167 NDR_TOKEN_MAX_LIST_SIZE
);
1173 get the stored array length field
1175 _PUBLIC_
enum ndr_err_code
ndr_get_array_length(struct ndr_pull
*ndr
, const void *p
, uint32_t *length
)
1177 return ndr_token_peek(&ndr
->array_length_list
, p
, length
);
1181 * check the stored array length field and remove from the stored list
1182 * (the array_size NDR token list). We try to remove when possible to
1183 * avoid the list growing towards the bounds check
1185 _PUBLIC_
enum ndr_err_code
ndr_steal_array_length(struct ndr_pull
*ndr
, const void *p
, uint32_t *length
)
1187 return ndr_token_retrieve(&ndr
->array_length_list
, p
, length
);
1190 check the stored array length field, removing it from the list
1192 _PUBLIC_
enum ndr_err_code
ndr_check_steal_array_length(struct ndr_pull
*ndr
, const void *p
, uint32_t length
)
1195 NDR_CHECK(ndr_steal_array_length(ndr
, p
, &stored
));
1196 if (stored
!= length
) {
1197 return ndr_pull_error(ndr
, NDR_ERR_ARRAY_SIZE
,
1198 "Bad array length - got %u expected %u\n",
1201 return NDR_ERR_SUCCESS
;
1204 _PUBLIC_
enum ndr_err_code
ndr_push_pipe_chunk_trailer(struct ndr_push
*ndr
, int ndr_flags
, uint32_t count
)
1206 if (ndr
->flags
& LIBNDR_FLAG_NDR64
) {
1207 int64_t tmp
= 0 - (int64_t)count
;
1208 uint64_t ncount
= tmp
;
1210 NDR_CHECK(ndr_push_hyper(ndr
, ndr_flags
, ncount
));
1213 return NDR_ERR_SUCCESS
;
1216 _PUBLIC_
enum ndr_err_code
ndr_check_pipe_chunk_trailer(struct ndr_pull
*ndr
, int ndr_flags
, uint32_t count
)
1218 if (ndr
->flags
& LIBNDR_FLAG_NDR64
) {
1219 int64_t tmp
= 0 - (int64_t)count
;
1220 uint64_t ncount1
= tmp
;
1223 NDR_CHECK(ndr_pull_hyper(ndr
, ndr_flags
, &ncount2
));
1224 if (ncount1
== ncount2
) {
1225 return NDR_ERR_SUCCESS
;
1228 return ndr_pull_error(ndr
, NDR_ERR_ARRAY_SIZE
,
1229 "Bad pipe trailer[%lld should be %lld] size was %lu\"",
1230 (unsigned long long)ncount2
,
1231 (unsigned long long)ncount1
,
1232 (unsigned long)count
);
1235 return NDR_ERR_SUCCESS
;
1239 store a switch value
1241 _PUBLIC_
enum ndr_err_code
ndr_push_set_switch_value(struct ndr_push
*ndr
, const void *p
, uint32_t val
)
1243 enum ndr_err_code ret
=
1244 ndr_token_store(ndr
, &ndr
->switch_list
, p
, val
);
1245 if (ret
== NDR_ERR_RANGE
) {
1246 return ndr_push_error(ndr
, ret
,
1247 "More than %d NDR tokens stored for switch_list",
1248 NDR_TOKEN_MAX_LIST_SIZE
);
1253 _PUBLIC_
enum ndr_err_code
ndr_pull_set_switch_value(struct ndr_pull
*ndr
, const void *p
, uint32_t val
)
1256 enum ndr_err_code ret
=
1257 ndr_token_store(ndr
, &ndr
->switch_list
, p
, val
);
1258 if (ret
== NDR_ERR_RANGE
) {
1259 return ndr_pull_error(ndr
, ret
,
1260 "More than %d NDR tokens stored for switch_list",
1261 NDR_TOKEN_MAX_LIST_SIZE
);
1266 _PUBLIC_
enum ndr_err_code
ndr_print_set_switch_value(struct ndr_print
*ndr
, const void *p
, uint32_t val
)
1268 return ndr_token_store(ndr
, &ndr
->switch_list
, p
, val
);
1271 /* retrieve a switch value (for push) and remove it from the list */
1272 _PUBLIC_
enum ndr_err_code
ndr_push_steal_switch_value(struct ndr_push
*ndr
,
1276 return ndr_token_retrieve(&ndr
->switch_list
, p
, v
);
1279 /* retrieve a switch value and remove it from the list */
1280 _PUBLIC_
uint32_t ndr_print_steal_switch_value(struct ndr_print
*ndr
, const void *p
)
1282 enum ndr_err_code status
;
1285 status
= ndr_token_retrieve(&ndr
->switch_list
, p
, &v
);
1286 if (!NDR_ERR_CODE_IS_SUCCESS(status
)) {
1293 /* retrieve a switch value and remove it from the list */
1294 _PUBLIC_
enum ndr_err_code
ndr_pull_steal_switch_value(struct ndr_pull
*ndr
,
1298 return ndr_token_retrieve(&ndr
->switch_list
, p
, v
);
1302 pull a struct from a blob using NDR
1304 _PUBLIC_
enum ndr_err_code
ndr_pull_struct_blob(const DATA_BLOB
*blob
, TALLOC_CTX
*mem_ctx
, void *p
,
1305 ndr_pull_flags_fn_t fn
)
1307 struct ndr_pull
*ndr
;
1308 ndr
= ndr_pull_init_blob(blob
, mem_ctx
);
1309 NDR_ERR_HAVE_NO_MEMORY(ndr
);
1310 NDR_CHECK_FREE(fn(ndr
, NDR_SCALARS
|NDR_BUFFERS
, p
));
1312 return NDR_ERR_SUCCESS
;
1316 pull a struct from a blob using NDR - failing if all bytes are not consumed
1318 _PUBLIC_
enum ndr_err_code
ndr_pull_struct_blob_all(const DATA_BLOB
*blob
, TALLOC_CTX
*mem_ctx
,
1319 void *p
, ndr_pull_flags_fn_t fn
)
1321 struct ndr_pull
*ndr
;
1322 uint32_t highest_ofs
;
1323 ndr
= ndr_pull_init_blob(blob
, mem_ctx
);
1324 NDR_ERR_HAVE_NO_MEMORY(ndr
);
1325 NDR_CHECK_FREE(fn(ndr
, NDR_SCALARS
|NDR_BUFFERS
, p
));
1326 if (ndr
->offset
> ndr
->relative_highest_offset
) {
1327 highest_ofs
= ndr
->offset
;
1329 highest_ofs
= ndr
->relative_highest_offset
;
1331 if (highest_ofs
< ndr
->data_size
) {
1332 enum ndr_err_code ret
;
1333 ret
= ndr_pull_error(ndr
, NDR_ERR_UNREAD_BYTES
,
1334 "not all bytes consumed ofs[%u] size[%u]",
1335 highest_ofs
, ndr
->data_size
);
1340 return NDR_ERR_SUCCESS
;
1344 pull a struct from a blob using NDR - failing if all bytes are not consumed
1346 This only works for structures with NO allocated memory, like
1347 objectSID and GUID. This helps because we parse these a lot.
1349 _PUBLIC_
enum ndr_err_code
ndr_pull_struct_blob_all_noalloc(const DATA_BLOB
*blob
,
1350 void *p
, ndr_pull_flags_fn_t fn
)
1353 * We init this structure on the stack here, to avoid a
1354 * talloc() as otherwise this call to the fn() is assured not
1355 * to be doing any allocation, eg SIDs and GUIDs.
1357 * This allows us to keep the safety of the PIDL-generated
1358 * code without the talloc() overhead.
1360 struct ndr_pull ndr
= {
1362 .data_size
= blob
->length
,
1363 .current_mem_ctx
= (void *)-1
1365 uint32_t highest_ofs
;
1366 NDR_CHECK(fn(&ndr
, NDR_SCALARS
|NDR_BUFFERS
, p
));
1367 highest_ofs
= MAX(ndr
.offset
, ndr
.relative_highest_offset
);
1368 if (highest_ofs
< ndr
.data_size
) {
1369 enum ndr_err_code ret
;
1370 ret
= ndr_pull_error(
1372 NDR_ERR_UNREAD_BYTES
,
1373 "not all bytes consumed ofs[%"PRIu32
"] "
1379 return NDR_ERR_SUCCESS
;
1383 pull a union from a blob using NDR, given the union discriminator
1385 _PUBLIC_
enum ndr_err_code
ndr_pull_union_blob(const DATA_BLOB
*blob
, TALLOC_CTX
*mem_ctx
,
1387 uint32_t level
, ndr_pull_flags_fn_t fn
)
1389 struct ndr_pull
*ndr
;
1390 ndr
= ndr_pull_init_blob(blob
, mem_ctx
);
1391 NDR_ERR_HAVE_NO_MEMORY(ndr
);
1392 NDR_CHECK_FREE(ndr_pull_set_switch_value(ndr
, p
, level
));
1393 NDR_CHECK_FREE(fn(ndr
, NDR_SCALARS
|NDR_BUFFERS
, p
));
1395 return NDR_ERR_SUCCESS
;
1399 pull a union from a blob using NDR, given the union discriminator,
1400 failing if all bytes are not consumed
1402 _PUBLIC_
enum ndr_err_code
ndr_pull_union_blob_all(const DATA_BLOB
*blob
, TALLOC_CTX
*mem_ctx
,
1404 uint32_t level
, ndr_pull_flags_fn_t fn
)
1406 struct ndr_pull
*ndr
;
1407 uint32_t highest_ofs
;
1408 ndr
= ndr_pull_init_blob(blob
, mem_ctx
);
1409 NDR_ERR_HAVE_NO_MEMORY(ndr
);
1410 NDR_CHECK_FREE(ndr_pull_set_switch_value(ndr
, p
, level
));
1411 NDR_CHECK_FREE(fn(ndr
, NDR_SCALARS
|NDR_BUFFERS
, p
));
1412 if (ndr
->offset
> ndr
->relative_highest_offset
) {
1413 highest_ofs
= ndr
->offset
;
1415 highest_ofs
= ndr
->relative_highest_offset
;
1417 if (highest_ofs
< ndr
->data_size
) {
1418 enum ndr_err_code ret
;
1419 ret
= ndr_pull_error(ndr
, NDR_ERR_UNREAD_BYTES
,
1420 "not all bytes consumed ofs[%u] size[%u]",
1421 highest_ofs
, ndr
->data_size
);
1426 return NDR_ERR_SUCCESS
;
1430 push a struct to a blob using NDR
1432 _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
)
1434 struct ndr_push
*ndr
;
1435 ndr
= ndr_push_init_ctx(mem_ctx
);
1436 NDR_ERR_HAVE_NO_MEMORY(ndr
);
1438 NDR_CHECK(fn(ndr
, NDR_SCALARS
|NDR_BUFFERS
, p
));
1440 *blob
= ndr_push_blob(ndr
);
1441 talloc_steal(mem_ctx
, blob
->data
);
1444 return NDR_ERR_SUCCESS
;
1448 push a struct into a provided blob using NDR.
1450 We error because we want to have the performance issue (extra
1451 talloc() calls) show up as an error, not just slower code. This is
1452 used for things like GUIDs, which we expect to be a fixed size, and
1453 SIDs that we can pre-calculate the size for.
1455 _PUBLIC_
enum ndr_err_code
ndr_push_struct_into_fixed_blob(
1456 DATA_BLOB
*blob
, const void *p
, ndr_push_flags_fn_t fn
)
1458 struct ndr_push ndr
= {
1460 .alloc_size
= blob
->length
,
1461 .fixed_buf_size
= true
1464 NDR_CHECK(fn(&ndr
, NDR_SCALARS
|NDR_BUFFERS
, p
));
1466 if (ndr
.offset
!= blob
->length
) {
1467 return ndr_push_error(&ndr
, NDR_ERR_BUFSIZE
,
1468 "buffer was either to large or small "
1469 "ofs[%u] size[%zu]",
1470 ndr
.offset
, blob
->length
);
1473 return NDR_ERR_SUCCESS
;
1477 push a union to a blob using NDR
1479 _PUBLIC_
enum ndr_err_code
ndr_push_union_blob(DATA_BLOB
*blob
, TALLOC_CTX
*mem_ctx
, void *p
,
1480 uint32_t level
, ndr_push_flags_fn_t fn
)
1482 struct ndr_push
*ndr
;
1483 ndr
= ndr_push_init_ctx(mem_ctx
);
1484 NDR_ERR_HAVE_NO_MEMORY(ndr
);
1486 NDR_CHECK(ndr_push_set_switch_value(ndr
, p
, level
));
1487 NDR_CHECK(fn(ndr
, NDR_SCALARS
|NDR_BUFFERS
, p
));
1489 *blob
= ndr_push_blob(ndr
);
1490 talloc_steal(mem_ctx
, blob
->data
);
1493 return NDR_ERR_SUCCESS
;
1497 generic ndr_size_*() handler for structures
1499 _PUBLIC_
size_t ndr_size_struct(const void *p
, int flags
, ndr_push_flags_fn_t push
)
1501 struct ndr_push
*ndr
;
1502 enum ndr_err_code status
;
1505 /* avoid recursion */
1506 if (flags
& LIBNDR_FLAG_NO_NDR_SIZE
) return 0;
1508 /* Avoid following a NULL pointer */
1513 ndr
= ndr_push_init_ctx(NULL
);
1515 ndr
->flags
|= flags
| LIBNDR_FLAG_NO_NDR_SIZE
;
1516 status
= push(ndr
, NDR_SCALARS
|NDR_BUFFERS
, discard_const(p
));
1517 if (!NDR_ERR_CODE_IS_SUCCESS(status
)) {
1527 generic ndr_size_*() handler for unions
1529 _PUBLIC_
size_t ndr_size_union(const void *p
, int flags
, uint32_t level
, ndr_push_flags_fn_t push
)
1531 struct ndr_push
*ndr
;
1532 enum ndr_err_code status
;
1535 /* avoid recursion */
1536 if (flags
& LIBNDR_FLAG_NO_NDR_SIZE
) return 0;
1538 /* Avoid following a NULL pointer */
1543 ndr
= ndr_push_init_ctx(NULL
);
1545 ndr
->flags
|= flags
| LIBNDR_FLAG_NO_NDR_SIZE
;
1547 status
= ndr_push_set_switch_value(ndr
, p
, level
);
1548 if (!NDR_ERR_CODE_IS_SUCCESS(status
)) {
1552 status
= push(ndr
, NDR_SCALARS
|NDR_BUFFERS
, p
);
1553 if (!NDR_ERR_CODE_IS_SUCCESS(status
)) {
1563 get the current base for relative pointers for the push
1565 _PUBLIC_
uint32_t ndr_push_get_relative_base_offset(struct ndr_push
*ndr
)
1567 return ndr
->relative_base_offset
;
1571 restore the old base for relative pointers for the push
1573 _PUBLIC_
void ndr_push_restore_relative_base_offset(struct ndr_push
*ndr
, uint32_t offset
)
1575 ndr
->relative_base_offset
= offset
;
1579 setup the current base for relative pointers for the push
1580 called in the NDR_SCALAR stage
1582 _PUBLIC_
enum ndr_err_code
ndr_push_setup_relative_base_offset1(struct ndr_push
*ndr
, const void *p
, uint32_t offset
)
1584 enum ndr_err_code ret
;
1585 ndr
->relative_base_offset
= offset
;
1586 ret
= ndr_token_store(ndr
, &ndr
->relative_base_list
, p
, offset
);
1587 if (ret
== NDR_ERR_RANGE
) {
1588 return ndr_push_error(ndr
, ret
,
1589 "More than %d NDR tokens stored for relative_base_list",
1590 NDR_TOKEN_MAX_LIST_SIZE
);
1596 setup the current base for relative pointers for the push
1597 called in the NDR_BUFFERS stage
1599 _PUBLIC_
enum ndr_err_code
ndr_push_setup_relative_base_offset2(struct ndr_push
*ndr
, const void *p
)
1601 return ndr_token_retrieve(&ndr
->relative_base_list
, p
, &ndr
->relative_base_offset
);
1605 push a relative object - stage1
1606 this is called during SCALARS processing
1608 _PUBLIC_
enum ndr_err_code
ndr_push_relative_ptr1(struct ndr_push
*ndr
, const void *p
)
1610 enum ndr_err_code ret
;
1612 NDR_CHECK(ndr_push_uint32(ndr
, NDR_SCALARS
, 0));
1613 return NDR_ERR_SUCCESS
;
1615 NDR_CHECK(ndr_push_align(ndr
, 4));
1616 ret
= ndr_token_store(ndr
, &ndr
->relative_list
, p
, ndr
->offset
);
1617 if (ret
== NDR_ERR_RANGE
) {
1618 return ndr_push_error(ndr
, ret
,
1619 "More than %d NDR tokens stored for relative_list",
1620 NDR_TOKEN_MAX_LIST_SIZE
);
1623 return ndr_push_uint32(ndr
, NDR_SCALARS
, 0xFFFFFFFF);
1627 push a short relative object - stage1
1628 this is called during SCALARS processing
1630 _PUBLIC_
enum ndr_err_code
ndr_push_short_relative_ptr1(struct ndr_push
*ndr
, const void *p
)
1632 enum ndr_err_code ret
;
1634 NDR_CHECK(ndr_push_uint16(ndr
, NDR_SCALARS
, 0));
1635 return NDR_ERR_SUCCESS
;
1637 NDR_CHECK(ndr_push_align(ndr
, 2));
1638 ret
= ndr_token_store(ndr
, &ndr
->relative_list
, p
, ndr
->offset
);
1639 if (ret
== NDR_ERR_RANGE
) {
1640 return ndr_push_error(ndr
, ret
,
1641 "More than %d NDR tokens stored for relative_list",
1642 NDR_TOKEN_MAX_LIST_SIZE
);
1645 return ndr_push_uint16(ndr
, NDR_SCALARS
, 0xFFFF);
1648 push a relative object - stage2
1649 this is called during buffers processing
1651 static enum ndr_err_code
ndr_push_relative_ptr2(struct ndr_push
*ndr
, const void *p
)
1653 uint32_t save_offset
;
1654 uint32_t ptr_offset
= 0xFFFFFFFF;
1656 return NDR_ERR_SUCCESS
;
1658 save_offset
= ndr
->offset
;
1659 NDR_CHECK(ndr_token_retrieve(&ndr
->relative_list
, p
, &ptr_offset
));
1660 if (ptr_offset
> ndr
->offset
) {
1661 return ndr_push_error(ndr
, NDR_ERR_BUFSIZE
,
1662 "ndr_push_relative_ptr2 ptr_offset(%u) > ndr->offset(%u)",
1663 ptr_offset
, ndr
->offset
);
1665 ndr
->offset
= ptr_offset
;
1666 if (save_offset
< ndr
->relative_base_offset
) {
1667 return ndr_push_error(ndr
, NDR_ERR_BUFSIZE
,
1668 "ndr_push_relative_ptr2 save_offset(%u) < ndr->relative_base_offset(%u)",
1669 save_offset
, ndr
->relative_base_offset
);
1671 NDR_CHECK(ndr_push_uint32(ndr
, NDR_SCALARS
, save_offset
- ndr
->relative_base_offset
));
1672 ndr
->offset
= save_offset
;
1673 return NDR_ERR_SUCCESS
;
1676 push a short relative object - stage2
1677 this is called during buffers processing
1679 _PUBLIC_
enum ndr_err_code
ndr_push_short_relative_ptr2(struct ndr_push
*ndr
, const void *p
)
1681 uint32_t save_offset
;
1682 uint32_t ptr_offset
= 0xFFFF;
1683 uint32_t relative_offset
;
1688 return NDR_ERR_SUCCESS
;
1691 if (ndr
->offset
< ndr
->relative_base_offset
) {
1692 return ndr_push_error(ndr
, NDR_ERR_BUFSIZE
,
1693 "ndr_push_relative_ptr2 ndr->offset(%u) < ndr->relative_base_offset(%u)",
1694 ndr
->offset
, ndr
->relative_base_offset
);
1697 relative_offset
= ndr
->offset
- ndr
->relative_base_offset
;
1699 if (ndr
->flags
& LIBNDR_FLAG_NOALIGN
) {
1701 } else if (ndr
->flags
& LIBNDR_FLAG_ALIGN2
) {
1703 } else if (ndr
->flags
& LIBNDR_FLAG_ALIGN4
) {
1705 } else if (ndr
->flags
& LIBNDR_FLAG_ALIGN8
) {
1709 pad
= ndr_align_size(relative_offset
, align
);
1711 NDR_CHECK(ndr_push_zero(ndr
, pad
));
1714 relative_offset
= ndr
->offset
- ndr
->relative_base_offset
;
1715 if (relative_offset
> UINT16_MAX
) {
1716 return ndr_push_error(ndr
, NDR_ERR_BUFSIZE
,
1717 "ndr_push_relative_ptr2 relative_offset(%u) > UINT16_MAX",
1721 save_offset
= ndr
->offset
;
1722 NDR_CHECK(ndr_token_retrieve(&ndr
->relative_list
, p
, &ptr_offset
));
1723 if (ptr_offset
> ndr
->offset
) {
1724 return ndr_push_error(ndr
, NDR_ERR_BUFSIZE
,
1725 "ndr_push_short_relative_ptr2 ptr_offset(%u) > ndr->offset(%u)",
1726 ptr_offset
, ndr
->offset
);
1728 ndr
->offset
= ptr_offset
;
1729 NDR_CHECK(ndr_push_uint16(ndr
, NDR_SCALARS
, relative_offset
));
1730 ndr
->offset
= save_offset
;
1731 return NDR_ERR_SUCCESS
;
1735 push a relative object - stage2 start
1736 this is called during buffers processing
1738 _PUBLIC_
enum ndr_err_code
ndr_push_relative_ptr2_start(struct ndr_push
*ndr
, const void *p
)
1740 enum ndr_err_code ret
;
1742 return NDR_ERR_SUCCESS
;
1744 if (!(ndr
->flags
& LIBNDR_FLAG_RELATIVE_REVERSE
)) {
1745 uint32_t relative_offset
;
1749 if (ndr
->offset
< ndr
->relative_base_offset
) {
1750 return ndr_push_error(ndr
, NDR_ERR_BUFSIZE
,
1751 "ndr_push_relative_ptr2_start ndr->offset(%u) < ndr->relative_base_offset(%u)",
1752 ndr
->offset
, ndr
->relative_base_offset
);
1755 relative_offset
= ndr
->offset
- ndr
->relative_base_offset
;
1757 if (ndr
->flags
& LIBNDR_FLAG_NOALIGN
) {
1759 } else if (ndr
->flags
& LIBNDR_FLAG_ALIGN2
) {
1761 } else if (ndr
->flags
& LIBNDR_FLAG_ALIGN4
) {
1763 } else if (ndr
->flags
& LIBNDR_FLAG_ALIGN8
) {
1767 pad
= ndr_align_size(relative_offset
, align
);
1769 NDR_CHECK(ndr_push_zero(ndr
, pad
));
1772 return ndr_push_relative_ptr2(ndr
, p
);
1774 if (ndr
->relative_end_offset
== -1) {
1775 return ndr_push_error(ndr
, NDR_ERR_RELATIVE
,
1776 "ndr_push_relative_ptr2_start RELATIVE_REVERSE flag set and relative_end_offset %d",
1777 ndr
->relative_end_offset
);
1779 ret
= ndr_token_store(ndr
,
1780 &ndr
->relative_begin_list
,
1783 if (ret
== NDR_ERR_RANGE
) {
1784 return ndr_push_error(ndr
, ret
,
1785 "More than %d NDR tokens stored for array_size",
1786 NDR_TOKEN_MAX_LIST_SIZE
);
1792 push a relative object - stage2 end
1793 this is called during buffers processing
1795 _PUBLIC_
enum ndr_err_code
ndr_push_relative_ptr2_end(struct ndr_push
*ndr
, const void *p
)
1797 uint32_t begin_offset
= 0xFFFFFFFF;
1799 uint32_t correct_offset
= 0;
1804 return NDR_ERR_SUCCESS
;
1807 if (!(ndr
->flags
& LIBNDR_FLAG_RELATIVE_REVERSE
)) {
1808 return NDR_ERR_SUCCESS
;
1811 if (ndr
->flags
& LIBNDR_FLAG_NO_NDR_SIZE
) {
1812 /* better say more than calculation a too small buffer */
1813 NDR_PUSH_ALIGN(ndr
, 8);
1814 return NDR_ERR_SUCCESS
;
1817 if (ndr
->relative_end_offset
< ndr
->offset
) {
1818 return ndr_push_error(ndr
, NDR_ERR_RELATIVE
,
1819 "ndr_push_relative_ptr2_end:"
1820 "relative_end_offset %u < offset %u",
1821 ndr
->relative_end_offset
, ndr
->offset
);
1824 NDR_CHECK(ndr_token_retrieve(&ndr
->relative_begin_list
, p
, &begin_offset
));
1826 /* we have marshalled a buffer, see how long it was */
1827 len
= ndr
->offset
- begin_offset
;
1830 return ndr_push_error(ndr
, NDR_ERR_RELATIVE
,
1831 "ndr_push_relative_ptr2_end:"
1832 "offset %u - begin_offset %u < 0",
1833 ndr
->offset
, begin_offset
);
1836 if (ndr
->relative_end_offset
< len
) {
1837 return ndr_push_error(ndr
, NDR_ERR_RELATIVE
,
1838 "ndr_push_relative_ptr2_end:"
1839 "relative_end_offset %u < len %lld",
1840 ndr
->offset
, (long long)len
);
1843 /* the reversed offset is at the end of the main buffer */
1844 correct_offset
= ndr
->relative_end_offset
- len
;
1846 if (ndr
->flags
& LIBNDR_FLAG_NOALIGN
) {
1848 } else if (ndr
->flags
& LIBNDR_FLAG_ALIGN2
) {
1850 } else if (ndr
->flags
& LIBNDR_FLAG_ALIGN4
) {
1852 } else if (ndr
->flags
& LIBNDR_FLAG_ALIGN8
) {
1856 pad
= ndr_align_size(correct_offset
, align
);
1858 correct_offset
+= pad
;
1859 correct_offset
-= align
;
1862 if (correct_offset
< begin_offset
) {
1863 return ndr_push_error(ndr
, NDR_ERR_RELATIVE
,
1864 "ndr_push_relative_ptr2_end: "
1865 "correct_offset %u < begin_offset %u",
1866 correct_offset
, begin_offset
);
1870 uint32_t clear_size
= correct_offset
- begin_offset
;
1872 clear_size
= MIN(clear_size
, len
);
1874 /* now move the marshalled buffer to the end of the main buffer */
1875 memmove(ndr
->data
+ correct_offset
, ndr
->data
+ begin_offset
, len
);
1878 /* and wipe out old buffer within the main buffer */
1879 memset(ndr
->data
+ begin_offset
, '\0', clear_size
);
1883 /* and set the end offset for the next buffer */
1884 ndr
->relative_end_offset
= correct_offset
;
1886 /* finally write the offset to the main buffer */
1887 ndr
->offset
= correct_offset
;
1888 NDR_CHECK(ndr_push_relative_ptr2(ndr
, p
));
1890 /* restore to where we were in the main buffer */
1891 ndr
->offset
= begin_offset
;
1893 return NDR_ERR_SUCCESS
;
1897 get the current base for relative pointers for the pull
1899 _PUBLIC_
uint32_t ndr_pull_get_relative_base_offset(struct ndr_pull
*ndr
)
1901 return ndr
->relative_base_offset
;
1905 restore the old base for relative pointers for the pull
1907 _PUBLIC_
void ndr_pull_restore_relative_base_offset(struct ndr_pull
*ndr
, uint32_t offset
)
1909 ndr
->relative_base_offset
= offset
;
1913 setup the current base for relative pointers for the pull
1914 called in the NDR_SCALAR stage
1916 _PUBLIC_
enum ndr_err_code
ndr_pull_setup_relative_base_offset1(struct ndr_pull
*ndr
, const void *p
, uint32_t offset
)
1918 enum ndr_err_code ret
;
1919 ndr
->relative_base_offset
= offset
;
1920 ret
= ndr_token_store(ndr
, &ndr
->relative_base_list
, p
, offset
);
1921 if (ret
== NDR_ERR_RANGE
) {
1922 return ndr_pull_error(ndr
, ret
,
1923 "More than %d NDR tokens stored for relative_base_list",
1924 NDR_TOKEN_MAX_LIST_SIZE
);
1930 setup the current base for relative pointers for the pull
1931 called in the NDR_BUFFERS stage
1933 _PUBLIC_
enum ndr_err_code
ndr_pull_setup_relative_base_offset2(struct ndr_pull
*ndr
, const void *p
)
1935 return ndr_token_retrieve(&ndr
->relative_base_list
, p
, &ndr
->relative_base_offset
);
1939 pull a relative object - stage1
1940 called during SCALARS processing
1942 _PUBLIC_
enum ndr_err_code
ndr_pull_relative_ptr1(struct ndr_pull
*ndr
, const void *p
, uint32_t rel_offset
)
1944 enum ndr_err_code ret
;
1945 rel_offset
+= ndr
->relative_base_offset
;
1946 if (rel_offset
> ndr
->data_size
) {
1947 return ndr_pull_error(ndr
, NDR_ERR_BUFSIZE
,
1948 "ndr_pull_relative_ptr1 rel_offset(%u) > ndr->data_size(%u)",
1949 rel_offset
, ndr
->data_size
);
1951 ret
= ndr_token_store(ndr
, &ndr
->relative_list
, p
, rel_offset
);
1952 if (ret
== NDR_ERR_RANGE
) {
1953 return ndr_pull_error(ndr
, ret
,
1954 "More than %d NDR tokens stored for relative_list",
1955 NDR_TOKEN_MAX_LIST_SIZE
);
1961 pull a relative object - stage2
1962 called during BUFFERS processing
1964 _PUBLIC_
enum ndr_err_code
ndr_pull_relative_ptr2(struct ndr_pull
*ndr
, const void *p
)
1966 uint32_t rel_offset
;
1967 NDR_CHECK(ndr_token_retrieve(&ndr
->relative_list
, p
, &rel_offset
));
1968 return ndr_pull_set_offset(ndr
, rel_offset
);
1971 static const struct {
1972 enum ndr_err_code err
;
1974 } ndr_err_code_strings
[] = {
1975 { NDR_ERR_SUCCESS
, "Success" },
1976 { NDR_ERR_ARRAY_SIZE
, "Bad Array Size" },
1977 { NDR_ERR_BAD_SWITCH
, "Bad Switch" },
1978 { NDR_ERR_OFFSET
, "Offset Error" },
1979 { NDR_ERR_RELATIVE
, "Relative Pointer Error" },
1980 { NDR_ERR_CHARCNV
, "Character Conversion Error" },
1981 { NDR_ERR_LENGTH
, "Length Error" },
1982 { NDR_ERR_SUBCONTEXT
, "Subcontext Error" },
1983 { NDR_ERR_COMPRESSION
, "Compression Error" },
1984 { NDR_ERR_STRING
, "String Error" },
1985 { NDR_ERR_VALIDATE
, "Validate Error" },
1986 { NDR_ERR_BUFSIZE
, "Buffer Size Error" },
1987 { NDR_ERR_ALLOC
, "Allocation Error" },
1988 { NDR_ERR_RANGE
, "Range Error" },
1989 { NDR_ERR_TOKEN
, "Token Error" },
1990 { NDR_ERR_IPV4ADDRESS
, "IPv4 Address Error" },
1991 { NDR_ERR_INVALID_POINTER
, "Invalid Pointer" },
1992 { NDR_ERR_UNREAD_BYTES
, "Unread Bytes" },
1993 { NDR_ERR_NDR64
, "NDR64 assertion error" },
1994 { NDR_ERR_INCOMPLETE_BUFFER
, "Incomplete Buffer" },
1995 { NDR_ERR_MAX_RECURSION_EXCEEDED
, "Maximum Recursion Exceeded" },
1996 { NDR_ERR_UNDERFLOW
, "Underflow" },
2000 _PUBLIC_
const char *ndr_map_error2string(enum ndr_err_code ndr_err
)
2003 for (i
= 0; ndr_err_code_strings
[i
].string
!= NULL
; i
++) {
2004 if (ndr_err_code_strings
[i
].err
== ndr_err
)
2005 return ndr_err_code_strings
[i
].string
;
2007 return "Unknown error";