2 Unix SMB/CIFS implementation.
6 Copyright (C) Andrew Tridgell 2003
7 Copyright (C) Jelmer Vernooij 2005-2008
9 This program is free software; you can redistribute it and/or modify
10 it under the terms of the GNU General Public License as published by
11 the Free Software Foundation; either version 3 of the License, or
12 (at your option) any later version.
14 This program is distributed in the hope that it will be useful,
15 but WITHOUT ANY WARRANTY; without even the implied warranty of
16 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17 GNU General Public License for more details.
19 You should have received a copy of the GNU General Public License
20 along with this program. If not, see <http://www.gnu.org/licenses/>.
24 this provides the core routines for NDR parsing functions
26 see http://www.opengroup.org/onlinepubs/9629399/chap14.htm for details
31 #include "librpc/ndr/libndr.h"
32 #include "../lib/util/dlinklist.h"
34 #define NDR_BASE_MARSHALL_SIZE 1024
36 /* this guid indicates NDR encoding in a protocol tower */
37 const struct ndr_syntax_id ndr_transfer_syntax_ndr
= {
38 { 0x8a885d04, 0x1ceb, 0x11c9, {0x9f, 0xe8}, {0x08,0x00,0x2b,0x10,0x48,0x60} },
42 const struct ndr_syntax_id ndr_transfer_syntax_ndr64
= {
43 { 0x71710533, 0xbeba, 0x4937, {0x83, 0x19}, {0xb5,0xdb,0xef,0x9c,0xcc,0x36} },
47 const struct ndr_syntax_id ndr_syntax_id_null
= {
48 { 0, 0, 0, { 0, 0 }, { 0, 0, 0, 0, 0, 0 } },
53 work out the number of bytes needed to align on a n byte boundary
55 _PUBLIC_
size_t ndr_align_size(uint32_t offset
, size_t n
)
57 if ((offset
& (n
-1)) == 0) return 0;
58 return n
- (offset
& (n
-1));
62 initialise a ndr parse structure from a data blob
64 _PUBLIC_
struct ndr_pull
*ndr_pull_init_blob(const DATA_BLOB
*blob
, TALLOC_CTX
*mem_ctx
)
68 ndr
= talloc_zero(mem_ctx
, struct ndr_pull
);
69 if (!ndr
) return NULL
;
70 ndr
->current_mem_ctx
= mem_ctx
;
72 ndr
->data
= blob
->data
;
73 ndr
->data_size
= blob
->length
;
78 _PUBLIC_
enum ndr_err_code
ndr_pull_append(struct ndr_pull
*ndr
, DATA_BLOB
*blob
)
80 enum ndr_err_code ndr_err
;
85 if (blob
->length
== 0) {
86 return NDR_ERR_SUCCESS
;
89 ndr_err
= ndr_token_retrieve(&ndr
->array_size_list
, ndr
, &append
);
90 if (ndr_err
== NDR_ERR_TOKEN
) {
92 ndr_err
= NDR_ERR_SUCCESS
;
96 if (ndr
->data_size
== 0) {
101 if (append
== UINT32_MAX
) {
103 * append == UINT32_MAX means that
104 * ndr->data is either NULL or a valid
105 * talloc child of ndr, which means
106 * we can use data_blob_append() without
107 * data_blob_talloc() of the existing callers data
109 b
= data_blob_const(ndr
->data
, ndr
->data_size
);
111 b
= data_blob_talloc(ndr
, ndr
->data
, ndr
->data_size
);
112 if (b
.data
== NULL
) {
113 return ndr_pull_error(ndr
, NDR_ERR_ALLOC
, "%s", __location__
);
117 ok
= data_blob_append(ndr
, &b
, blob
->data
, blob
->length
);
119 return ndr_pull_error(ndr
, NDR_ERR_ALLOC
, "%s", __location__
);
123 ndr
->data_size
= b
.length
;
125 return ndr_token_store(ndr
, &ndr
->array_size_list
, ndr
, UINT32_MAX
);
128 _PUBLIC_
enum ndr_err_code
ndr_pull_pop(struct ndr_pull
*ndr
)
133 if (ndr
->relative_base_offset
!= 0) {
134 return ndr_pull_error(ndr
, NDR_ERR_RELATIVE
,
137 if (ndr
->relative_highest_offset
!= 0) {
138 return ndr_pull_error(ndr
, NDR_ERR_RELATIVE
,
141 if (ndr
->relative_list
!= NULL
) {
142 return ndr_pull_error(ndr
, NDR_ERR_RELATIVE
,
145 if (ndr
->relative_base_list
!= NULL
) {
146 return ndr_pull_error(ndr
, NDR_ERR_RELATIVE
,
151 * we need to keep up to 7 bytes
152 * in order to get the aligment right.
154 skip
= ndr
->offset
& 0xFFFFFFF8;
157 return NDR_ERR_SUCCESS
;
161 ndr
->data_size
-= skip
;
163 append
= ndr_token_peek(&ndr
->array_size_list
, ndr
);
164 if (append
!= UINT32_MAX
) {
166 * here we assume, that ndr->data is not a
167 * talloc child of ndr.
170 return NDR_ERR_SUCCESS
;
173 memmove(ndr
->data
, ndr
->data
+ skip
, ndr
->data_size
);
175 ndr
->data
= talloc_realloc(ndr
, ndr
->data
, uint8_t, ndr
->data_size
);
176 if (ndr
->data_size
!= 0 && ndr
->data
== NULL
) {
177 return ndr_pull_error(ndr
, NDR_ERR_ALLOC
, "%s", __location__
);
180 return NDR_ERR_SUCCESS
;
184 advance by 'size' bytes
186 _PUBLIC_
enum ndr_err_code
ndr_pull_advance(struct ndr_pull
*ndr
, uint32_t size
)
189 if (ndr
->offset
> ndr
->data_size
) {
190 return ndr_pull_error(ndr
, NDR_ERR_BUFSIZE
,
191 "ndr_pull_advance by %u failed",
194 return NDR_ERR_SUCCESS
;
198 set the parse offset to 'ofs'
200 static enum ndr_err_code
ndr_pull_set_offset(struct ndr_pull
*ndr
, uint32_t ofs
)
203 if (ndr
->offset
> ndr
->data_size
) {
204 return ndr_pull_error(ndr
, NDR_ERR_BUFSIZE
,
205 "ndr_pull_set_offset %u failed",
208 return NDR_ERR_SUCCESS
;
211 /* create a ndr_push structure, ready for some marshalling */
212 _PUBLIC_
struct ndr_push
*ndr_push_init_ctx(TALLOC_CTX
*mem_ctx
)
214 struct ndr_push
*ndr
;
216 ndr
= talloc_zero(mem_ctx
, struct ndr_push
);
222 ndr
->alloc_size
= NDR_BASE_MARSHALL_SIZE
;
223 ndr
->data
= talloc_array(ndr
, uint8_t, ndr
->alloc_size
);
232 /* return a DATA_BLOB structure for the current ndr_push marshalled data */
233 _PUBLIC_ DATA_BLOB
ndr_push_blob(struct ndr_push
*ndr
)
236 blob
= data_blob_const(ndr
->data
, ndr
->offset
);
237 if (ndr
->alloc_size
> ndr
->offset
) {
238 ndr
->data
[ndr
->offset
] = 0;
245 expand the available space in the buffer to ndr->offset + extra_size
247 _PUBLIC_
enum ndr_err_code
ndr_push_expand(struct ndr_push
*ndr
, uint32_t extra_size
)
249 uint32_t size
= extra_size
+ ndr
->offset
;
251 if (size
< ndr
->offset
) {
252 /* extra_size overflowed the offset */
253 return ndr_push_error(ndr
, NDR_ERR_BUFSIZE
, "Overflow in push_expand to %u",
257 if (ndr
->fixed_buf_size
) {
258 if (ndr
->alloc_size
>= size
) {
259 return NDR_ERR_SUCCESS
;
261 return ndr_push_error(ndr
,
263 "Overflow of fixed buffer in "
268 if (ndr
->alloc_size
> size
) {
269 return NDR_ERR_SUCCESS
;
272 ndr
->alloc_size
+= NDR_BASE_MARSHALL_SIZE
;
273 if (size
+1 > ndr
->alloc_size
) {
274 ndr
->alloc_size
= size
+1;
276 ndr
->data
= talloc_realloc(ndr
, ndr
->data
, uint8_t, ndr
->alloc_size
);
278 return ndr_push_error(ndr
, NDR_ERR_ALLOC
, "Failed to push_expand to %u",
282 return NDR_ERR_SUCCESS
;
285 _PUBLIC_
void ndr_print_debugc_helper(struct ndr_print
*ndr
, const char *format
, ...)
293 va_start(ap
, format
);
294 ret
= vasprintf(&s
, format
, ap
);
301 dbgc_class
= *(int *)ndr
->private_data
;
303 if (ndr
->no_newline
) {
304 DEBUGADDC(dbgc_class
, 1,("%s", s
));
309 for (i
=0;i
<ndr
->depth
;i
++) {
310 DEBUGADDC(dbgc_class
, 1,(" "));
313 DEBUGADDC(dbgc_class
, 1,("%s\n", s
));
317 _PUBLIC_
void ndr_print_debug_helper(struct ndr_print
*ndr
, const char *format
, ...)
324 va_start(ap
, format
);
325 ret
= vasprintf(&s
, format
, ap
);
332 if (ndr
->no_newline
) {
333 DEBUGADD(1,("%s", s
));
338 for (i
=0;i
<ndr
->depth
;i
++) {
342 DEBUGADD(1,("%s\n", s
));
346 _PUBLIC_
void ndr_print_printf_helper(struct ndr_print
*ndr
, const char *format
, ...)
351 if (!ndr
->no_newline
) {
352 for (i
=0;i
<ndr
->depth
;i
++) {
357 va_start(ap
, format
);
360 if (!ndr
->no_newline
) {
365 _PUBLIC_
void ndr_print_string_helper(struct ndr_print
*ndr
, const char *format
, ...)
370 if (!ndr
->no_newline
) {
371 for (i
=0;i
<ndr
->depth
;i
++) {
372 ndr
->private_data
= talloc_asprintf_append_buffer(
373 (char *)ndr
->private_data
, " ");
377 va_start(ap
, format
);
378 ndr
->private_data
= talloc_vasprintf_append_buffer((char *)ndr
->private_data
,
381 if (!ndr
->no_newline
) {
382 ndr
->private_data
= talloc_asprintf_append_buffer((char *)ndr
->private_data
,
388 a useful helper function for printing idl structures via DEBUGC()
390 _PUBLIC_
void ndr_print_debugc(int dbgc_class
, ndr_print_fn_t fn
, const char *name
, void *ptr
)
392 struct ndr_print
*ndr
;
394 DEBUGC(dbgc_class
, 1,(" "));
396 ndr
= talloc_zero(NULL
, struct ndr_print
);
398 ndr
->private_data
= &dbgc_class
;
399 ndr
->print
= ndr_print_debugc_helper
;
407 a useful helper function for printing idl structures via DEBUG()
409 _PUBLIC_
void ndr_print_debug(ndr_print_fn_t fn
, const char *name
, void *ptr
)
411 struct ndr_print
*ndr
;
415 ndr
= talloc_zero(NULL
, struct ndr_print
);
417 ndr
->print
= ndr_print_debug_helper
;
425 a useful helper function for printing idl unions via DEBUG()
427 _PUBLIC_
void ndr_print_union_debug(ndr_print_fn_t fn
, const char *name
, uint32_t level
, void *ptr
)
429 struct ndr_print
*ndr
;
433 ndr
= talloc_zero(NULL
, struct ndr_print
);
435 ndr
->print
= ndr_print_debug_helper
;
438 ndr_print_set_switch_value(ndr
, ptr
, level
);
444 a useful helper function for printing idl function calls via DEBUG()
446 _PUBLIC_
void ndr_print_function_debug(ndr_print_function_t fn
, const char *name
, int flags
, void *ptr
)
448 struct ndr_print
*ndr
;
452 ndr
= talloc_zero(NULL
, struct ndr_print
);
454 ndr
->print
= ndr_print_debug_helper
;
458 fn(ndr
, name
, flags
, ptr
);
463 a useful helper function for printing idl structures to a string
465 _PUBLIC_
char *ndr_print_struct_string(TALLOC_CTX
*mem_ctx
, ndr_print_fn_t fn
, const char *name
, void *ptr
)
467 struct ndr_print
*ndr
;
470 ndr
= talloc_zero(mem_ctx
, struct ndr_print
);
471 if (!ndr
) return NULL
;
472 ndr
->private_data
= talloc_strdup(ndr
, "");
473 if (!ndr
->private_data
) {
476 ndr
->print
= ndr_print_string_helper
;
481 ret
= talloc_steal(mem_ctx
, (char *)ndr
->private_data
);
488 a useful helper function for printing idl unions to a string
490 _PUBLIC_
char *ndr_print_union_string(TALLOC_CTX
*mem_ctx
, ndr_print_fn_t fn
, const char *name
, uint32_t level
, void *ptr
)
492 struct ndr_print
*ndr
;
495 ndr
= talloc_zero(mem_ctx
, struct ndr_print
);
496 if (!ndr
) return NULL
;
497 ndr
->private_data
= talloc_strdup(ndr
, "");
498 if (!ndr
->private_data
) {
501 ndr
->print
= ndr_print_string_helper
;
504 ndr_print_set_switch_value(ndr
, ptr
, level
);
506 ret
= talloc_steal(mem_ctx
, (char *)ndr
->private_data
);
513 a useful helper function for printing idl function calls to a string
515 _PUBLIC_
char *ndr_print_function_string(TALLOC_CTX
*mem_ctx
,
516 ndr_print_function_t fn
, const char *name
,
517 int flags
, void *ptr
)
519 struct ndr_print
*ndr
;
522 ndr
= talloc_zero(mem_ctx
, struct ndr_print
);
523 if (!ndr
) return NULL
;
524 ndr
->private_data
= talloc_strdup(ndr
, "");
525 if (!ndr
->private_data
) {
528 ndr
->print
= ndr_print_string_helper
;
531 fn(ndr
, name
, flags
, ptr
);
532 ret
= talloc_steal(mem_ctx
, (char *)ndr
->private_data
);
538 _PUBLIC_
void ndr_set_flags(uint32_t *pflags
, uint32_t new_flags
)
540 /* the big/little endian flags are inter-dependent */
541 if (new_flags
& LIBNDR_FLAG_LITTLE_ENDIAN
) {
542 (*pflags
) &= ~LIBNDR_FLAG_BIGENDIAN
;
543 (*pflags
) &= ~LIBNDR_FLAG_NDR64
;
545 if (new_flags
& LIBNDR_FLAG_BIGENDIAN
) {
546 (*pflags
) &= ~LIBNDR_FLAG_LITTLE_ENDIAN
;
547 (*pflags
) &= ~LIBNDR_FLAG_NDR64
;
549 if (new_flags
& LIBNDR_ALIGN_FLAGS
) {
550 /* Ensure we only have the passed-in
551 align flag set in the new_flags,
552 remove any old align flag. */
553 (*pflags
) &= ~LIBNDR_ALIGN_FLAGS
;
555 if (new_flags
& LIBNDR_FLAG_NO_RELATIVE_REVERSE
) {
556 (*pflags
) &= ~LIBNDR_FLAG_RELATIVE_REVERSE
;
558 (*pflags
) |= new_flags
;
562 return and possibly log an NDR error
564 _PUBLIC_
enum ndr_err_code
ndr_pull_error(struct ndr_pull
*ndr
,
565 enum ndr_err_code ndr_err
,
566 const char *format
, ...)
572 if (ndr
->flags
& LIBNDR_FLAG_INCOMPLETE_BUFFER
) {
574 case NDR_ERR_BUFSIZE
:
575 return NDR_ERR_INCOMPLETE_BUFFER
;
581 va_start(ap
, format
);
582 ret
= vasprintf(&s
, format
, ap
);
586 return NDR_ERR_ALLOC
;
589 DEBUG(1,("ndr_pull_error(%u): %s\n", ndr_err
, s
));
597 return and possibly log an NDR error
599 _PUBLIC_
enum ndr_err_code
ndr_push_error(struct ndr_push
*ndr
,
600 enum ndr_err_code ndr_err
,
601 const char *format
, ...)
607 va_start(ap
, format
);
608 ret
= vasprintf(&s
, format
, ap
);
612 return NDR_ERR_ALLOC
;
615 DEBUG(1,("ndr_push_error(%u): %s\n", ndr_err
, s
));
623 handle subcontext buffers, which in midl land are user-marshalled, but
624 we use magic in pidl to make them easier to cope with
626 _PUBLIC_
enum ndr_err_code
ndr_pull_subcontext_start(struct ndr_pull
*ndr
,
627 struct ndr_pull
**_subndr
,
631 struct ndr_pull
*subndr
;
632 uint32_t r_content_size
;
633 bool force_le
= false;
634 bool force_be
= false;
636 switch (header_size
) {
638 uint32_t content_size
= ndr
->data_size
- ndr
->offset
;
640 content_size
= size_is
;
642 r_content_size
= content_size
;
647 uint16_t content_size
;
648 NDR_CHECK(ndr_pull_uint16(ndr
, NDR_SCALARS
, &content_size
));
649 if (size_is
>= 0 && size_is
!= content_size
) {
650 return ndr_pull_error(ndr
, NDR_ERR_SUBCONTEXT
, "Bad subcontext (PULL) size_is(%d) (0x%04x) mismatch content_size %d (0x%04x)",
651 (int)size_is
, (int)size_is
,
655 r_content_size
= content_size
;
660 uint32_t content_size
;
661 NDR_CHECK(ndr_pull_uint3264(ndr
, NDR_SCALARS
, &content_size
));
662 if (size_is
>= 0 && size_is
!= content_size
) {
663 return ndr_pull_error(ndr
, NDR_ERR_SUBCONTEXT
, "Bad subcontext (PULL) size_is(%d) (0x%08x) mismatch content_size %d (0x%08x)",
664 (int)size_is
, (int)size_is
,
668 r_content_size
= content_size
;
673 * Common Type Header for the Serialization Stream
674 * See [MS-RPCE] 2.2.6 Type Serialization Version 1
680 uint32_t content_size
;
684 NDR_CHECK(ndr_pull_uint8(ndr
, NDR_SCALARS
, &version
));
687 return ndr_pull_error(ndr
, NDR_ERR_SUBCONTEXT
,
688 "Bad subcontext (PULL) Common Type Header version %d != 1",
696 NDR_CHECK(ndr_pull_uint8(ndr
, NDR_SCALARS
, &drep
));
699 } else if (drep
== 0x00) {
702 return ndr_pull_error(ndr
, NDR_ERR_SUBCONTEXT
,
703 "Bad subcontext (PULL) Common Type Header invalid drep 0x%02X",
707 /* length of the "Private Header for Constructed Type" */
708 NDR_CHECK(ndr_pull_uint16(ndr
, NDR_SCALARS
, &hdrlen
));
710 return ndr_pull_error(ndr
, NDR_ERR_SUBCONTEXT
,
711 "Bad subcontext (PULL) Common Type Header length %d != 8",
715 /* filler should be ignored */
716 NDR_CHECK(ndr_pull_uint32(ndr
, NDR_SCALARS
, &filler
));
719 * Private Header for Constructed Type
721 /* length - will be updated latter */
722 NDR_CHECK(ndr_pull_uint32(ndr
, NDR_SCALARS
, &content_size
));
723 if (size_is
>= 0 && size_is
!= content_size
) {
724 return ndr_pull_error(ndr
, NDR_ERR_SUBCONTEXT
, "Bad subcontext (PULL) size_is(%d) mismatch content_size %d",
725 (int)size_is
, (int)content_size
);
727 /* the content size must be a multiple of 8 */
728 if ((content_size
% 8) != 0) {
729 return ndr_pull_error(ndr
, NDR_ERR_SUBCONTEXT
,
730 "Bad subcontext (PULL) size_is(%d) not padded to 8 content_size %d",
731 (int)size_is
, (int)content_size
);
733 r_content_size
= content_size
;
736 NDR_CHECK(ndr_pull_uint32(ndr
, NDR_SCALARS
, &reserved
));
741 * a shallow copy like subcontext
742 * useful for DCERPC pipe chunks.
744 subndr
= talloc_zero(ndr
, struct ndr_pull
);
745 NDR_ERR_HAVE_NO_MEMORY(subndr
);
747 subndr
->flags
= ndr
->flags
;
748 subndr
->current_mem_ctx
= ndr
->current_mem_ctx
;
749 subndr
->data
= ndr
->data
;
750 subndr
->offset
= ndr
->offset
;
751 subndr
->data_size
= ndr
->data_size
;
754 return NDR_ERR_SUCCESS
;
757 return ndr_pull_error(ndr
, NDR_ERR_SUBCONTEXT
, "Bad subcontext (PULL) header_size %d",
761 NDR_PULL_NEED_BYTES(ndr
, r_content_size
);
763 subndr
= talloc_zero(ndr
, struct ndr_pull
);
764 NDR_ERR_HAVE_NO_MEMORY(subndr
);
765 subndr
->flags
= ndr
->flags
& ~LIBNDR_FLAG_NDR64
;
766 subndr
->current_mem_ctx
= ndr
->current_mem_ctx
;
768 subndr
->data
= ndr
->data
+ ndr
->offset
;
770 subndr
->data_size
= r_content_size
;
773 ndr_set_flags(&ndr
->flags
, LIBNDR_FLAG_LITTLE_ENDIAN
);
774 } else if (force_be
) {
775 ndr_set_flags(&ndr
->flags
, LIBNDR_FLAG_BIGENDIAN
);
779 return NDR_ERR_SUCCESS
;
782 _PUBLIC_
enum ndr_err_code
ndr_pull_subcontext_end(struct ndr_pull
*ndr
,
783 struct ndr_pull
*subndr
,
788 uint32_t highest_ofs
;
790 if (header_size
== 0xFFFFFFFF) {
791 advance
= subndr
->offset
- ndr
->offset
;
792 } else if (size_is
>= 0) {
794 } else if (header_size
> 0) {
795 advance
= subndr
->data_size
;
797 advance
= subndr
->offset
;
800 if (subndr
->offset
> ndr
->relative_highest_offset
) {
801 highest_ofs
= subndr
->offset
;
803 highest_ofs
= subndr
->relative_highest_offset
;
805 if (!(subndr
->flags
& LIBNDR_FLAG_SUBCONTEXT_NO_UNREAD_BYTES
)) {
807 * avoid an error unless SUBCONTEXT_NO_UNREAD_BYTES is specified
809 highest_ofs
= advance
;
811 if (highest_ofs
< advance
) {
812 return ndr_pull_error(subndr
, NDR_ERR_UNREAD_BYTES
,
813 "not all bytes consumed ofs[%u] advance[%u]",
814 highest_ofs
, advance
);
817 NDR_CHECK(ndr_pull_advance(ndr
, advance
));
818 return NDR_ERR_SUCCESS
;
821 _PUBLIC_
enum ndr_err_code
ndr_push_subcontext_start(struct ndr_push
*ndr
,
822 struct ndr_push
**_subndr
,
826 struct ndr_push
*subndr
;
828 subndr
= ndr_push_init_ctx(ndr
);
829 NDR_ERR_HAVE_NO_MEMORY(subndr
);
830 subndr
->flags
= ndr
->flags
& ~LIBNDR_FLAG_NDR64
;
833 NDR_CHECK(ndr_push_zero(subndr
, size_is
));
835 subndr
->relative_end_offset
= size_is
;
839 return NDR_ERR_SUCCESS
;
843 push a subcontext header
845 _PUBLIC_
enum ndr_err_code
ndr_push_subcontext_end(struct ndr_push
*ndr
,
846 struct ndr_push
*subndr
,
853 padding_len
= size_is
- subndr
->offset
;
854 if (padding_len
< 0) {
855 return ndr_push_error(ndr
, NDR_ERR_SUBCONTEXT
, "Bad subcontext (PUSH) content_size %d is larger than size_is(%d)",
856 (int)subndr
->offset
, (int)size_is
);
858 subndr
->offset
= size_is
;
861 switch (header_size
) {
866 NDR_CHECK(ndr_push_uint16(ndr
, NDR_SCALARS
, subndr
->offset
));
870 NDR_CHECK(ndr_push_uint3264(ndr
, NDR_SCALARS
, subndr
->offset
));
875 * Common Type Header for the Serialization Stream
876 * See [MS-RPCE] 2.2.6 Type Serialization Version 1
878 padding_len
= NDR_ROUND(subndr
->offset
, 8) - subndr
->offset
;
879 if (padding_len
> 0) {
880 NDR_CHECK(ndr_push_zero(subndr
, padding_len
));
884 NDR_CHECK(ndr_push_uint8(ndr
, NDR_SCALARS
, 1));
890 NDR_CHECK(ndr_push_uint8(ndr
, NDR_SCALARS
, NDR_BE(ndr
)?0x00:0x10));
892 /* length of the "Private Header for Constructed Type" */
893 NDR_CHECK(ndr_push_uint16(ndr
, NDR_SCALARS
, 8));
896 NDR_CHECK(ndr_push_uint32(ndr
, NDR_SCALARS
, 0xCCCCCCCC));
899 * Private Header for Constructed Type
901 /* length - will be updated latter */
902 NDR_CHECK(ndr_push_uint32(ndr
, NDR_SCALARS
, subndr
->offset
));
905 NDR_CHECK(ndr_push_uint32(ndr
, NDR_SCALARS
, 0));
909 return ndr_push_error(ndr
, NDR_ERR_SUBCONTEXT
, "Bad subcontext header size %d",
913 NDR_CHECK(ndr_push_bytes(ndr
, subndr
->data
, subndr
->offset
));
914 return NDR_ERR_SUCCESS
;
918 store a token in the ndr context, for later retrieval
920 _PUBLIC_
enum ndr_err_code
ndr_token_store(TALLOC_CTX
*mem_ctx
,
921 struct ndr_token_list
**list
,
925 struct ndr_token_list
*tok
;
926 tok
= talloc(mem_ctx
, struct ndr_token_list
);
927 NDR_ERR_HAVE_NO_MEMORY(tok
);
930 DLIST_ADD((*list
), tok
);
931 return NDR_ERR_SUCCESS
;
935 retrieve a token from a ndr context, using cmp_fn to match the tokens
937 _PUBLIC_
enum ndr_err_code
ndr_token_retrieve_cmp_fn(struct ndr_token_list
**list
, const void *key
, uint32_t *v
,
938 comparison_fn_t _cmp_fn
, bool _remove_tok
)
940 struct ndr_token_list
*tok
;
941 for (tok
=*list
;tok
;tok
=tok
->next
) {
942 if (_cmp_fn
&& _cmp_fn(tok
->key
,key
)==0) goto found
;
943 else if (!_cmp_fn
&& tok
->key
== key
) goto found
;
945 return NDR_ERR_TOKEN
;
949 DLIST_REMOVE((*list
), tok
);
952 return NDR_ERR_SUCCESS
;
956 retrieve a token from a ndr context
958 _PUBLIC_
enum ndr_err_code
ndr_token_retrieve(struct ndr_token_list
**list
, const void *key
, uint32_t *v
)
960 return ndr_token_retrieve_cmp_fn(list
, key
, v
, NULL
, true);
964 peek at but don't removed a token from a ndr context
966 _PUBLIC_
uint32_t ndr_token_peek(struct ndr_token_list
**list
, const void *key
)
968 struct ndr_token_list
*tok
;
969 for (tok
= *list
; tok
; tok
= tok
->next
) {
970 if (tok
->key
== key
) {
978 pull an array size field and add it to the array_size_list token list
980 _PUBLIC_
enum ndr_err_code
ndr_pull_array_size(struct ndr_pull
*ndr
, const void *p
)
983 NDR_CHECK(ndr_pull_uint3264(ndr
, NDR_SCALARS
, &size
));
984 return ndr_token_store(ndr
, &ndr
->array_size_list
, p
, size
);
988 get the stored array size field
990 _PUBLIC_
uint32_t ndr_get_array_size(struct ndr_pull
*ndr
, const void *p
)
992 return ndr_token_peek(&ndr
->array_size_list
, p
);
996 check the stored array size field
998 _PUBLIC_
enum ndr_err_code
ndr_check_array_size(struct ndr_pull
*ndr
, void *p
, uint32_t size
)
1001 stored
= ndr_token_peek(&ndr
->array_size_list
, p
);
1002 if (stored
!= size
) {
1003 return ndr_pull_error(ndr
, NDR_ERR_ARRAY_SIZE
,
1004 "Bad array size - got %u expected %u\n",
1007 return NDR_ERR_SUCCESS
;
1011 pull an array length field and add it to the array_length_list token list
1013 _PUBLIC_
enum ndr_err_code
ndr_pull_array_length(struct ndr_pull
*ndr
, const void *p
)
1015 uint32_t length
, offset
;
1016 NDR_CHECK(ndr_pull_uint3264(ndr
, NDR_SCALARS
, &offset
));
1018 return ndr_pull_error(ndr
, NDR_ERR_ARRAY_SIZE
,
1019 "non-zero array offset %u\n", offset
);
1021 NDR_CHECK(ndr_pull_uint3264(ndr
, NDR_SCALARS
, &length
));
1022 return ndr_token_store(ndr
, &ndr
->array_length_list
, p
, length
);
1026 get the stored array length field
1028 _PUBLIC_
uint32_t ndr_get_array_length(struct ndr_pull
*ndr
, const void *p
)
1030 return ndr_token_peek(&ndr
->array_length_list
, p
);
1034 check the stored array length field
1036 _PUBLIC_
enum ndr_err_code
ndr_check_array_length(struct ndr_pull
*ndr
, void *p
, uint32_t length
)
1039 stored
= ndr_token_peek(&ndr
->array_length_list
, p
);
1040 if (stored
!= length
) {
1041 return ndr_pull_error(ndr
, NDR_ERR_ARRAY_SIZE
,
1042 "Bad array length - got %u expected %u\n",
1045 return NDR_ERR_SUCCESS
;
1048 _PUBLIC_
enum ndr_err_code
ndr_push_pipe_chunk_trailer(struct ndr_push
*ndr
, int ndr_flags
, uint32_t count
)
1050 if (ndr
->flags
& LIBNDR_FLAG_NDR64
) {
1051 int64_t tmp
= 0 - (int64_t)count
;
1052 uint64_t ncount
= tmp
;
1054 NDR_CHECK(ndr_push_hyper(ndr
, ndr_flags
, ncount
));
1057 return NDR_ERR_SUCCESS
;
1060 _PUBLIC_
enum ndr_err_code
ndr_check_pipe_chunk_trailer(struct ndr_pull
*ndr
, int ndr_flags
, uint32_t count
)
1062 if (ndr
->flags
& LIBNDR_FLAG_NDR64
) {
1063 int64_t tmp
= 0 - (int64_t)count
;
1064 uint64_t ncount1
= tmp
;
1067 NDR_CHECK(ndr_pull_hyper(ndr
, ndr_flags
, &ncount2
));
1068 if (ncount1
== ncount2
) {
1069 return NDR_ERR_SUCCESS
;
1072 return ndr_pull_error(ndr
, NDR_ERR_ARRAY_SIZE
,
1073 "Bad pipe trailer[%lld should be %lld] size was %lu\"",
1074 (unsigned long long)ncount2
,
1075 (unsigned long long)ncount1
,
1076 (unsigned long)count
);
1079 return NDR_ERR_SUCCESS
;
1083 store a switch value
1085 _PUBLIC_
enum ndr_err_code
ndr_push_set_switch_value(struct ndr_push
*ndr
, const void *p
, uint32_t val
)
1087 return ndr_token_store(ndr
, &ndr
->switch_list
, p
, val
);
1090 _PUBLIC_
enum ndr_err_code
ndr_pull_set_switch_value(struct ndr_pull
*ndr
, const void *p
, uint32_t val
)
1092 return ndr_token_store(ndr
, &ndr
->switch_list
, p
, val
);
1095 _PUBLIC_
enum ndr_err_code
ndr_print_set_switch_value(struct ndr_print
*ndr
, const void *p
, uint32_t val
)
1097 return ndr_token_store(ndr
, &ndr
->switch_list
, p
, val
);
1101 retrieve a switch value
1103 _PUBLIC_
uint32_t ndr_push_get_switch_value(struct ndr_push
*ndr
, const void *p
)
1105 return ndr_token_peek(&ndr
->switch_list
, p
);
1108 _PUBLIC_
uint32_t ndr_pull_get_switch_value(struct ndr_pull
*ndr
, const void *p
)
1110 return ndr_token_peek(&ndr
->switch_list
, p
);
1113 _PUBLIC_
uint32_t ndr_print_get_switch_value(struct ndr_print
*ndr
, const void *p
)
1115 return ndr_token_peek(&ndr
->switch_list
, p
);
1118 /* retrieve a switch value and remove it from the list */
1119 _PUBLIC_
uint32_t ndr_pull_steal_switch_value(struct ndr_pull
*ndr
, const void *p
)
1121 enum ndr_err_code status
;
1124 status
= ndr_token_retrieve(&ndr
->switch_list
, p
, &v
);
1125 if (!NDR_ERR_CODE_IS_SUCCESS(status
)) {
1133 pull a struct from a blob using NDR
1135 _PUBLIC_
enum ndr_err_code
ndr_pull_struct_blob(const DATA_BLOB
*blob
, TALLOC_CTX
*mem_ctx
, void *p
,
1136 ndr_pull_flags_fn_t fn
)
1138 struct ndr_pull
*ndr
;
1139 ndr
= ndr_pull_init_blob(blob
, mem_ctx
);
1140 NDR_ERR_HAVE_NO_MEMORY(ndr
);
1141 NDR_CHECK_FREE(fn(ndr
, NDR_SCALARS
|NDR_BUFFERS
, p
));
1143 return NDR_ERR_SUCCESS
;
1147 pull a struct from a blob using NDR - failing if all bytes are not consumed
1149 _PUBLIC_
enum ndr_err_code
ndr_pull_struct_blob_all(const DATA_BLOB
*blob
, TALLOC_CTX
*mem_ctx
,
1150 void *p
, ndr_pull_flags_fn_t fn
)
1152 struct ndr_pull
*ndr
;
1153 uint32_t highest_ofs
;
1154 ndr
= ndr_pull_init_blob(blob
, mem_ctx
);
1155 NDR_ERR_HAVE_NO_MEMORY(ndr
);
1156 NDR_CHECK_FREE(fn(ndr
, NDR_SCALARS
|NDR_BUFFERS
, p
));
1157 if (ndr
->offset
> ndr
->relative_highest_offset
) {
1158 highest_ofs
= ndr
->offset
;
1160 highest_ofs
= ndr
->relative_highest_offset
;
1162 if (highest_ofs
< ndr
->data_size
) {
1163 enum ndr_err_code ret
;
1164 ret
= ndr_pull_error(ndr
, NDR_ERR_UNREAD_BYTES
,
1165 "not all bytes consumed ofs[%u] size[%u]",
1166 highest_ofs
, ndr
->data_size
);
1171 return NDR_ERR_SUCCESS
;
1175 pull a struct from a blob using NDR - failing if all bytes are not consumed
1177 This only works for structures with NO allocated memory, like
1178 objectSID and GUID. This helps because we parse these a lot.
1180 _PUBLIC_
enum ndr_err_code
ndr_pull_struct_blob_all_noalloc(const DATA_BLOB
*blob
,
1181 void *p
, ndr_pull_flags_fn_t fn
)
1184 * We init this structure on the stack here, to avoid a
1185 * talloc() as otherwise this call to the fn() is assured not
1186 * to be doing any allocation, eg SIDs and GUIDs.
1188 * This allows us to keep the safety of the PIDL-generated
1189 * code without the talloc() overhead.
1191 struct ndr_pull ndr
= {
1193 .data_size
= blob
->length
,
1194 .current_mem_ctx
= (void *)-1
1196 uint32_t highest_ofs
;
1197 NDR_CHECK(fn(&ndr
, NDR_SCALARS
|NDR_BUFFERS
, p
));
1198 if (ndr
.offset
> ndr
.relative_highest_offset
) {
1199 highest_ofs
= ndr
.offset
;
1201 highest_ofs
= ndr
.relative_highest_offset
;
1203 if (highest_ofs
< ndr
.data_size
) {
1204 enum ndr_err_code ret
;
1205 ret
= ndr_pull_error(&ndr
, NDR_ERR_UNREAD_BYTES
,
1206 "not all bytes consumed ofs[%u] size[%u]",
1207 highest_ofs
, ndr
.data_size
);
1210 return NDR_ERR_SUCCESS
;
1214 pull a union from a blob using NDR, given the union discriminator
1216 _PUBLIC_
enum ndr_err_code
ndr_pull_union_blob(const DATA_BLOB
*blob
, TALLOC_CTX
*mem_ctx
,
1218 uint32_t level
, ndr_pull_flags_fn_t fn
)
1220 struct ndr_pull
*ndr
;
1221 ndr
= ndr_pull_init_blob(blob
, mem_ctx
);
1222 NDR_ERR_HAVE_NO_MEMORY(ndr
);
1223 NDR_CHECK_FREE(ndr_pull_set_switch_value(ndr
, p
, level
));
1224 NDR_CHECK_FREE(fn(ndr
, NDR_SCALARS
|NDR_BUFFERS
, p
));
1226 return NDR_ERR_SUCCESS
;
1230 pull a union from a blob using NDR, given the union discriminator,
1231 failing if all bytes are not consumed
1233 _PUBLIC_
enum ndr_err_code
ndr_pull_union_blob_all(const DATA_BLOB
*blob
, TALLOC_CTX
*mem_ctx
,
1235 uint32_t level
, ndr_pull_flags_fn_t fn
)
1237 struct ndr_pull
*ndr
;
1238 uint32_t highest_ofs
;
1239 ndr
= ndr_pull_init_blob(blob
, mem_ctx
);
1240 NDR_ERR_HAVE_NO_MEMORY(ndr
);
1241 NDR_CHECK_FREE(ndr_pull_set_switch_value(ndr
, p
, level
));
1242 NDR_CHECK_FREE(fn(ndr
, NDR_SCALARS
|NDR_BUFFERS
, p
));
1243 if (ndr
->offset
> ndr
->relative_highest_offset
) {
1244 highest_ofs
= ndr
->offset
;
1246 highest_ofs
= ndr
->relative_highest_offset
;
1248 if (highest_ofs
< ndr
->data_size
) {
1249 enum ndr_err_code ret
;
1250 ret
= ndr_pull_error(ndr
, NDR_ERR_UNREAD_BYTES
,
1251 "not all bytes consumed ofs[%u] size[%u]",
1252 highest_ofs
, ndr
->data_size
);
1257 return NDR_ERR_SUCCESS
;
1261 push a struct to a blob using NDR
1263 _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
)
1265 struct ndr_push
*ndr
;
1266 ndr
= ndr_push_init_ctx(mem_ctx
);
1267 NDR_ERR_HAVE_NO_MEMORY(ndr
);
1269 NDR_CHECK(fn(ndr
, NDR_SCALARS
|NDR_BUFFERS
, p
));
1271 *blob
= ndr_push_blob(ndr
);
1272 talloc_steal(mem_ctx
, blob
->data
);
1275 return NDR_ERR_SUCCESS
;
1279 push a struct into a provided blob using NDR.
1281 We error because we want to have the performance issue (extra
1282 talloc() calls) show up as an error, not just slower code. This is
1283 used for things like GUIDs, which we expect to be a fixed size, and
1284 SIDs that we can pre-calculate the size for.
1286 _PUBLIC_
enum ndr_err_code
ndr_push_struct_into_fixed_blob(
1287 DATA_BLOB
*blob
, const void *p
, ndr_push_flags_fn_t fn
)
1289 struct ndr_push ndr
= {
1291 .alloc_size
= blob
->length
,
1292 .fixed_buf_size
= true
1295 NDR_CHECK(fn(&ndr
, NDR_SCALARS
|NDR_BUFFERS
, p
));
1297 if (ndr
.offset
!= blob
->length
) {
1298 return ndr_push_error(&ndr
, NDR_ERR_BUFSIZE
,
1299 "buffer was either to large or small "
1300 "ofs[%u] size[%zu]",
1301 ndr
.offset
, blob
->length
);
1304 return NDR_ERR_SUCCESS
;
1308 push a union to a blob using NDR
1310 _PUBLIC_
enum ndr_err_code
ndr_push_union_blob(DATA_BLOB
*blob
, TALLOC_CTX
*mem_ctx
, void *p
,
1311 uint32_t level
, ndr_push_flags_fn_t fn
)
1313 struct ndr_push
*ndr
;
1314 ndr
= ndr_push_init_ctx(mem_ctx
);
1315 NDR_ERR_HAVE_NO_MEMORY(ndr
);
1317 NDR_CHECK(ndr_push_set_switch_value(ndr
, p
, level
));
1318 NDR_CHECK(fn(ndr
, NDR_SCALARS
|NDR_BUFFERS
, p
));
1320 *blob
= ndr_push_blob(ndr
);
1321 talloc_steal(mem_ctx
, blob
->data
);
1324 return NDR_ERR_SUCCESS
;
1328 generic ndr_size_*() handler for structures
1330 _PUBLIC_
size_t ndr_size_struct(const void *p
, int flags
, ndr_push_flags_fn_t push
)
1332 struct ndr_push
*ndr
;
1333 enum ndr_err_code status
;
1336 /* avoid recursion */
1337 if (flags
& LIBNDR_FLAG_NO_NDR_SIZE
) return 0;
1339 ndr
= ndr_push_init_ctx(NULL
);
1341 ndr
->flags
|= flags
| LIBNDR_FLAG_NO_NDR_SIZE
;
1342 status
= push(ndr
, NDR_SCALARS
|NDR_BUFFERS
, discard_const(p
));
1343 if (!NDR_ERR_CODE_IS_SUCCESS(status
)) {
1353 generic ndr_size_*() handler for unions
1355 _PUBLIC_
size_t ndr_size_union(const void *p
, int flags
, uint32_t level
, ndr_push_flags_fn_t push
)
1357 struct ndr_push
*ndr
;
1358 enum ndr_err_code status
;
1361 /* avoid recursion */
1362 if (flags
& LIBNDR_FLAG_NO_NDR_SIZE
) return 0;
1364 ndr
= ndr_push_init_ctx(NULL
);
1366 ndr
->flags
|= flags
| LIBNDR_FLAG_NO_NDR_SIZE
;
1368 status
= ndr_push_set_switch_value(ndr
, p
, level
);
1369 if (!NDR_ERR_CODE_IS_SUCCESS(status
)) {
1373 status
= push(ndr
, NDR_SCALARS
|NDR_BUFFERS
, p
);
1374 if (!NDR_ERR_CODE_IS_SUCCESS(status
)) {
1384 get the current base for relative pointers for the push
1386 _PUBLIC_
uint32_t ndr_push_get_relative_base_offset(struct ndr_push
*ndr
)
1388 return ndr
->relative_base_offset
;
1392 restore the old base for relative pointers for the push
1394 _PUBLIC_
void ndr_push_restore_relative_base_offset(struct ndr_push
*ndr
, uint32_t offset
)
1396 ndr
->relative_base_offset
= offset
;
1400 setup the current base for relative pointers for the push
1401 called in the NDR_SCALAR stage
1403 _PUBLIC_
enum ndr_err_code
ndr_push_setup_relative_base_offset1(struct ndr_push
*ndr
, const void *p
, uint32_t offset
)
1405 ndr
->relative_base_offset
= offset
;
1406 return ndr_token_store(ndr
, &ndr
->relative_base_list
, p
, offset
);
1410 setup the current base for relative pointers for the push
1411 called in the NDR_BUFFERS stage
1413 _PUBLIC_
enum ndr_err_code
ndr_push_setup_relative_base_offset2(struct ndr_push
*ndr
, const void *p
)
1415 return ndr_token_retrieve(&ndr
->relative_base_list
, p
, &ndr
->relative_base_offset
);
1419 push a relative object - stage1
1420 this is called during SCALARS processing
1422 _PUBLIC_
enum ndr_err_code
ndr_push_relative_ptr1(struct ndr_push
*ndr
, const void *p
)
1425 NDR_CHECK(ndr_push_uint32(ndr
, NDR_SCALARS
, 0));
1426 return NDR_ERR_SUCCESS
;
1428 NDR_CHECK(ndr_push_align(ndr
, 4));
1429 NDR_CHECK(ndr_token_store(ndr
, &ndr
->relative_list
, p
, ndr
->offset
));
1430 return ndr_push_uint32(ndr
, NDR_SCALARS
, 0xFFFFFFFF);
1434 push a short relative object - stage1
1435 this is called during SCALARS processing
1437 _PUBLIC_
enum ndr_err_code
ndr_push_short_relative_ptr1(struct ndr_push
*ndr
, const void *p
)
1440 NDR_CHECK(ndr_push_uint16(ndr
, NDR_SCALARS
, 0));
1441 return NDR_ERR_SUCCESS
;
1443 NDR_CHECK(ndr_push_align(ndr
, 2));
1444 NDR_CHECK(ndr_token_store(ndr
, &ndr
->relative_list
, p
, ndr
->offset
));
1445 return ndr_push_uint16(ndr
, NDR_SCALARS
, 0xFFFF);
1448 push a relative object - stage2
1449 this is called during buffers processing
1451 static enum ndr_err_code
ndr_push_relative_ptr2(struct ndr_push
*ndr
, const void *p
)
1453 uint32_t save_offset
;
1454 uint32_t ptr_offset
= 0xFFFFFFFF;
1456 return NDR_ERR_SUCCESS
;
1458 save_offset
= ndr
->offset
;
1459 NDR_CHECK(ndr_token_retrieve(&ndr
->relative_list
, p
, &ptr_offset
));
1460 if (ptr_offset
> ndr
->offset
) {
1461 return ndr_push_error(ndr
, NDR_ERR_BUFSIZE
,
1462 "ndr_push_relative_ptr2 ptr_offset(%u) > ndr->offset(%u)",
1463 ptr_offset
, ndr
->offset
);
1465 ndr
->offset
= ptr_offset
;
1466 if (save_offset
< ndr
->relative_base_offset
) {
1467 return ndr_push_error(ndr
, NDR_ERR_BUFSIZE
,
1468 "ndr_push_relative_ptr2 save_offset(%u) < ndr->relative_base_offset(%u)",
1469 save_offset
, ndr
->relative_base_offset
);
1471 NDR_CHECK(ndr_push_uint32(ndr
, NDR_SCALARS
, save_offset
- ndr
->relative_base_offset
));
1472 ndr
->offset
= save_offset
;
1473 return NDR_ERR_SUCCESS
;
1476 push a short relative object - stage2
1477 this is called during buffers processing
1479 _PUBLIC_
enum ndr_err_code
ndr_push_short_relative_ptr2(struct ndr_push
*ndr
, const void *p
)
1481 uint32_t save_offset
;
1482 uint32_t ptr_offset
= 0xFFFF;
1483 uint32_t relative_offset
;
1488 return NDR_ERR_SUCCESS
;
1491 if (ndr
->offset
< ndr
->relative_base_offset
) {
1492 return ndr_push_error(ndr
, NDR_ERR_BUFSIZE
,
1493 "ndr_push_relative_ptr2 ndr->offset(%u) < ndr->relative_base_offset(%u)",
1494 ndr
->offset
, ndr
->relative_base_offset
);
1497 relative_offset
= ndr
->offset
- ndr
->relative_base_offset
;
1499 if (ndr
->flags
& LIBNDR_FLAG_NOALIGN
) {
1501 } else if (ndr
->flags
& LIBNDR_FLAG_ALIGN2
) {
1503 } else if (ndr
->flags
& LIBNDR_FLAG_ALIGN4
) {
1505 } else if (ndr
->flags
& LIBNDR_FLAG_ALIGN8
) {
1509 pad
= ndr_align_size(relative_offset
, align
);
1511 NDR_CHECK(ndr_push_zero(ndr
, pad
));
1514 relative_offset
= ndr
->offset
- ndr
->relative_base_offset
;
1515 if (relative_offset
> UINT16_MAX
) {
1516 return ndr_push_error(ndr
, NDR_ERR_BUFSIZE
,
1517 "ndr_push_relative_ptr2 relative_offset(%u) > UINT16_MAX",
1521 save_offset
= ndr
->offset
;
1522 NDR_CHECK(ndr_token_retrieve(&ndr
->relative_list
, p
, &ptr_offset
));
1523 if (ptr_offset
> ndr
->offset
) {
1524 return ndr_push_error(ndr
, NDR_ERR_BUFSIZE
,
1525 "ndr_push_short_relative_ptr2 ptr_offset(%u) > ndr->offset(%u)",
1526 ptr_offset
, ndr
->offset
);
1528 ndr
->offset
= ptr_offset
;
1529 NDR_CHECK(ndr_push_uint16(ndr
, NDR_SCALARS
, relative_offset
));
1530 ndr
->offset
= save_offset
;
1531 return NDR_ERR_SUCCESS
;
1535 push a relative object - stage2 start
1536 this is called during buffers processing
1538 _PUBLIC_
enum ndr_err_code
ndr_push_relative_ptr2_start(struct ndr_push
*ndr
, const void *p
)
1541 return NDR_ERR_SUCCESS
;
1543 if (!(ndr
->flags
& LIBNDR_FLAG_RELATIVE_REVERSE
)) {
1544 uint32_t relative_offset
;
1548 if (ndr
->offset
< ndr
->relative_base_offset
) {
1549 return ndr_push_error(ndr
, NDR_ERR_BUFSIZE
,
1550 "ndr_push_relative_ptr2_start ndr->offset(%u) < ndr->relative_base_offset(%u)",
1551 ndr
->offset
, ndr
->relative_base_offset
);
1554 relative_offset
= ndr
->offset
- ndr
->relative_base_offset
;
1556 if (ndr
->flags
& LIBNDR_FLAG_NOALIGN
) {
1558 } else if (ndr
->flags
& LIBNDR_FLAG_ALIGN2
) {
1560 } else if (ndr
->flags
& LIBNDR_FLAG_ALIGN4
) {
1562 } else if (ndr
->flags
& LIBNDR_FLAG_ALIGN8
) {
1566 pad
= ndr_align_size(relative_offset
, align
);
1568 NDR_CHECK(ndr_push_zero(ndr
, pad
));
1571 return ndr_push_relative_ptr2(ndr
, p
);
1573 if (ndr
->relative_end_offset
== -1) {
1574 return ndr_push_error(ndr
, NDR_ERR_RELATIVE
,
1575 "ndr_push_relative_ptr2_start RELATIVE_REVERSE flag set and relative_end_offset %d",
1576 ndr
->relative_end_offset
);
1578 NDR_CHECK(ndr_token_store(ndr
, &ndr
->relative_begin_list
, p
, ndr
->offset
));
1579 return NDR_ERR_SUCCESS
;
1583 push a relative object - stage2 end
1584 this is called during buffers processing
1586 _PUBLIC_
enum ndr_err_code
ndr_push_relative_ptr2_end(struct ndr_push
*ndr
, const void *p
)
1588 uint32_t begin_offset
= 0xFFFFFFFF;
1590 uint32_t correct_offset
= 0;
1595 return NDR_ERR_SUCCESS
;
1598 if (!(ndr
->flags
& LIBNDR_FLAG_RELATIVE_REVERSE
)) {
1599 return NDR_ERR_SUCCESS
;
1602 if (ndr
->flags
& LIBNDR_FLAG_NO_NDR_SIZE
) {
1603 /* better say more than calculation a too small buffer */
1604 NDR_PUSH_ALIGN(ndr
, 8);
1605 return NDR_ERR_SUCCESS
;
1608 if (ndr
->relative_end_offset
< ndr
->offset
) {
1609 return ndr_push_error(ndr
, NDR_ERR_RELATIVE
,
1610 "ndr_push_relative_ptr2_end:"
1611 "relative_end_offset %u < offset %u",
1612 ndr
->relative_end_offset
, ndr
->offset
);
1615 NDR_CHECK(ndr_token_retrieve(&ndr
->relative_begin_list
, p
, &begin_offset
));
1617 /* we have marshalled a buffer, see how long it was */
1618 len
= ndr
->offset
- begin_offset
;
1621 return ndr_push_error(ndr
, NDR_ERR_RELATIVE
,
1622 "ndr_push_relative_ptr2_end:"
1623 "offset %u - begin_offset %u < 0",
1624 ndr
->offset
, begin_offset
);
1627 if (ndr
->relative_end_offset
< len
) {
1628 return ndr_push_error(ndr
, NDR_ERR_RELATIVE
,
1629 "ndr_push_relative_ptr2_end:"
1630 "relative_end_offset %u < len %lld",
1631 ndr
->offset
, (long long)len
);
1634 /* the reversed offset is at the end of the main buffer */
1635 correct_offset
= ndr
->relative_end_offset
- len
;
1637 if (ndr
->flags
& LIBNDR_FLAG_NOALIGN
) {
1639 } else if (ndr
->flags
& LIBNDR_FLAG_ALIGN2
) {
1641 } else if (ndr
->flags
& LIBNDR_FLAG_ALIGN4
) {
1643 } else if (ndr
->flags
& LIBNDR_FLAG_ALIGN8
) {
1647 pad
= ndr_align_size(correct_offset
, align
);
1649 correct_offset
+= pad
;
1650 correct_offset
-= align
;
1653 if (correct_offset
< begin_offset
) {
1654 return ndr_push_error(ndr
, NDR_ERR_RELATIVE
,
1655 "ndr_push_relative_ptr2_end: "
1656 "correct_offset %u < begin_offset %u",
1657 correct_offset
, begin_offset
);
1661 uint32_t clear_size
= correct_offset
- begin_offset
;
1663 clear_size
= MIN(clear_size
, len
);
1665 /* now move the marshalled buffer to the end of the main buffer */
1666 memmove(ndr
->data
+ correct_offset
, ndr
->data
+ begin_offset
, len
);
1669 /* and wipe out old buffer within the main buffer */
1670 memset(ndr
->data
+ begin_offset
, '\0', clear_size
);
1674 /* and set the end offset for the next buffer */
1675 ndr
->relative_end_offset
= correct_offset
;
1677 /* finally write the offset to the main buffer */
1678 ndr
->offset
= correct_offset
;
1679 NDR_CHECK(ndr_push_relative_ptr2(ndr
, p
));
1681 /* restore to where we were in the main buffer */
1682 ndr
->offset
= begin_offset
;
1684 return NDR_ERR_SUCCESS
;
1688 get the current base for relative pointers for the pull
1690 _PUBLIC_
uint32_t ndr_pull_get_relative_base_offset(struct ndr_pull
*ndr
)
1692 return ndr
->relative_base_offset
;
1696 restore the old base for relative pointers for the pull
1698 _PUBLIC_
void ndr_pull_restore_relative_base_offset(struct ndr_pull
*ndr
, uint32_t offset
)
1700 ndr
->relative_base_offset
= offset
;
1704 setup the current base for relative pointers for the pull
1705 called in the NDR_SCALAR stage
1707 _PUBLIC_
enum ndr_err_code
ndr_pull_setup_relative_base_offset1(struct ndr_pull
*ndr
, const void *p
, uint32_t offset
)
1709 ndr
->relative_base_offset
= offset
;
1710 return ndr_token_store(ndr
, &ndr
->relative_base_list
, p
, offset
);
1714 setup the current base for relative pointers for the pull
1715 called in the NDR_BUFFERS stage
1717 _PUBLIC_
enum ndr_err_code
ndr_pull_setup_relative_base_offset2(struct ndr_pull
*ndr
, const void *p
)
1719 return ndr_token_retrieve(&ndr
->relative_base_list
, p
, &ndr
->relative_base_offset
);
1723 pull a relative object - stage1
1724 called during SCALARS processing
1726 _PUBLIC_
enum ndr_err_code
ndr_pull_relative_ptr1(struct ndr_pull
*ndr
, const void *p
, uint32_t rel_offset
)
1728 rel_offset
+= ndr
->relative_base_offset
;
1729 if (rel_offset
> ndr
->data_size
) {
1730 return ndr_pull_error(ndr
, NDR_ERR_BUFSIZE
,
1731 "ndr_pull_relative_ptr1 rel_offset(%u) > ndr->data_size(%u)",
1732 rel_offset
, ndr
->data_size
);
1734 return ndr_token_store(ndr
, &ndr
->relative_list
, p
, rel_offset
);
1738 pull a relative object - stage2
1739 called during BUFFERS processing
1741 _PUBLIC_
enum ndr_err_code
ndr_pull_relative_ptr2(struct ndr_pull
*ndr
, const void *p
)
1743 uint32_t rel_offset
;
1744 NDR_CHECK(ndr_token_retrieve(&ndr
->relative_list
, p
, &rel_offset
));
1745 return ndr_pull_set_offset(ndr
, rel_offset
);
1748 const static struct {
1749 enum ndr_err_code err
;
1751 } ndr_err_code_strings
[] = {
1752 { NDR_ERR_SUCCESS
, "Success" },
1753 { NDR_ERR_ARRAY_SIZE
, "Bad Array Size" },
1754 { NDR_ERR_BAD_SWITCH
, "Bad Switch" },
1755 { NDR_ERR_OFFSET
, "Offset Error" },
1756 { NDR_ERR_RELATIVE
, "Relative Pointer Error" },
1757 { NDR_ERR_CHARCNV
, "Character Conversion Error" },
1758 { NDR_ERR_LENGTH
, "Length Error" },
1759 { NDR_ERR_SUBCONTEXT
, "Subcontext Error" },
1760 { NDR_ERR_COMPRESSION
, "Compression Error" },
1761 { NDR_ERR_STRING
, "String Error" },
1762 { NDR_ERR_VALIDATE
, "Validate Error" },
1763 { NDR_ERR_BUFSIZE
, "Buffer Size Error" },
1764 { NDR_ERR_ALLOC
, "Allocation Error" },
1765 { NDR_ERR_RANGE
, "Range Error" },
1766 { NDR_ERR_TOKEN
, "Token Error" },
1767 { NDR_ERR_IPV4ADDRESS
, "IPv4 Address Error" },
1768 { NDR_ERR_INVALID_POINTER
, "Invalid Pointer" },
1769 { NDR_ERR_UNREAD_BYTES
, "Unread Bytes" },
1770 { NDR_ERR_NDR64
, "NDR64 assertion error" },
1771 { NDR_ERR_INCOMPLETE_BUFFER
, "Incomplete Buffer" },
1775 _PUBLIC_
const char *ndr_map_error2string(enum ndr_err_code ndr_err
)
1778 for (i
= 0; ndr_err_code_strings
[i
].string
!= NULL
; i
++) {
1779 if (ndr_err_code_strings
[i
].err
== ndr_err
)
1780 return ndr_err_code_strings
[i
].string
;
1782 return "Unknown error";