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 arbitary
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 aligment 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
+1 > ndr
->alloc_size
) {
290 ndr
->alloc_size
= size
+1;
292 ndr
->data
= talloc_realloc(ndr
, ndr
->data
, uint8_t, ndr
->alloc_size
);
294 return ndr_push_error(ndr
, NDR_ERR_ALLOC
, "Failed to push_expand to %u",
298 return NDR_ERR_SUCCESS
;
301 _PUBLIC_
void ndr_print_debugc_helper(struct ndr_print
*ndr
, const char *format
, ...)
309 va_start(ap
, format
);
310 ret
= vasprintf(&s
, format
, ap
);
317 dbgc_class
= *(int *)ndr
->private_data
;
319 if (ndr
->no_newline
) {
320 DEBUGADDC(dbgc_class
, 1,("%s", s
));
325 for (i
=0;i
<ndr
->depth
;i
++) {
326 DEBUGADDC(dbgc_class
, 1,(" "));
329 DEBUGADDC(dbgc_class
, 1,("%s\n", s
));
333 _PUBLIC_
void ndr_print_debug_helper(struct ndr_print
*ndr
, const char *format
, ...)
340 va_start(ap
, format
);
341 ret
= vasprintf(&s
, format
, ap
);
348 if (ndr
->no_newline
) {
349 DEBUGADD(1,("%s", s
));
354 for (i
=0;i
<ndr
->depth
;i
++) {
358 DEBUGADD(1,("%s\n", s
));
362 _PUBLIC_
void ndr_print_printf_helper(struct ndr_print
*ndr
, const char *format
, ...)
367 if (!ndr
->no_newline
) {
368 for (i
=0;i
<ndr
->depth
;i
++) {
373 va_start(ap
, format
);
376 if (!ndr
->no_newline
) {
381 _PUBLIC_
void ndr_print_string_helper(struct ndr_print
*ndr
, const char *format
, ...)
386 if (!ndr
->no_newline
) {
387 for (i
=0;i
<ndr
->depth
;i
++) {
388 ndr
->private_data
= talloc_asprintf_append_buffer(
389 (char *)ndr
->private_data
, " ");
393 va_start(ap
, format
);
394 ndr
->private_data
= talloc_vasprintf_append_buffer((char *)ndr
->private_data
,
397 if (!ndr
->no_newline
) {
398 ndr
->private_data
= talloc_asprintf_append_buffer((char *)ndr
->private_data
,
404 a useful helper function for printing idl structures via DEBUGC()
406 _PUBLIC_
void ndr_print_debugc(int dbgc_class
, ndr_print_fn_t fn
, const char *name
, void *ptr
)
408 struct ndr_print
*ndr
;
410 DEBUGC(dbgc_class
, 1,(" "));
412 ndr
= talloc_zero(NULL
, struct ndr_print
);
414 ndr
->private_data
= &dbgc_class
;
415 ndr
->print
= ndr_print_debugc_helper
;
418 #ifdef DEBUG_PASSWORD
419 if (CHECK_DEBUGLVL(100)) {
420 ndr
->print_secrets
= true;
429 a useful helper function for printing idl structures via DEBUG()
431 _PUBLIC_
bool ndr_print_debug(int level
,
435 const char *location
,
436 const char *function
)
438 struct ndr_print
*ndr
;
440 DEBUGLF(level
, (" "), location
, function
);
442 ndr
= talloc_zero(NULL
, struct ndr_print
);
443 if (!ndr
) return false;
444 ndr
->print
= ndr_print_debug_helper
;
447 #ifdef DEBUG_PASSWORD
448 if (CHECK_DEBUGLVL(100)) {
449 ndr
->print_secrets
= true;
459 a useful helper function for printing idl unions via DEBUG()
461 _PUBLIC_
void ndr_print_union_debug(ndr_print_fn_t fn
, const char *name
, uint32_t level
, void *ptr
)
463 struct ndr_print
*ndr
;
467 ndr
= talloc_zero(NULL
, struct ndr_print
);
469 ndr
->print
= ndr_print_debug_helper
;
472 #ifdef DEBUG_PASSWORD
473 if (CHECK_DEBUGLVL(100)) {
474 ndr
->print_secrets
= true;
478 ndr_print_set_switch_value(ndr
, ptr
, level
);
484 a useful helper function for printing idl function calls via DEBUG()
486 _PUBLIC_
void ndr_print_function_debug(ndr_print_function_t fn
, const char *name
, int flags
, void *ptr
)
488 struct ndr_print
*ndr
;
492 ndr
= talloc_zero(NULL
, struct ndr_print
);
494 ndr
->print
= ndr_print_debug_helper
;
497 #ifdef DEBUG_PASSWORD
498 if (CHECK_DEBUGLVL(100)) {
499 ndr
->print_secrets
= true;
503 fn(ndr
, name
, flags
, ptr
);
508 a useful helper function for printing idl structures to a string
510 _PUBLIC_
char *ndr_print_struct_string(TALLOC_CTX
*mem_ctx
, ndr_print_fn_t fn
, const char *name
, void *ptr
)
512 struct ndr_print
*ndr
;
515 ndr
= talloc_zero(mem_ctx
, struct ndr_print
);
516 if (!ndr
) return NULL
;
517 ndr
->private_data
= talloc_strdup(ndr
, "");
518 if (!ndr
->private_data
) {
521 ndr
->print
= ndr_print_string_helper
;
526 ret
= talloc_steal(mem_ctx
, (char *)ndr
->private_data
);
533 a useful helper function for printing idl unions to a string
535 _PUBLIC_
char *ndr_print_union_string(TALLOC_CTX
*mem_ctx
, ndr_print_fn_t fn
, const char *name
, uint32_t level
, void *ptr
)
537 struct ndr_print
*ndr
;
540 ndr
= talloc_zero(mem_ctx
, struct ndr_print
);
541 if (!ndr
) return NULL
;
542 ndr
->private_data
= talloc_strdup(ndr
, "");
543 if (!ndr
->private_data
) {
546 ndr
->print
= ndr_print_string_helper
;
549 ndr_print_set_switch_value(ndr
, ptr
, level
);
551 ret
= talloc_steal(mem_ctx
, (char *)ndr
->private_data
);
558 a useful helper function for printing idl function calls to a string
560 _PUBLIC_
char *ndr_print_function_string(TALLOC_CTX
*mem_ctx
,
561 ndr_print_function_t fn
, const char *name
,
562 int flags
, void *ptr
)
564 struct ndr_print
*ndr
;
567 ndr
= talloc_zero(mem_ctx
, struct ndr_print
);
568 if (!ndr
) return NULL
;
569 ndr
->private_data
= talloc_strdup(ndr
, "");
570 if (!ndr
->private_data
) {
573 ndr
->print
= ndr_print_string_helper
;
576 fn(ndr
, name
, flags
, ptr
);
577 ret
= talloc_steal(mem_ctx
, (char *)ndr
->private_data
);
583 _PUBLIC_
void ndr_set_flags(uint32_t *pflags
, uint32_t new_flags
)
585 /* the big/little endian flags are inter-dependent */
586 if (new_flags
& LIBNDR_FLAG_LITTLE_ENDIAN
) {
587 (*pflags
) &= ~LIBNDR_FLAG_BIGENDIAN
;
588 (*pflags
) &= ~LIBNDR_FLAG_NDR64
;
590 if (new_flags
& LIBNDR_FLAG_BIGENDIAN
) {
591 (*pflags
) &= ~LIBNDR_FLAG_LITTLE_ENDIAN
;
592 (*pflags
) &= ~LIBNDR_FLAG_NDR64
;
594 if (new_flags
& LIBNDR_ALIGN_FLAGS
) {
595 /* Ensure we only have the passed-in
596 align flag set in the new_flags,
597 remove any old align flag. */
598 (*pflags
) &= ~LIBNDR_ALIGN_FLAGS
;
600 if (new_flags
& LIBNDR_FLAG_NO_RELATIVE_REVERSE
) {
601 (*pflags
) &= ~LIBNDR_FLAG_RELATIVE_REVERSE
;
603 (*pflags
) |= new_flags
;
607 return and possibly log an NDR error
609 _PUBLIC_
enum ndr_err_code
_ndr_pull_error(struct ndr_pull
*ndr
,
610 enum ndr_err_code ndr_err
,
611 const char *function
,
612 const char *location
,
613 const char *format
, ...)
619 if (ndr
->flags
& LIBNDR_FLAG_INCOMPLETE_BUFFER
) {
621 case NDR_ERR_BUFSIZE
:
622 return NDR_ERR_INCOMPLETE_BUFFER
;
628 va_start(ap
, format
);
629 ret
= vasprintf(&s
, format
, ap
);
633 return NDR_ERR_ALLOC
;
636 D_WARNING("%s: ndr_pull_error(%s): %s at %s\n",
638 ndr_map_error2string(ndr_err
),
648 return and possibly log an NDR error
650 _PUBLIC_
enum ndr_err_code
_ndr_push_error(struct ndr_push
*ndr
,
651 enum ndr_err_code ndr_err
,
652 const char *function
,
653 const char *location
,
654 const char *format
, ...)
660 va_start(ap
, format
);
661 ret
= vasprintf(&s
, format
, ap
);
665 return NDR_ERR_ALLOC
;
668 D_WARNING("%s: ndr_push_error(%s): %s at %s\n",
670 ndr_map_error2string(ndr_err
),
680 handle subcontext buffers, which in midl land are user-marshalled, but
681 we use magic in pidl to make them easier to cope with
683 _PUBLIC_
enum ndr_err_code
ndr_pull_subcontext_start(struct ndr_pull
*ndr
,
684 struct ndr_pull
**_subndr
,
688 struct ndr_pull
*subndr
;
689 uint32_t r_content_size
;
690 bool force_le
= false;
691 bool force_be
= false;
693 switch (header_size
) {
695 uint32_t content_size
= ndr
->data_size
- ndr
->offset
;
697 content_size
= size_is
;
699 r_content_size
= content_size
;
704 uint16_t content_size
;
705 NDR_CHECK(ndr_pull_uint16(ndr
, NDR_SCALARS
, &content_size
));
706 if (size_is
>= 0 && size_is
!= content_size
) {
707 return ndr_pull_error(ndr
, NDR_ERR_SUBCONTEXT
, "Bad subcontext (PULL) size_is(%d) (0x%04x) mismatch content_size %d (0x%04x)",
708 (int)size_is
, (int)size_is
,
712 r_content_size
= content_size
;
717 uint32_t content_size
;
718 NDR_CHECK(ndr_pull_uint3264(ndr
, NDR_SCALARS
, &content_size
));
719 if (size_is
>= 0 && size_is
!= content_size
) {
720 return ndr_pull_error(ndr
, NDR_ERR_SUBCONTEXT
, "Bad subcontext (PULL) size_is(%d) (0x%08x) mismatch content_size %d (0x%08x)",
721 (int)size_is
, (int)size_is
,
725 r_content_size
= content_size
;
730 * Common Type Header for the Serialization Stream
731 * See [MS-RPCE] 2.2.6 Type Serialization Version 1
737 uint32_t content_size
;
741 NDR_CHECK(ndr_pull_uint8(ndr
, NDR_SCALARS
, &version
));
744 return ndr_pull_error(ndr
, NDR_ERR_SUBCONTEXT
,
745 "Bad subcontext (PULL) Common Type Header version %d != 1",
753 NDR_CHECK(ndr_pull_uint8(ndr
, NDR_SCALARS
, &drep
));
756 } else if (drep
== 0x00) {
759 return ndr_pull_error(ndr
, NDR_ERR_SUBCONTEXT
,
760 "Bad subcontext (PULL) Common Type Header invalid drep 0x%02X",
764 /* length of the "Private Header for Constructed Type" */
765 NDR_CHECK(ndr_pull_uint16(ndr
, NDR_SCALARS
, &hdrlen
));
767 return ndr_pull_error(ndr
, NDR_ERR_SUBCONTEXT
,
768 "Bad subcontext (PULL) Common Type Header length %d != 8",
772 /* filler should be ignored */
773 NDR_CHECK(ndr_pull_uint32(ndr
, NDR_SCALARS
, &filler
));
776 * Private Header for Constructed Type
778 /* length - will be updated latter */
779 NDR_CHECK(ndr_pull_uint32(ndr
, NDR_SCALARS
, &content_size
));
780 if (size_is
>= 0 && size_is
!= content_size
) {
781 return ndr_pull_error(ndr
, NDR_ERR_SUBCONTEXT
, "Bad subcontext (PULL) size_is(%d) mismatch content_size %d",
782 (int)size_is
, (int)content_size
);
784 /* the content size must be a multiple of 8 */
785 if ((content_size
% 8) != 0) {
786 return ndr_pull_error(ndr
, NDR_ERR_SUBCONTEXT
,
787 "Bad subcontext (PULL) size_is(%d) not padded to 8 content_size %d",
788 (int)size_is
, (int)content_size
);
790 r_content_size
= content_size
;
793 NDR_CHECK(ndr_pull_uint32(ndr
, NDR_SCALARS
, &reserved
));
798 * a shallow copy like subcontext
799 * useful for DCERPC pipe chunks.
801 subndr
= talloc_zero(ndr
, struct ndr_pull
);
802 NDR_ERR_HAVE_NO_MEMORY(subndr
);
804 subndr
->flags
= ndr
->flags
;
805 subndr
->current_mem_ctx
= ndr
->current_mem_ctx
;
806 subndr
->data
= ndr
->data
;
807 subndr
->offset
= ndr
->offset
;
808 subndr
->data_size
= ndr
->data_size
;
811 return NDR_ERR_SUCCESS
;
814 return ndr_pull_error(ndr
, NDR_ERR_SUBCONTEXT
, "Bad subcontext (PULL) header_size %d",
818 NDR_PULL_NEED_BYTES(ndr
, r_content_size
);
820 subndr
= talloc_zero(ndr
, struct ndr_pull
);
821 NDR_ERR_HAVE_NO_MEMORY(subndr
);
822 subndr
->flags
= ndr
->flags
& ~LIBNDR_FLAG_NDR64
;
823 subndr
->current_mem_ctx
= ndr
->current_mem_ctx
;
825 subndr
->data
= ndr
->data
+ ndr
->offset
;
827 subndr
->data_size
= r_content_size
;
830 ndr_set_flags(&ndr
->flags
, LIBNDR_FLAG_LITTLE_ENDIAN
);
831 } else if (force_be
) {
832 ndr_set_flags(&ndr
->flags
, LIBNDR_FLAG_BIGENDIAN
);
836 return NDR_ERR_SUCCESS
;
839 _PUBLIC_
enum ndr_err_code
ndr_pull_subcontext_end(struct ndr_pull
*ndr
,
840 struct ndr_pull
*subndr
,
845 uint32_t highest_ofs
;
847 if (header_size
== 0xFFFFFFFF) {
848 advance
= subndr
->offset
- ndr
->offset
;
849 } else if (size_is
>= 0) {
851 } else if (header_size
> 0) {
852 advance
= subndr
->data_size
;
854 advance
= subndr
->offset
;
857 if (subndr
->offset
> ndr
->relative_highest_offset
) {
858 highest_ofs
= subndr
->offset
;
860 highest_ofs
= subndr
->relative_highest_offset
;
862 if (!(subndr
->flags
& LIBNDR_FLAG_SUBCONTEXT_NO_UNREAD_BYTES
)) {
864 * avoid an error unless SUBCONTEXT_NO_UNREAD_BYTES is specified
866 highest_ofs
= advance
;
868 if (highest_ofs
< advance
) {
869 return ndr_pull_error(subndr
, NDR_ERR_UNREAD_BYTES
,
870 "not all bytes consumed ofs[%u] advance[%u]",
871 highest_ofs
, advance
);
874 NDR_CHECK(ndr_pull_advance(ndr
, advance
));
875 return NDR_ERR_SUCCESS
;
878 _PUBLIC_
enum ndr_err_code
ndr_push_subcontext_start(struct ndr_push
*ndr
,
879 struct ndr_push
**_subndr
,
883 struct ndr_push
*subndr
;
885 subndr
= ndr_push_init_ctx(ndr
);
886 NDR_ERR_HAVE_NO_MEMORY(subndr
);
887 subndr
->flags
= ndr
->flags
& ~LIBNDR_FLAG_NDR64
;
890 NDR_CHECK(ndr_push_zero(subndr
, size_is
));
892 subndr
->relative_end_offset
= size_is
;
896 return NDR_ERR_SUCCESS
;
900 push a subcontext header
902 _PUBLIC_
enum ndr_err_code
ndr_push_subcontext_end(struct ndr_push
*ndr
,
903 struct ndr_push
*subndr
,
910 padding_len
= size_is
- subndr
->offset
;
911 if (padding_len
< 0) {
912 return ndr_push_error(ndr
, NDR_ERR_SUBCONTEXT
, "Bad subcontext (PUSH) content_size %d is larger than size_is(%d)",
913 (int)subndr
->offset
, (int)size_is
);
915 subndr
->offset
= size_is
;
918 switch (header_size
) {
923 NDR_CHECK(ndr_push_uint16(ndr
, NDR_SCALARS
, subndr
->offset
));
927 NDR_CHECK(ndr_push_uint3264(ndr
, NDR_SCALARS
, subndr
->offset
));
932 * Common Type Header for the Serialization Stream
933 * See [MS-RPCE] 2.2.6 Type Serialization Version 1
935 padding_len
= NDR_ROUND(subndr
->offset
, 8) - subndr
->offset
;
936 if (padding_len
> 0) {
937 NDR_CHECK(ndr_push_zero(subndr
, padding_len
));
941 NDR_CHECK(ndr_push_uint8(ndr
, NDR_SCALARS
, 1));
947 NDR_CHECK(ndr_push_uint8(ndr
, NDR_SCALARS
, NDR_BE(ndr
)?0x00:0x10));
949 /* length of the "Private Header for Constructed Type" */
950 NDR_CHECK(ndr_push_uint16(ndr
, NDR_SCALARS
, 8));
953 NDR_CHECK(ndr_push_uint32(ndr
, NDR_SCALARS
, 0xCCCCCCCC));
956 * Private Header for Constructed Type
958 /* length - will be updated latter */
959 NDR_CHECK(ndr_push_uint32(ndr
, NDR_SCALARS
, subndr
->offset
));
962 NDR_CHECK(ndr_push_uint32(ndr
, NDR_SCALARS
, 0));
966 return ndr_push_error(ndr
, NDR_ERR_SUBCONTEXT
, "Bad subcontext header size %d",
970 NDR_CHECK(ndr_push_bytes(ndr
, subndr
->data
, subndr
->offset
));
971 return NDR_ERR_SUCCESS
;
981 store a token in the ndr context, for later retrieval
983 _PUBLIC_
enum ndr_err_code
ndr_token_store(TALLOC_CTX
*mem_ctx
,
984 struct ndr_token_list
*list
,
988 if (list
->tokens
== NULL
) {
989 list
->tokens
= talloc_array(mem_ctx
, struct ndr_token
, 10);
990 if (list
->tokens
== NULL
) {
991 NDR_ERR_HAVE_NO_MEMORY(list
->tokens
);
994 struct ndr_token
*new_tokens
= NULL
;
995 uint32_t alloc_count
= talloc_array_length(list
->tokens
);
998 * Check every time we have not allocated too many
999 * tokens. This ensures developer sanity when
1000 * debugging the boundary condition
1002 if (list
->count
>= NDR_TOKEN_MAX_LIST_SIZE
) {
1003 return NDR_ERR_RANGE
;
1005 if (list
->count
== alloc_count
) {
1008 * Double the list, until we start in chunks
1011 unsigned increment
= MIN(list
->count
, 1000);
1012 new_alloc
= alloc_count
+ increment
;
1013 if (new_alloc
< alloc_count
) {
1014 return NDR_ERR_RANGE
;
1016 new_tokens
= talloc_realloc(mem_ctx
, list
->tokens
,
1017 struct ndr_token
, new_alloc
);
1018 NDR_ERR_HAVE_NO_MEMORY(new_tokens
);
1019 list
->tokens
= new_tokens
;
1022 list
->tokens
[list
->count
].key
= key
;
1023 list
->tokens
[list
->count
].value
= value
;
1025 return NDR_ERR_SUCCESS
;
1029 retrieve a token from a ndr context, using cmp_fn to match the tokens
1031 _PUBLIC_
enum ndr_err_code
ndr_token_retrieve_cmp_fn(struct ndr_token_list
*list
,
1032 const void *key
, uint32_t *v
,
1033 comparison_fn_t _cmp_fn
,
1036 struct ndr_token
*tokens
= list
->tokens
;
1039 for (i
= list
->count
- 1; i
< list
->count
; i
--) {
1040 if (_cmp_fn(tokens
[i
].key
, key
) == 0) {
1045 for (i
= list
->count
- 1; i
< list
->count
; i
--) {
1046 if (tokens
[i
].key
== key
) {
1051 return NDR_ERR_TOKEN
;
1053 *v
= tokens
[i
].value
;
1055 if (i
!= list
->count
- 1) {
1056 tokens
[i
] = tokens
[list
->count
- 1];
1060 return NDR_ERR_SUCCESS
;
1064 retrieve a token from a ndr context
1066 _PUBLIC_
enum ndr_err_code
ndr_token_retrieve(struct ndr_token_list
*list
,
1067 const void *key
, uint32_t *v
)
1069 return ndr_token_retrieve_cmp_fn(list
, key
, v
, NULL
, true);
1073 peek at but don't removed a token from a ndr context
1075 _PUBLIC_
enum ndr_err_code
ndr_token_peek(struct ndr_token_list
*list
,
1076 const void *key
, uint32_t *v
)
1078 return ndr_token_retrieve_cmp_fn(list
, key
, v
, NULL
, false);
1082 pull an array size field and add it to the array_size_list token list
1084 _PUBLIC_
enum ndr_err_code
ndr_pull_array_size(struct ndr_pull
*ndr
, const void *p
)
1086 enum ndr_err_code ret
;
1088 NDR_CHECK(ndr_pull_uint3264(ndr
, NDR_SCALARS
, &size
));
1089 ret
= ndr_token_store(ndr
, &ndr
->array_size_list
, p
, size
);
1090 if (ret
== NDR_ERR_RANGE
) {
1091 return ndr_pull_error(ndr
, ret
,
1092 "More than %d NDR tokens stored for array_size",
1093 NDR_TOKEN_MAX_LIST_SIZE
);
1099 get the stored array size field
1101 _PUBLIC_
enum ndr_err_code
ndr_get_array_size(struct ndr_pull
*ndr
, const void *p
, uint32_t *size
)
1103 return ndr_token_peek(&ndr
->array_size_list
, p
, size
);
1107 get and remove from the stored list the stored array size field
1109 _PUBLIC_
enum ndr_err_code
ndr_steal_array_size(struct ndr_pull
*ndr
, const void *p
, uint32_t *size
)
1111 return ndr_token_retrieve(&ndr
->array_size_list
, p
, size
);
1115 * check the stored array size field and remove from the stored list
1116 * (the array_size NDR token list). We try to remove when possible to
1117 * avoid the list growing towards the bounds check
1119 _PUBLIC_
enum ndr_err_code
ndr_check_steal_array_size(struct ndr_pull
*ndr
, const void *p
, uint32_t size
)
1122 NDR_CHECK(ndr_steal_array_size(ndr
, p
, &stored
));
1123 if (stored
!= size
) {
1124 return ndr_pull_error(ndr
, NDR_ERR_ARRAY_SIZE
,
1125 "Bad array size - got %u expected %u\n",
1128 return NDR_ERR_SUCCESS
;
1132 * check the stored array size field (leaving it on the array_size
1135 _PUBLIC_
enum ndr_err_code
ndr_check_array_size(struct ndr_pull
*ndr
, const void *p
, uint32_t size
)
1138 NDR_CHECK(ndr_get_array_size(ndr
, p
, &stored
));
1139 if (stored
!= size
) {
1140 return ndr_pull_error(ndr
, NDR_ERR_ARRAY_SIZE
,
1141 "Bad array size - got %u expected %u\n",
1144 return NDR_ERR_SUCCESS
;
1148 pull an array length field and add it to the array_length_list token list
1150 _PUBLIC_
enum ndr_err_code
ndr_pull_array_length(struct ndr_pull
*ndr
, const void *p
)
1152 enum ndr_err_code ret
;
1153 uint32_t length
, offset
;
1154 NDR_CHECK(ndr_pull_uint3264(ndr
, NDR_SCALARS
, &offset
));
1156 return ndr_pull_error(ndr
, NDR_ERR_ARRAY_SIZE
,
1157 "non-zero array offset %u\n", offset
);
1159 NDR_CHECK(ndr_pull_uint3264(ndr
, NDR_SCALARS
, &length
));
1160 ret
= ndr_token_store(ndr
, &ndr
->array_length_list
, p
, length
);
1161 if (ret
== NDR_ERR_RANGE
) {
1162 return ndr_pull_error(ndr
, ret
,
1163 "More than %d NDR tokens stored for array_length_list",
1164 NDR_TOKEN_MAX_LIST_SIZE
);
1170 get the stored array length field
1172 _PUBLIC_
enum ndr_err_code
ndr_get_array_length(struct ndr_pull
*ndr
, const void *p
, uint32_t *length
)
1174 return ndr_token_peek(&ndr
->array_length_list
, p
, length
);
1178 * check the stored array length field and remove from the stored list
1179 * (the array_size NDR token list). We try to remove when possible to
1180 * avoid the list growing towards the bounds check
1182 _PUBLIC_
enum ndr_err_code
ndr_steal_array_length(struct ndr_pull
*ndr
, const void *p
, uint32_t *length
)
1184 return ndr_token_retrieve(&ndr
->array_length_list
, p
, length
);
1187 check the stored array length field, removing it from the list
1189 _PUBLIC_
enum ndr_err_code
ndr_check_steal_array_length(struct ndr_pull
*ndr
, const void *p
, uint32_t length
)
1192 NDR_CHECK(ndr_steal_array_length(ndr
, p
, &stored
));
1193 if (stored
!= length
) {
1194 return ndr_pull_error(ndr
, NDR_ERR_ARRAY_SIZE
,
1195 "Bad array length - got %u expected %u\n",
1198 return NDR_ERR_SUCCESS
;
1201 _PUBLIC_
enum ndr_err_code
ndr_push_pipe_chunk_trailer(struct ndr_push
*ndr
, int ndr_flags
, uint32_t count
)
1203 if (ndr
->flags
& LIBNDR_FLAG_NDR64
) {
1204 int64_t tmp
= 0 - (int64_t)count
;
1205 uint64_t ncount
= tmp
;
1207 NDR_CHECK(ndr_push_hyper(ndr
, ndr_flags
, ncount
));
1210 return NDR_ERR_SUCCESS
;
1213 _PUBLIC_
enum ndr_err_code
ndr_check_pipe_chunk_trailer(struct ndr_pull
*ndr
, int ndr_flags
, uint32_t count
)
1215 if (ndr
->flags
& LIBNDR_FLAG_NDR64
) {
1216 int64_t tmp
= 0 - (int64_t)count
;
1217 uint64_t ncount1
= tmp
;
1220 NDR_CHECK(ndr_pull_hyper(ndr
, ndr_flags
, &ncount2
));
1221 if (ncount1
== ncount2
) {
1222 return NDR_ERR_SUCCESS
;
1225 return ndr_pull_error(ndr
, NDR_ERR_ARRAY_SIZE
,
1226 "Bad pipe trailer[%lld should be %lld] size was %lu\"",
1227 (unsigned long long)ncount2
,
1228 (unsigned long long)ncount1
,
1229 (unsigned long)count
);
1232 return NDR_ERR_SUCCESS
;
1236 store a switch value
1238 _PUBLIC_
enum ndr_err_code
ndr_push_set_switch_value(struct ndr_push
*ndr
, const void *p
, uint32_t val
)
1240 enum ndr_err_code ret
=
1241 ndr_token_store(ndr
, &ndr
->switch_list
, p
, val
);
1242 if (ret
== NDR_ERR_RANGE
) {
1243 return ndr_push_error(ndr
, ret
,
1244 "More than %d NDR tokens stored for switch_list",
1245 NDR_TOKEN_MAX_LIST_SIZE
);
1250 _PUBLIC_
enum ndr_err_code
ndr_pull_set_switch_value(struct ndr_pull
*ndr
, const void *p
, uint32_t val
)
1253 enum ndr_err_code ret
=
1254 ndr_token_store(ndr
, &ndr
->switch_list
, p
, val
);
1255 if (ret
== NDR_ERR_RANGE
) {
1256 return ndr_pull_error(ndr
, ret
,
1257 "More than %d NDR tokens stored for switch_list",
1258 NDR_TOKEN_MAX_LIST_SIZE
);
1263 _PUBLIC_
enum ndr_err_code
ndr_print_set_switch_value(struct ndr_print
*ndr
, const void *p
, uint32_t val
)
1265 return ndr_token_store(ndr
, &ndr
->switch_list
, p
, val
);
1268 /* retrieve a switch value (for push) and remove it from the list */
1269 _PUBLIC_
enum ndr_err_code
ndr_push_steal_switch_value(struct ndr_push
*ndr
,
1273 return ndr_token_retrieve(&ndr
->switch_list
, p
, v
);
1276 /* retrieve a switch value and remove it from the list */
1277 _PUBLIC_
uint32_t ndr_print_steal_switch_value(struct ndr_print
*ndr
, const void *p
)
1279 enum ndr_err_code status
;
1282 status
= ndr_token_retrieve(&ndr
->switch_list
, p
, &v
);
1283 if (!NDR_ERR_CODE_IS_SUCCESS(status
)) {
1290 /* retrieve a switch value and remove it from the list */
1291 _PUBLIC_
enum ndr_err_code
ndr_pull_steal_switch_value(struct ndr_pull
*ndr
,
1295 return ndr_token_retrieve(&ndr
->switch_list
, p
, v
);
1299 pull a struct from a blob using NDR
1301 _PUBLIC_
enum ndr_err_code
ndr_pull_struct_blob(const DATA_BLOB
*blob
, TALLOC_CTX
*mem_ctx
, void *p
,
1302 ndr_pull_flags_fn_t fn
)
1304 struct ndr_pull
*ndr
;
1305 ndr
= ndr_pull_init_blob(blob
, mem_ctx
);
1306 NDR_ERR_HAVE_NO_MEMORY(ndr
);
1307 NDR_CHECK_FREE(fn(ndr
, NDR_SCALARS
|NDR_BUFFERS
, p
));
1309 return NDR_ERR_SUCCESS
;
1313 pull a struct from a blob using NDR - failing if all bytes are not consumed
1315 _PUBLIC_
enum ndr_err_code
ndr_pull_struct_blob_all(const DATA_BLOB
*blob
, TALLOC_CTX
*mem_ctx
,
1316 void *p
, ndr_pull_flags_fn_t fn
)
1318 struct ndr_pull
*ndr
;
1319 uint32_t highest_ofs
;
1320 ndr
= ndr_pull_init_blob(blob
, mem_ctx
);
1321 NDR_ERR_HAVE_NO_MEMORY(ndr
);
1322 NDR_CHECK_FREE(fn(ndr
, NDR_SCALARS
|NDR_BUFFERS
, p
));
1323 if (ndr
->offset
> ndr
->relative_highest_offset
) {
1324 highest_ofs
= ndr
->offset
;
1326 highest_ofs
= ndr
->relative_highest_offset
;
1328 if (highest_ofs
< ndr
->data_size
) {
1329 enum ndr_err_code ret
;
1330 ret
= ndr_pull_error(ndr
, NDR_ERR_UNREAD_BYTES
,
1331 "not all bytes consumed ofs[%u] size[%u]",
1332 highest_ofs
, ndr
->data_size
);
1337 return NDR_ERR_SUCCESS
;
1341 pull a struct from a blob using NDR - failing if all bytes are not consumed
1343 This only works for structures with NO allocated memory, like
1344 objectSID and GUID. This helps because we parse these a lot.
1346 _PUBLIC_
enum ndr_err_code
ndr_pull_struct_blob_all_noalloc(const DATA_BLOB
*blob
,
1347 void *p
, ndr_pull_flags_fn_t fn
)
1350 * We init this structure on the stack here, to avoid a
1351 * talloc() as otherwise this call to the fn() is assured not
1352 * to be doing any allocation, eg SIDs and GUIDs.
1354 * This allows us to keep the safety of the PIDL-generated
1355 * code without the talloc() overhead.
1357 struct ndr_pull ndr
= {
1359 .data_size
= blob
->length
,
1360 .current_mem_ctx
= (void *)-1
1362 uint32_t highest_ofs
;
1363 NDR_CHECK(fn(&ndr
, NDR_SCALARS
|NDR_BUFFERS
, p
));
1364 highest_ofs
= MAX(ndr
.offset
, ndr
.relative_highest_offset
);
1365 if (highest_ofs
< ndr
.data_size
) {
1366 enum ndr_err_code ret
;
1367 ret
= ndr_pull_error(
1369 NDR_ERR_UNREAD_BYTES
,
1370 "not all bytes consumed ofs[%"PRIu32
"] "
1376 return NDR_ERR_SUCCESS
;
1380 pull a union from a blob using NDR, given the union discriminator
1382 _PUBLIC_
enum ndr_err_code
ndr_pull_union_blob(const DATA_BLOB
*blob
, TALLOC_CTX
*mem_ctx
,
1384 uint32_t level
, ndr_pull_flags_fn_t fn
)
1386 struct ndr_pull
*ndr
;
1387 ndr
= ndr_pull_init_blob(blob
, mem_ctx
);
1388 NDR_ERR_HAVE_NO_MEMORY(ndr
);
1389 NDR_CHECK_FREE(ndr_pull_set_switch_value(ndr
, p
, level
));
1390 NDR_CHECK_FREE(fn(ndr
, NDR_SCALARS
|NDR_BUFFERS
, p
));
1392 return NDR_ERR_SUCCESS
;
1396 pull a union from a blob using NDR, given the union discriminator,
1397 failing if all bytes are not consumed
1399 _PUBLIC_
enum ndr_err_code
ndr_pull_union_blob_all(const DATA_BLOB
*blob
, TALLOC_CTX
*mem_ctx
,
1401 uint32_t level
, ndr_pull_flags_fn_t fn
)
1403 struct ndr_pull
*ndr
;
1404 uint32_t highest_ofs
;
1405 ndr
= ndr_pull_init_blob(blob
, mem_ctx
);
1406 NDR_ERR_HAVE_NO_MEMORY(ndr
);
1407 NDR_CHECK_FREE(ndr_pull_set_switch_value(ndr
, p
, level
));
1408 NDR_CHECK_FREE(fn(ndr
, NDR_SCALARS
|NDR_BUFFERS
, p
));
1409 if (ndr
->offset
> ndr
->relative_highest_offset
) {
1410 highest_ofs
= ndr
->offset
;
1412 highest_ofs
= ndr
->relative_highest_offset
;
1414 if (highest_ofs
< ndr
->data_size
) {
1415 enum ndr_err_code ret
;
1416 ret
= ndr_pull_error(ndr
, NDR_ERR_UNREAD_BYTES
,
1417 "not all bytes consumed ofs[%u] size[%u]",
1418 highest_ofs
, ndr
->data_size
);
1423 return NDR_ERR_SUCCESS
;
1427 push a struct to a blob using NDR
1429 _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
)
1431 struct ndr_push
*ndr
;
1432 ndr
= ndr_push_init_ctx(mem_ctx
);
1433 NDR_ERR_HAVE_NO_MEMORY(ndr
);
1435 NDR_CHECK(fn(ndr
, NDR_SCALARS
|NDR_BUFFERS
, p
));
1437 *blob
= ndr_push_blob(ndr
);
1438 talloc_steal(mem_ctx
, blob
->data
);
1441 return NDR_ERR_SUCCESS
;
1445 push a struct into a provided blob using NDR.
1447 We error because we want to have the performance issue (extra
1448 talloc() calls) show up as an error, not just slower code. This is
1449 used for things like GUIDs, which we expect to be a fixed size, and
1450 SIDs that we can pre-calculate the size for.
1452 _PUBLIC_
enum ndr_err_code
ndr_push_struct_into_fixed_blob(
1453 DATA_BLOB
*blob
, const void *p
, ndr_push_flags_fn_t fn
)
1455 struct ndr_push ndr
= {
1457 .alloc_size
= blob
->length
,
1458 .fixed_buf_size
= true
1461 NDR_CHECK(fn(&ndr
, NDR_SCALARS
|NDR_BUFFERS
, p
));
1463 if (ndr
.offset
!= blob
->length
) {
1464 return ndr_push_error(&ndr
, NDR_ERR_BUFSIZE
,
1465 "buffer was either to large or small "
1466 "ofs[%u] size[%zu]",
1467 ndr
.offset
, blob
->length
);
1470 return NDR_ERR_SUCCESS
;
1474 push a union to a blob using NDR
1476 _PUBLIC_
enum ndr_err_code
ndr_push_union_blob(DATA_BLOB
*blob
, TALLOC_CTX
*mem_ctx
, void *p
,
1477 uint32_t level
, ndr_push_flags_fn_t fn
)
1479 struct ndr_push
*ndr
;
1480 ndr
= ndr_push_init_ctx(mem_ctx
);
1481 NDR_ERR_HAVE_NO_MEMORY(ndr
);
1483 NDR_CHECK(ndr_push_set_switch_value(ndr
, p
, level
));
1484 NDR_CHECK(fn(ndr
, NDR_SCALARS
|NDR_BUFFERS
, p
));
1486 *blob
= ndr_push_blob(ndr
);
1487 talloc_steal(mem_ctx
, blob
->data
);
1490 return NDR_ERR_SUCCESS
;
1494 generic ndr_size_*() handler for structures
1496 _PUBLIC_
size_t ndr_size_struct(const void *p
, int flags
, ndr_push_flags_fn_t push
)
1498 struct ndr_push
*ndr
;
1499 enum ndr_err_code status
;
1502 /* avoid recursion */
1503 if (flags
& LIBNDR_FLAG_NO_NDR_SIZE
) return 0;
1505 /* Avoid following a NULL pointer */
1510 ndr
= ndr_push_init_ctx(NULL
);
1512 ndr
->flags
|= flags
| LIBNDR_FLAG_NO_NDR_SIZE
;
1513 status
= push(ndr
, NDR_SCALARS
|NDR_BUFFERS
, discard_const(p
));
1514 if (!NDR_ERR_CODE_IS_SUCCESS(status
)) {
1524 generic ndr_size_*() handler for unions
1526 _PUBLIC_
size_t ndr_size_union(const void *p
, int flags
, uint32_t level
, ndr_push_flags_fn_t push
)
1528 struct ndr_push
*ndr
;
1529 enum ndr_err_code status
;
1532 /* avoid recursion */
1533 if (flags
& LIBNDR_FLAG_NO_NDR_SIZE
) return 0;
1535 /* Avoid following a NULL pointer */
1540 ndr
= ndr_push_init_ctx(NULL
);
1542 ndr
->flags
|= flags
| LIBNDR_FLAG_NO_NDR_SIZE
;
1544 status
= ndr_push_set_switch_value(ndr
, p
, level
);
1545 if (!NDR_ERR_CODE_IS_SUCCESS(status
)) {
1549 status
= push(ndr
, NDR_SCALARS
|NDR_BUFFERS
, p
);
1550 if (!NDR_ERR_CODE_IS_SUCCESS(status
)) {
1560 get the current base for relative pointers for the push
1562 _PUBLIC_
uint32_t ndr_push_get_relative_base_offset(struct ndr_push
*ndr
)
1564 return ndr
->relative_base_offset
;
1568 restore the old base for relative pointers for the push
1570 _PUBLIC_
void ndr_push_restore_relative_base_offset(struct ndr_push
*ndr
, uint32_t offset
)
1572 ndr
->relative_base_offset
= offset
;
1576 setup the current base for relative pointers for the push
1577 called in the NDR_SCALAR stage
1579 _PUBLIC_
enum ndr_err_code
ndr_push_setup_relative_base_offset1(struct ndr_push
*ndr
, const void *p
, uint32_t offset
)
1581 enum ndr_err_code ret
;
1582 ndr
->relative_base_offset
= offset
;
1583 ret
= ndr_token_store(ndr
, &ndr
->relative_base_list
, p
, offset
);
1584 if (ret
== NDR_ERR_RANGE
) {
1585 return ndr_push_error(ndr
, ret
,
1586 "More than %d NDR tokens stored for relative_base_list",
1587 NDR_TOKEN_MAX_LIST_SIZE
);
1593 setup the current base for relative pointers for the push
1594 called in the NDR_BUFFERS stage
1596 _PUBLIC_
enum ndr_err_code
ndr_push_setup_relative_base_offset2(struct ndr_push
*ndr
, const void *p
)
1598 return ndr_token_retrieve(&ndr
->relative_base_list
, p
, &ndr
->relative_base_offset
);
1602 push a relative object - stage1
1603 this is called during SCALARS processing
1605 _PUBLIC_
enum ndr_err_code
ndr_push_relative_ptr1(struct ndr_push
*ndr
, const void *p
)
1607 enum ndr_err_code ret
;
1609 NDR_CHECK(ndr_push_uint32(ndr
, NDR_SCALARS
, 0));
1610 return NDR_ERR_SUCCESS
;
1612 NDR_CHECK(ndr_push_align(ndr
, 4));
1613 ret
= ndr_token_store(ndr
, &ndr
->relative_list
, p
, ndr
->offset
);
1614 if (ret
== NDR_ERR_RANGE
) {
1615 return ndr_push_error(ndr
, ret
,
1616 "More than %d NDR tokens stored for relative_list",
1617 NDR_TOKEN_MAX_LIST_SIZE
);
1620 return ndr_push_uint32(ndr
, NDR_SCALARS
, 0xFFFFFFFF);
1624 push a short relative object - stage1
1625 this is called during SCALARS processing
1627 _PUBLIC_
enum ndr_err_code
ndr_push_short_relative_ptr1(struct ndr_push
*ndr
, const void *p
)
1629 enum ndr_err_code ret
;
1631 NDR_CHECK(ndr_push_uint16(ndr
, NDR_SCALARS
, 0));
1632 return NDR_ERR_SUCCESS
;
1634 NDR_CHECK(ndr_push_align(ndr
, 2));
1635 ret
= ndr_token_store(ndr
, &ndr
->relative_list
, p
, ndr
->offset
);
1636 if (ret
== NDR_ERR_RANGE
) {
1637 return ndr_push_error(ndr
, ret
,
1638 "More than %d NDR tokens stored for relative_list",
1639 NDR_TOKEN_MAX_LIST_SIZE
);
1642 return ndr_push_uint16(ndr
, NDR_SCALARS
, 0xFFFF);
1645 push a relative object - stage2
1646 this is called during buffers processing
1648 static enum ndr_err_code
ndr_push_relative_ptr2(struct ndr_push
*ndr
, const void *p
)
1650 uint32_t save_offset
;
1651 uint32_t ptr_offset
= 0xFFFFFFFF;
1653 return NDR_ERR_SUCCESS
;
1655 save_offset
= ndr
->offset
;
1656 NDR_CHECK(ndr_token_retrieve(&ndr
->relative_list
, p
, &ptr_offset
));
1657 if (ptr_offset
> ndr
->offset
) {
1658 return ndr_push_error(ndr
, NDR_ERR_BUFSIZE
,
1659 "ndr_push_relative_ptr2 ptr_offset(%u) > ndr->offset(%u)",
1660 ptr_offset
, ndr
->offset
);
1662 ndr
->offset
= ptr_offset
;
1663 if (save_offset
< ndr
->relative_base_offset
) {
1664 return ndr_push_error(ndr
, NDR_ERR_BUFSIZE
,
1665 "ndr_push_relative_ptr2 save_offset(%u) < ndr->relative_base_offset(%u)",
1666 save_offset
, ndr
->relative_base_offset
);
1668 NDR_CHECK(ndr_push_uint32(ndr
, NDR_SCALARS
, save_offset
- ndr
->relative_base_offset
));
1669 ndr
->offset
= save_offset
;
1670 return NDR_ERR_SUCCESS
;
1673 push a short relative object - stage2
1674 this is called during buffers processing
1676 _PUBLIC_
enum ndr_err_code
ndr_push_short_relative_ptr2(struct ndr_push
*ndr
, const void *p
)
1678 uint32_t save_offset
;
1679 uint32_t ptr_offset
= 0xFFFF;
1680 uint32_t relative_offset
;
1685 return NDR_ERR_SUCCESS
;
1688 if (ndr
->offset
< ndr
->relative_base_offset
) {
1689 return ndr_push_error(ndr
, NDR_ERR_BUFSIZE
,
1690 "ndr_push_relative_ptr2 ndr->offset(%u) < ndr->relative_base_offset(%u)",
1691 ndr
->offset
, ndr
->relative_base_offset
);
1694 relative_offset
= ndr
->offset
- ndr
->relative_base_offset
;
1696 if (ndr
->flags
& LIBNDR_FLAG_NOALIGN
) {
1698 } else if (ndr
->flags
& LIBNDR_FLAG_ALIGN2
) {
1700 } else if (ndr
->flags
& LIBNDR_FLAG_ALIGN4
) {
1702 } else if (ndr
->flags
& LIBNDR_FLAG_ALIGN8
) {
1706 pad
= ndr_align_size(relative_offset
, align
);
1708 NDR_CHECK(ndr_push_zero(ndr
, pad
));
1711 relative_offset
= ndr
->offset
- ndr
->relative_base_offset
;
1712 if (relative_offset
> UINT16_MAX
) {
1713 return ndr_push_error(ndr
, NDR_ERR_BUFSIZE
,
1714 "ndr_push_relative_ptr2 relative_offset(%u) > UINT16_MAX",
1718 save_offset
= ndr
->offset
;
1719 NDR_CHECK(ndr_token_retrieve(&ndr
->relative_list
, p
, &ptr_offset
));
1720 if (ptr_offset
> ndr
->offset
) {
1721 return ndr_push_error(ndr
, NDR_ERR_BUFSIZE
,
1722 "ndr_push_short_relative_ptr2 ptr_offset(%u) > ndr->offset(%u)",
1723 ptr_offset
, ndr
->offset
);
1725 ndr
->offset
= ptr_offset
;
1726 NDR_CHECK(ndr_push_uint16(ndr
, NDR_SCALARS
, relative_offset
));
1727 ndr
->offset
= save_offset
;
1728 return NDR_ERR_SUCCESS
;
1732 push a relative object - stage2 start
1733 this is called during buffers processing
1735 _PUBLIC_
enum ndr_err_code
ndr_push_relative_ptr2_start(struct ndr_push
*ndr
, const void *p
)
1737 enum ndr_err_code ret
;
1739 return NDR_ERR_SUCCESS
;
1741 if (!(ndr
->flags
& LIBNDR_FLAG_RELATIVE_REVERSE
)) {
1742 uint32_t relative_offset
;
1746 if (ndr
->offset
< ndr
->relative_base_offset
) {
1747 return ndr_push_error(ndr
, NDR_ERR_BUFSIZE
,
1748 "ndr_push_relative_ptr2_start ndr->offset(%u) < ndr->relative_base_offset(%u)",
1749 ndr
->offset
, ndr
->relative_base_offset
);
1752 relative_offset
= ndr
->offset
- ndr
->relative_base_offset
;
1754 if (ndr
->flags
& LIBNDR_FLAG_NOALIGN
) {
1756 } else if (ndr
->flags
& LIBNDR_FLAG_ALIGN2
) {
1758 } else if (ndr
->flags
& LIBNDR_FLAG_ALIGN4
) {
1760 } else if (ndr
->flags
& LIBNDR_FLAG_ALIGN8
) {
1764 pad
= ndr_align_size(relative_offset
, align
);
1766 NDR_CHECK(ndr_push_zero(ndr
, pad
));
1769 return ndr_push_relative_ptr2(ndr
, p
);
1771 if (ndr
->relative_end_offset
== -1) {
1772 return ndr_push_error(ndr
, NDR_ERR_RELATIVE
,
1773 "ndr_push_relative_ptr2_start RELATIVE_REVERSE flag set and relative_end_offset %d",
1774 ndr
->relative_end_offset
);
1776 ret
= ndr_token_store(ndr
,
1777 &ndr
->relative_begin_list
,
1780 if (ret
== NDR_ERR_RANGE
) {
1781 return ndr_push_error(ndr
, ret
,
1782 "More than %d NDR tokens stored for array_size",
1783 NDR_TOKEN_MAX_LIST_SIZE
);
1789 push a relative object - stage2 end
1790 this is called during buffers processing
1792 _PUBLIC_
enum ndr_err_code
ndr_push_relative_ptr2_end(struct ndr_push
*ndr
, const void *p
)
1794 uint32_t begin_offset
= 0xFFFFFFFF;
1796 uint32_t correct_offset
= 0;
1801 return NDR_ERR_SUCCESS
;
1804 if (!(ndr
->flags
& LIBNDR_FLAG_RELATIVE_REVERSE
)) {
1805 return NDR_ERR_SUCCESS
;
1808 if (ndr
->flags
& LIBNDR_FLAG_NO_NDR_SIZE
) {
1809 /* better say more than calculation a too small buffer */
1810 NDR_PUSH_ALIGN(ndr
, 8);
1811 return NDR_ERR_SUCCESS
;
1814 if (ndr
->relative_end_offset
< ndr
->offset
) {
1815 return ndr_push_error(ndr
, NDR_ERR_RELATIVE
,
1816 "ndr_push_relative_ptr2_end:"
1817 "relative_end_offset %u < offset %u",
1818 ndr
->relative_end_offset
, ndr
->offset
);
1821 NDR_CHECK(ndr_token_retrieve(&ndr
->relative_begin_list
, p
, &begin_offset
));
1823 /* we have marshalled a buffer, see how long it was */
1824 len
= ndr
->offset
- begin_offset
;
1827 return ndr_push_error(ndr
, NDR_ERR_RELATIVE
,
1828 "ndr_push_relative_ptr2_end:"
1829 "offset %u - begin_offset %u < 0",
1830 ndr
->offset
, begin_offset
);
1833 if (ndr
->relative_end_offset
< len
) {
1834 return ndr_push_error(ndr
, NDR_ERR_RELATIVE
,
1835 "ndr_push_relative_ptr2_end:"
1836 "relative_end_offset %u < len %lld",
1837 ndr
->offset
, (long long)len
);
1840 /* the reversed offset is at the end of the main buffer */
1841 correct_offset
= ndr
->relative_end_offset
- len
;
1843 if (ndr
->flags
& LIBNDR_FLAG_NOALIGN
) {
1845 } else if (ndr
->flags
& LIBNDR_FLAG_ALIGN2
) {
1847 } else if (ndr
->flags
& LIBNDR_FLAG_ALIGN4
) {
1849 } else if (ndr
->flags
& LIBNDR_FLAG_ALIGN8
) {
1853 pad
= ndr_align_size(correct_offset
, align
);
1855 correct_offset
+= pad
;
1856 correct_offset
-= align
;
1859 if (correct_offset
< begin_offset
) {
1860 return ndr_push_error(ndr
, NDR_ERR_RELATIVE
,
1861 "ndr_push_relative_ptr2_end: "
1862 "correct_offset %u < begin_offset %u",
1863 correct_offset
, begin_offset
);
1867 uint32_t clear_size
= correct_offset
- begin_offset
;
1869 clear_size
= MIN(clear_size
, len
);
1871 /* now move the marshalled buffer to the end of the main buffer */
1872 memmove(ndr
->data
+ correct_offset
, ndr
->data
+ begin_offset
, len
);
1875 /* and wipe out old buffer within the main buffer */
1876 memset(ndr
->data
+ begin_offset
, '\0', clear_size
);
1880 /* and set the end offset for the next buffer */
1881 ndr
->relative_end_offset
= correct_offset
;
1883 /* finally write the offset to the main buffer */
1884 ndr
->offset
= correct_offset
;
1885 NDR_CHECK(ndr_push_relative_ptr2(ndr
, p
));
1887 /* restore to where we were in the main buffer */
1888 ndr
->offset
= begin_offset
;
1890 return NDR_ERR_SUCCESS
;
1894 get the current base for relative pointers for the pull
1896 _PUBLIC_
uint32_t ndr_pull_get_relative_base_offset(struct ndr_pull
*ndr
)
1898 return ndr
->relative_base_offset
;
1902 restore the old base for relative pointers for the pull
1904 _PUBLIC_
void ndr_pull_restore_relative_base_offset(struct ndr_pull
*ndr
, uint32_t offset
)
1906 ndr
->relative_base_offset
= offset
;
1910 setup the current base for relative pointers for the pull
1911 called in the NDR_SCALAR stage
1913 _PUBLIC_
enum ndr_err_code
ndr_pull_setup_relative_base_offset1(struct ndr_pull
*ndr
, const void *p
, uint32_t offset
)
1915 enum ndr_err_code ret
;
1916 ndr
->relative_base_offset
= offset
;
1917 ret
= ndr_token_store(ndr
, &ndr
->relative_base_list
, p
, offset
);
1918 if (ret
== NDR_ERR_RANGE
) {
1919 return ndr_pull_error(ndr
, ret
,
1920 "More than %d NDR tokens stored for relative_base_list",
1921 NDR_TOKEN_MAX_LIST_SIZE
);
1927 setup the current base for relative pointers for the pull
1928 called in the NDR_BUFFERS stage
1930 _PUBLIC_
enum ndr_err_code
ndr_pull_setup_relative_base_offset2(struct ndr_pull
*ndr
, const void *p
)
1932 return ndr_token_retrieve(&ndr
->relative_base_list
, p
, &ndr
->relative_base_offset
);
1936 pull a relative object - stage1
1937 called during SCALARS processing
1939 _PUBLIC_
enum ndr_err_code
ndr_pull_relative_ptr1(struct ndr_pull
*ndr
, const void *p
, uint32_t rel_offset
)
1941 enum ndr_err_code ret
;
1942 rel_offset
+= ndr
->relative_base_offset
;
1943 if (rel_offset
> ndr
->data_size
) {
1944 return ndr_pull_error(ndr
, NDR_ERR_BUFSIZE
,
1945 "ndr_pull_relative_ptr1 rel_offset(%u) > ndr->data_size(%u)",
1946 rel_offset
, ndr
->data_size
);
1948 ret
= ndr_token_store(ndr
, &ndr
->relative_list
, p
, rel_offset
);
1949 if (ret
== NDR_ERR_RANGE
) {
1950 return ndr_pull_error(ndr
, ret
,
1951 "More than %d NDR tokens stored for relative_list",
1952 NDR_TOKEN_MAX_LIST_SIZE
);
1958 pull a relative object - stage2
1959 called during BUFFERS processing
1961 _PUBLIC_
enum ndr_err_code
ndr_pull_relative_ptr2(struct ndr_pull
*ndr
, const void *p
)
1963 uint32_t rel_offset
;
1964 NDR_CHECK(ndr_token_retrieve(&ndr
->relative_list
, p
, &rel_offset
));
1965 return ndr_pull_set_offset(ndr
, rel_offset
);
1968 static const struct {
1969 enum ndr_err_code err
;
1971 } ndr_err_code_strings
[] = {
1972 { NDR_ERR_SUCCESS
, "Success" },
1973 { NDR_ERR_ARRAY_SIZE
, "Bad Array Size" },
1974 { NDR_ERR_BAD_SWITCH
, "Bad Switch" },
1975 { NDR_ERR_OFFSET
, "Offset Error" },
1976 { NDR_ERR_RELATIVE
, "Relative Pointer Error" },
1977 { NDR_ERR_CHARCNV
, "Character Conversion Error" },
1978 { NDR_ERR_LENGTH
, "Length Error" },
1979 { NDR_ERR_SUBCONTEXT
, "Subcontext Error" },
1980 { NDR_ERR_COMPRESSION
, "Compression Error" },
1981 { NDR_ERR_STRING
, "String Error" },
1982 { NDR_ERR_VALIDATE
, "Validate Error" },
1983 { NDR_ERR_BUFSIZE
, "Buffer Size Error" },
1984 { NDR_ERR_ALLOC
, "Allocation Error" },
1985 { NDR_ERR_RANGE
, "Range Error" },
1986 { NDR_ERR_TOKEN
, "Token Error" },
1987 { NDR_ERR_IPV4ADDRESS
, "IPv4 Address Error" },
1988 { NDR_ERR_INVALID_POINTER
, "Invalid Pointer" },
1989 { NDR_ERR_UNREAD_BYTES
, "Unread Bytes" },
1990 { NDR_ERR_NDR64
, "NDR64 assertion error" },
1991 { NDR_ERR_INCOMPLETE_BUFFER
, "Incomplete Buffer" },
1992 { NDR_ERR_MAX_RECURSION_EXCEEDED
, "Maximum Recursion Exceeded" },
1993 { NDR_ERR_UNDERFLOW
, "Underflow" },
1997 _PUBLIC_
const char *ndr_map_error2string(enum ndr_err_code ndr_err
)
2000 for (i
= 0; ndr_err_code_strings
[i
].string
!= NULL
; i
++) {
2001 if (ndr_err_code_strings
[i
].err
== ndr_err
)
2002 return ndr_err_code_strings
[i
].string
;
2004 return "Unknown error";