2 Unix SMB/CIFS implementation.
6 Copyright (C) Andrew Tridgell 2003
7 Copyright (C) Jelmer Vernooij 2005-2008
9 This program is free software; you can redistribute it and/or modify
10 it under the terms of the GNU General Public License as published by
11 the Free Software Foundation; either version 3 of the License, or
12 (at your option) any later version.
14 This program is distributed in the hope that it will be useful,
15 but WITHOUT ANY WARRANTY; without even the implied warranty of
16 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17 GNU General Public License for more details.
19 You should have received a copy of the GNU General Public License
20 along with this program. If not, see <http://www.gnu.org/licenses/>.
24 this provides the core routines for NDR parsing functions
26 see http://www.opengroup.org/onlinepubs/9629399/chap14.htm for details
31 #include "librpc/ndr/libndr.h"
32 #include "../lib/util/dlinklist.h"
35 #define DBGC_CLASS DBGC_RPC_PARSE
37 #define NDR_BASE_MARSHALL_SIZE 1024
39 /* this guid indicates NDR encoding in a protocol tower */
40 const struct ndr_syntax_id ndr_transfer_syntax_ndr
= {
41 { 0x8a885d04, 0x1ceb, 0x11c9, {0x9f, 0xe8}, {0x08,0x00,0x2b,0x10,0x48,0x60} },
45 const struct ndr_syntax_id ndr_transfer_syntax_ndr64
= {
46 { 0x71710533, 0xbeba, 0x4937, {0x83, 0x19}, {0xb5,0xdb,0xef,0x9c,0xcc,0x36} },
50 const struct ndr_syntax_id ndr_syntax_id_null
= {
51 { 0, 0, 0, { 0, 0 }, { 0, 0, 0, 0, 0, 0 } },
56 work out the number of bytes needed to align on a n byte boundary
58 _PUBLIC_
size_t ndr_align_size(uint32_t offset
, size_t n
)
60 if ((offset
& (n
-1)) == 0) return 0;
61 return n
- (offset
& (n
-1));
65 initialise a ndr parse structure from a data blob
67 _PUBLIC_
struct ndr_pull
*ndr_pull_init_blob(const DATA_BLOB
*blob
, TALLOC_CTX
*mem_ctx
)
71 ndr
= talloc_zero(mem_ctx
, struct ndr_pull
);
72 if (!ndr
) return NULL
;
73 ndr
->current_mem_ctx
= mem_ctx
;
75 ndr
->data
= blob
->data
;
76 ndr
->data_size
= blob
->length
;
81 _PUBLIC_
enum ndr_err_code
ndr_pull_append(struct ndr_pull
*ndr
, DATA_BLOB
*blob
)
83 enum ndr_err_code ndr_err
;
88 if (blob
->length
== 0) {
89 return NDR_ERR_SUCCESS
;
92 ndr_err
= ndr_token_retrieve(&ndr
->array_size_list
, ndr
, &append
);
93 if (ndr_err
== NDR_ERR_TOKEN
) {
95 ndr_err
= NDR_ERR_SUCCESS
;
99 if (ndr
->data_size
== 0) {
104 if (append
== UINT32_MAX
) {
106 * append == UINT32_MAX means that
107 * ndr->data is either NULL or a valid
108 * talloc child of ndr, which means
109 * we can use data_blob_append() without
110 * data_blob_talloc() of the existing callers data
112 b
= data_blob_const(ndr
->data
, ndr
->data_size
);
114 b
= data_blob_talloc(ndr
, ndr
->data
, ndr
->data_size
);
115 if (b
.data
== NULL
) {
116 return ndr_pull_error(ndr
, NDR_ERR_ALLOC
, "%s", __location__
);
120 ok
= data_blob_append(ndr
, &b
, blob
->data
, blob
->length
);
122 return ndr_pull_error(ndr
, NDR_ERR_ALLOC
, "%s", __location__
);
126 ndr
->data_size
= b
.length
;
128 return ndr_token_store(ndr
, &ndr
->array_size_list
, ndr
, UINT32_MAX
);
131 _PUBLIC_
enum ndr_err_code
ndr_pull_pop(struct ndr_pull
*ndr
)
136 if (ndr
->relative_base_offset
!= 0) {
137 return ndr_pull_error(ndr
, NDR_ERR_RELATIVE
,
140 if (ndr
->relative_highest_offset
!= 0) {
141 return ndr_pull_error(ndr
, NDR_ERR_RELATIVE
,
144 if (ndr
->relative_list
.count
!= 0) {
145 return ndr_pull_error(ndr
, NDR_ERR_RELATIVE
,
148 if (ndr
->relative_base_list
.count
!= 0) {
149 return ndr_pull_error(ndr
, NDR_ERR_RELATIVE
,
154 * we need to keep up to 7 bytes
155 * in order to get the aligment right.
157 skip
= ndr
->offset
& 0xFFFFFFF8;
160 return NDR_ERR_SUCCESS
;
164 ndr
->data_size
-= skip
;
166 append
= ndr_token_peek(&ndr
->array_size_list
, ndr
);
167 if (append
!= UINT32_MAX
) {
169 * here we assume, that ndr->data is not a
170 * talloc child of ndr.
173 return NDR_ERR_SUCCESS
;
176 memmove(ndr
->data
, ndr
->data
+ skip
, ndr
->data_size
);
178 ndr
->data
= talloc_realloc(ndr
, ndr
->data
, uint8_t, ndr
->data_size
);
179 if (ndr
->data_size
!= 0 && ndr
->data
== NULL
) {
180 return ndr_pull_error(ndr
, NDR_ERR_ALLOC
, "%s", __location__
);
183 return NDR_ERR_SUCCESS
;
187 advance by 'size' bytes
189 _PUBLIC_
enum ndr_err_code
ndr_pull_advance(struct ndr_pull
*ndr
, uint32_t size
)
192 if (ndr
->offset
> ndr
->data_size
) {
193 return ndr_pull_error(ndr
, NDR_ERR_BUFSIZE
,
194 "ndr_pull_advance by %u failed",
197 return NDR_ERR_SUCCESS
;
201 set the parse offset to 'ofs'
203 static enum ndr_err_code
ndr_pull_set_offset(struct ndr_pull
*ndr
, uint32_t ofs
)
206 if (ndr
->offset
> ndr
->data_size
) {
207 return ndr_pull_error(ndr
, NDR_ERR_BUFSIZE
,
208 "ndr_pull_set_offset %u failed",
211 return NDR_ERR_SUCCESS
;
214 /* create a ndr_push structure, ready for some marshalling */
215 _PUBLIC_
struct ndr_push
*ndr_push_init_ctx(TALLOC_CTX
*mem_ctx
)
217 struct ndr_push
*ndr
;
219 ndr
= talloc_zero(mem_ctx
, struct ndr_push
);
225 ndr
->alloc_size
= NDR_BASE_MARSHALL_SIZE
;
226 ndr
->data
= talloc_array(ndr
, uint8_t, ndr
->alloc_size
);
235 /* return a DATA_BLOB structure for the current ndr_push marshalled data */
236 _PUBLIC_ DATA_BLOB
ndr_push_blob(struct ndr_push
*ndr
)
239 blob
= data_blob_const(ndr
->data
, ndr
->offset
);
240 if (ndr
->alloc_size
> ndr
->offset
) {
241 ndr
->data
[ndr
->offset
] = 0;
248 expand the available space in the buffer to ndr->offset + extra_size
250 _PUBLIC_
enum ndr_err_code
ndr_push_expand(struct ndr_push
*ndr
, uint32_t extra_size
)
252 uint32_t size
= extra_size
+ ndr
->offset
;
254 if (size
< ndr
->offset
) {
255 /* extra_size overflowed the offset */
256 return ndr_push_error(ndr
, NDR_ERR_BUFSIZE
, "Overflow in push_expand to %u",
260 if (ndr
->fixed_buf_size
) {
261 if (ndr
->alloc_size
>= size
) {
262 return NDR_ERR_SUCCESS
;
264 return ndr_push_error(ndr
,
266 "Overflow of fixed buffer in "
271 if (ndr
->alloc_size
> size
) {
272 return NDR_ERR_SUCCESS
;
275 ndr
->alloc_size
+= NDR_BASE_MARSHALL_SIZE
;
276 if (size
+1 > ndr
->alloc_size
) {
277 ndr
->alloc_size
= size
+1;
279 ndr
->data
= talloc_realloc(ndr
, ndr
->data
, uint8_t, ndr
->alloc_size
);
281 return ndr_push_error(ndr
, NDR_ERR_ALLOC
, "Failed to push_expand to %u",
285 return NDR_ERR_SUCCESS
;
288 _PUBLIC_
void ndr_print_debugc_helper(struct ndr_print
*ndr
, const char *format
, ...)
296 va_start(ap
, format
);
297 ret
= vasprintf(&s
, format
, ap
);
304 dbgc_class
= *(int *)ndr
->private_data
;
306 if (ndr
->no_newline
) {
307 DEBUGADDC(dbgc_class
, 1,("%s", s
));
312 for (i
=0;i
<ndr
->depth
;i
++) {
313 DEBUGADDC(dbgc_class
, 1,(" "));
316 DEBUGADDC(dbgc_class
, 1,("%s\n", s
));
320 _PUBLIC_
void ndr_print_debug_helper(struct ndr_print
*ndr
, const char *format
, ...)
327 va_start(ap
, format
);
328 ret
= vasprintf(&s
, format
, ap
);
335 if (ndr
->no_newline
) {
336 DEBUGADD(1,("%s", s
));
341 for (i
=0;i
<ndr
->depth
;i
++) {
345 DEBUGADD(1,("%s\n", s
));
349 _PUBLIC_
void ndr_print_printf_helper(struct ndr_print
*ndr
, const char *format
, ...)
354 if (!ndr
->no_newline
) {
355 for (i
=0;i
<ndr
->depth
;i
++) {
360 va_start(ap
, format
);
363 if (!ndr
->no_newline
) {
368 _PUBLIC_
void ndr_print_string_helper(struct ndr_print
*ndr
, const char *format
, ...)
373 if (!ndr
->no_newline
) {
374 for (i
=0;i
<ndr
->depth
;i
++) {
375 ndr
->private_data
= talloc_asprintf_append_buffer(
376 (char *)ndr
->private_data
, " ");
380 va_start(ap
, format
);
381 ndr
->private_data
= talloc_vasprintf_append_buffer((char *)ndr
->private_data
,
384 if (!ndr
->no_newline
) {
385 ndr
->private_data
= talloc_asprintf_append_buffer((char *)ndr
->private_data
,
391 a useful helper function for printing idl structures via DEBUGC()
393 _PUBLIC_
void ndr_print_debugc(int dbgc_class
, ndr_print_fn_t fn
, const char *name
, void *ptr
)
395 struct ndr_print
*ndr
;
397 DEBUGC(dbgc_class
, 1,(" "));
399 ndr
= talloc_zero(NULL
, struct ndr_print
);
401 ndr
->private_data
= &dbgc_class
;
402 ndr
->print
= ndr_print_debugc_helper
;
405 #ifdef DEBUG_PASSWORD
406 if (CHECK_DEBUGLVL(100)) {
407 ndr
->print_secrets
= true;
416 a useful helper function for printing idl structures via DEBUG()
418 _PUBLIC_
void ndr_print_debug(ndr_print_fn_t fn
, const char *name
, void *ptr
)
420 struct ndr_print
*ndr
;
424 ndr
= talloc_zero(NULL
, struct ndr_print
);
426 ndr
->print
= ndr_print_debug_helper
;
429 #ifdef DEBUG_PASSWORD
430 if (CHECK_DEBUGLVL(100)) {
431 ndr
->print_secrets
= true;
440 a useful helper function for printing idl unions via DEBUG()
442 _PUBLIC_
void ndr_print_union_debug(ndr_print_fn_t fn
, const char *name
, uint32_t level
, void *ptr
)
444 struct ndr_print
*ndr
;
448 ndr
= talloc_zero(NULL
, struct ndr_print
);
450 ndr
->print
= ndr_print_debug_helper
;
453 #ifdef DEBUG_PASSWORD
454 if (CHECK_DEBUGLVL(100)) {
455 ndr
->print_secrets
= true;
459 ndr_print_set_switch_value(ndr
, ptr
, level
);
465 a useful helper function for printing idl function calls via DEBUG()
467 _PUBLIC_
void ndr_print_function_debug(ndr_print_function_t fn
, const char *name
, int flags
, void *ptr
)
469 struct ndr_print
*ndr
;
473 ndr
= talloc_zero(NULL
, struct ndr_print
);
475 ndr
->print
= ndr_print_debug_helper
;
478 #ifdef DEBUG_PASSWORD
479 if (CHECK_DEBUGLVL(100)) {
480 ndr
->print_secrets
= true;
484 fn(ndr
, name
, flags
, ptr
);
489 a useful helper function for printing idl structures to a string
491 _PUBLIC_
char *ndr_print_struct_string(TALLOC_CTX
*mem_ctx
, ndr_print_fn_t fn
, const char *name
, void *ptr
)
493 struct ndr_print
*ndr
;
496 ndr
= talloc_zero(mem_ctx
, struct ndr_print
);
497 if (!ndr
) return NULL
;
498 ndr
->private_data
= talloc_strdup(ndr
, "");
499 if (!ndr
->private_data
) {
502 ndr
->print
= ndr_print_string_helper
;
507 ret
= talloc_steal(mem_ctx
, (char *)ndr
->private_data
);
514 a useful helper function for printing idl unions to a string
516 _PUBLIC_
char *ndr_print_union_string(TALLOC_CTX
*mem_ctx
, ndr_print_fn_t fn
, const char *name
, uint32_t level
, void *ptr
)
518 struct ndr_print
*ndr
;
521 ndr
= talloc_zero(mem_ctx
, struct ndr_print
);
522 if (!ndr
) return NULL
;
523 ndr
->private_data
= talloc_strdup(ndr
, "");
524 if (!ndr
->private_data
) {
527 ndr
->print
= ndr_print_string_helper
;
530 ndr_print_set_switch_value(ndr
, ptr
, level
);
532 ret
= talloc_steal(mem_ctx
, (char *)ndr
->private_data
);
539 a useful helper function for printing idl function calls to a string
541 _PUBLIC_
char *ndr_print_function_string(TALLOC_CTX
*mem_ctx
,
542 ndr_print_function_t fn
, const char *name
,
543 int flags
, void *ptr
)
545 struct ndr_print
*ndr
;
548 ndr
= talloc_zero(mem_ctx
, struct ndr_print
);
549 if (!ndr
) return NULL
;
550 ndr
->private_data
= talloc_strdup(ndr
, "");
551 if (!ndr
->private_data
) {
554 ndr
->print
= ndr_print_string_helper
;
557 fn(ndr
, name
, flags
, ptr
);
558 ret
= talloc_steal(mem_ctx
, (char *)ndr
->private_data
);
564 _PUBLIC_
void ndr_set_flags(uint32_t *pflags
, uint32_t new_flags
)
566 /* the big/little endian flags are inter-dependent */
567 if (new_flags
& LIBNDR_FLAG_LITTLE_ENDIAN
) {
568 (*pflags
) &= ~LIBNDR_FLAG_BIGENDIAN
;
569 (*pflags
) &= ~LIBNDR_FLAG_NDR64
;
571 if (new_flags
& LIBNDR_FLAG_BIGENDIAN
) {
572 (*pflags
) &= ~LIBNDR_FLAG_LITTLE_ENDIAN
;
573 (*pflags
) &= ~LIBNDR_FLAG_NDR64
;
575 if (new_flags
& LIBNDR_ALIGN_FLAGS
) {
576 /* Ensure we only have the passed-in
577 align flag set in the new_flags,
578 remove any old align flag. */
579 (*pflags
) &= ~LIBNDR_ALIGN_FLAGS
;
581 if (new_flags
& LIBNDR_FLAG_NO_RELATIVE_REVERSE
) {
582 (*pflags
) &= ~LIBNDR_FLAG_RELATIVE_REVERSE
;
584 (*pflags
) |= new_flags
;
588 return and possibly log an NDR error
590 _PUBLIC_
enum ndr_err_code
ndr_pull_error(struct ndr_pull
*ndr
,
591 enum ndr_err_code ndr_err
,
592 const char *format
, ...)
598 if (ndr
->flags
& LIBNDR_FLAG_INCOMPLETE_BUFFER
) {
600 case NDR_ERR_BUFSIZE
:
601 return NDR_ERR_INCOMPLETE_BUFFER
;
607 va_start(ap
, format
);
608 ret
= vasprintf(&s
, format
, ap
);
612 return NDR_ERR_ALLOC
;
615 DEBUG(1,("ndr_pull_error(%u): %s\n", ndr_err
, s
));
623 return and possibly log an NDR error
625 _PUBLIC_
enum ndr_err_code
ndr_push_error(struct ndr_push
*ndr
,
626 enum ndr_err_code ndr_err
,
627 const char *format
, ...)
633 va_start(ap
, format
);
634 ret
= vasprintf(&s
, format
, ap
);
638 return NDR_ERR_ALLOC
;
641 DEBUG(1,("ndr_push_error(%u): %s\n", ndr_err
, s
));
649 handle subcontext buffers, which in midl land are user-marshalled, but
650 we use magic in pidl to make them easier to cope with
652 _PUBLIC_
enum ndr_err_code
ndr_pull_subcontext_start(struct ndr_pull
*ndr
,
653 struct ndr_pull
**_subndr
,
657 struct ndr_pull
*subndr
;
658 uint32_t r_content_size
;
659 bool force_le
= false;
660 bool force_be
= false;
662 switch (header_size
) {
664 uint32_t content_size
= ndr
->data_size
- ndr
->offset
;
666 content_size
= size_is
;
668 r_content_size
= content_size
;
673 uint16_t content_size
;
674 NDR_CHECK(ndr_pull_uint16(ndr
, NDR_SCALARS
, &content_size
));
675 if (size_is
>= 0 && size_is
!= content_size
) {
676 return ndr_pull_error(ndr
, NDR_ERR_SUBCONTEXT
, "Bad subcontext (PULL) size_is(%d) (0x%04x) mismatch content_size %d (0x%04x)",
677 (int)size_is
, (int)size_is
,
681 r_content_size
= content_size
;
686 uint32_t content_size
;
687 NDR_CHECK(ndr_pull_uint3264(ndr
, NDR_SCALARS
, &content_size
));
688 if (size_is
>= 0 && size_is
!= content_size
) {
689 return ndr_pull_error(ndr
, NDR_ERR_SUBCONTEXT
, "Bad subcontext (PULL) size_is(%d) (0x%08x) mismatch content_size %d (0x%08x)",
690 (int)size_is
, (int)size_is
,
694 r_content_size
= content_size
;
699 * Common Type Header for the Serialization Stream
700 * See [MS-RPCE] 2.2.6 Type Serialization Version 1
706 uint32_t content_size
;
710 NDR_CHECK(ndr_pull_uint8(ndr
, NDR_SCALARS
, &version
));
713 return ndr_pull_error(ndr
, NDR_ERR_SUBCONTEXT
,
714 "Bad subcontext (PULL) Common Type Header version %d != 1",
722 NDR_CHECK(ndr_pull_uint8(ndr
, NDR_SCALARS
, &drep
));
725 } else if (drep
== 0x00) {
728 return ndr_pull_error(ndr
, NDR_ERR_SUBCONTEXT
,
729 "Bad subcontext (PULL) Common Type Header invalid drep 0x%02X",
733 /* length of the "Private Header for Constructed Type" */
734 NDR_CHECK(ndr_pull_uint16(ndr
, NDR_SCALARS
, &hdrlen
));
736 return ndr_pull_error(ndr
, NDR_ERR_SUBCONTEXT
,
737 "Bad subcontext (PULL) Common Type Header length %d != 8",
741 /* filler should be ignored */
742 NDR_CHECK(ndr_pull_uint32(ndr
, NDR_SCALARS
, &filler
));
745 * Private Header for Constructed Type
747 /* length - will be updated latter */
748 NDR_CHECK(ndr_pull_uint32(ndr
, NDR_SCALARS
, &content_size
));
749 if (size_is
>= 0 && size_is
!= content_size
) {
750 return ndr_pull_error(ndr
, NDR_ERR_SUBCONTEXT
, "Bad subcontext (PULL) size_is(%d) mismatch content_size %d",
751 (int)size_is
, (int)content_size
);
753 /* the content size must be a multiple of 8 */
754 if ((content_size
% 8) != 0) {
755 return ndr_pull_error(ndr
, NDR_ERR_SUBCONTEXT
,
756 "Bad subcontext (PULL) size_is(%d) not padded to 8 content_size %d",
757 (int)size_is
, (int)content_size
);
759 r_content_size
= content_size
;
762 NDR_CHECK(ndr_pull_uint32(ndr
, NDR_SCALARS
, &reserved
));
767 * a shallow copy like subcontext
768 * useful for DCERPC pipe chunks.
770 subndr
= talloc_zero(ndr
, struct ndr_pull
);
771 NDR_ERR_HAVE_NO_MEMORY(subndr
);
773 subndr
->flags
= ndr
->flags
;
774 subndr
->current_mem_ctx
= ndr
->current_mem_ctx
;
775 subndr
->data
= ndr
->data
;
776 subndr
->offset
= ndr
->offset
;
777 subndr
->data_size
= ndr
->data_size
;
780 return NDR_ERR_SUCCESS
;
783 return ndr_pull_error(ndr
, NDR_ERR_SUBCONTEXT
, "Bad subcontext (PULL) header_size %d",
787 NDR_PULL_NEED_BYTES(ndr
, r_content_size
);
789 subndr
= talloc_zero(ndr
, struct ndr_pull
);
790 NDR_ERR_HAVE_NO_MEMORY(subndr
);
791 subndr
->flags
= ndr
->flags
& ~LIBNDR_FLAG_NDR64
;
792 subndr
->current_mem_ctx
= ndr
->current_mem_ctx
;
794 subndr
->data
= ndr
->data
+ ndr
->offset
;
796 subndr
->data_size
= r_content_size
;
799 ndr_set_flags(&ndr
->flags
, LIBNDR_FLAG_LITTLE_ENDIAN
);
800 } else if (force_be
) {
801 ndr_set_flags(&ndr
->flags
, LIBNDR_FLAG_BIGENDIAN
);
805 return NDR_ERR_SUCCESS
;
808 _PUBLIC_
enum ndr_err_code
ndr_pull_subcontext_end(struct ndr_pull
*ndr
,
809 struct ndr_pull
*subndr
,
814 uint32_t highest_ofs
;
816 if (header_size
== 0xFFFFFFFF) {
817 advance
= subndr
->offset
- ndr
->offset
;
818 } else if (size_is
>= 0) {
820 } else if (header_size
> 0) {
821 advance
= subndr
->data_size
;
823 advance
= subndr
->offset
;
826 if (subndr
->offset
> ndr
->relative_highest_offset
) {
827 highest_ofs
= subndr
->offset
;
829 highest_ofs
= subndr
->relative_highest_offset
;
831 if (!(subndr
->flags
& LIBNDR_FLAG_SUBCONTEXT_NO_UNREAD_BYTES
)) {
833 * avoid an error unless SUBCONTEXT_NO_UNREAD_BYTES is specified
835 highest_ofs
= advance
;
837 if (highest_ofs
< advance
) {
838 return ndr_pull_error(subndr
, NDR_ERR_UNREAD_BYTES
,
839 "not all bytes consumed ofs[%u] advance[%u]",
840 highest_ofs
, advance
);
843 NDR_CHECK(ndr_pull_advance(ndr
, advance
));
844 return NDR_ERR_SUCCESS
;
847 _PUBLIC_
enum ndr_err_code
ndr_push_subcontext_start(struct ndr_push
*ndr
,
848 struct ndr_push
**_subndr
,
852 struct ndr_push
*subndr
;
854 subndr
= ndr_push_init_ctx(ndr
);
855 NDR_ERR_HAVE_NO_MEMORY(subndr
);
856 subndr
->flags
= ndr
->flags
& ~LIBNDR_FLAG_NDR64
;
859 NDR_CHECK(ndr_push_zero(subndr
, size_is
));
861 subndr
->relative_end_offset
= size_is
;
865 return NDR_ERR_SUCCESS
;
869 push a subcontext header
871 _PUBLIC_
enum ndr_err_code
ndr_push_subcontext_end(struct ndr_push
*ndr
,
872 struct ndr_push
*subndr
,
879 padding_len
= size_is
- subndr
->offset
;
880 if (padding_len
< 0) {
881 return ndr_push_error(ndr
, NDR_ERR_SUBCONTEXT
, "Bad subcontext (PUSH) content_size %d is larger than size_is(%d)",
882 (int)subndr
->offset
, (int)size_is
);
884 subndr
->offset
= size_is
;
887 switch (header_size
) {
892 NDR_CHECK(ndr_push_uint16(ndr
, NDR_SCALARS
, subndr
->offset
));
896 NDR_CHECK(ndr_push_uint3264(ndr
, NDR_SCALARS
, subndr
->offset
));
901 * Common Type Header for the Serialization Stream
902 * See [MS-RPCE] 2.2.6 Type Serialization Version 1
904 padding_len
= NDR_ROUND(subndr
->offset
, 8) - subndr
->offset
;
905 if (padding_len
> 0) {
906 NDR_CHECK(ndr_push_zero(subndr
, padding_len
));
910 NDR_CHECK(ndr_push_uint8(ndr
, NDR_SCALARS
, 1));
916 NDR_CHECK(ndr_push_uint8(ndr
, NDR_SCALARS
, NDR_BE(ndr
)?0x00:0x10));
918 /* length of the "Private Header for Constructed Type" */
919 NDR_CHECK(ndr_push_uint16(ndr
, NDR_SCALARS
, 8));
922 NDR_CHECK(ndr_push_uint32(ndr
, NDR_SCALARS
, 0xCCCCCCCC));
925 * Private Header for Constructed Type
927 /* length - will be updated latter */
928 NDR_CHECK(ndr_push_uint32(ndr
, NDR_SCALARS
, subndr
->offset
));
931 NDR_CHECK(ndr_push_uint32(ndr
, NDR_SCALARS
, 0));
935 return ndr_push_error(ndr
, NDR_ERR_SUBCONTEXT
, "Bad subcontext header size %d",
939 NDR_CHECK(ndr_push_bytes(ndr
, subndr
->data
, subndr
->offset
));
940 return NDR_ERR_SUCCESS
;
950 store a token in the ndr context, for later retrieval
952 _PUBLIC_
enum ndr_err_code
ndr_token_store(TALLOC_CTX
*mem_ctx
,
953 struct ndr_token_list
*list
,
957 if (list
->tokens
== NULL
) {
958 list
->tokens
= talloc_array(mem_ctx
, struct ndr_token
, 10);
959 if (list
->tokens
== NULL
) {
960 NDR_ERR_HAVE_NO_MEMORY(list
->tokens
);
963 uint32_t alloc_count
= talloc_array_length(list
->tokens
);
964 if (list
->count
== alloc_count
) {
966 unsigned increment
= MIN(list
->count
, 1000);
967 new_alloc
= alloc_count
+ increment
;
968 if (new_alloc
< alloc_count
) {
969 return NDR_ERR_RANGE
;
971 list
->tokens
= talloc_realloc(mem_ctx
, list
->tokens
,
972 struct ndr_token
, new_alloc
);
973 if (list
->tokens
== NULL
) {
974 NDR_ERR_HAVE_NO_MEMORY(list
->tokens
);
978 list
->tokens
[list
->count
].key
= key
;
979 list
->tokens
[list
->count
].value
= value
;
981 return NDR_ERR_SUCCESS
;
985 retrieve a token from a ndr context, using cmp_fn to match the tokens
987 _PUBLIC_
enum ndr_err_code
ndr_token_retrieve_cmp_fn(struct ndr_token_list
*list
,
988 const void *key
, uint32_t *v
,
989 comparison_fn_t _cmp_fn
,
992 struct ndr_token
*tokens
= list
->tokens
;
995 for (i
= list
->count
- 1; i
< list
->count
; i
--) {
996 if (_cmp_fn(tokens
[i
].key
, key
) == 0) {
1001 for (i
= list
->count
- 1; i
< list
->count
; i
--) {
1002 if (tokens
[i
].key
== key
) {
1007 return NDR_ERR_TOKEN
;
1009 *v
= tokens
[i
].value
;
1011 if (i
!= list
->count
- 1) {
1012 tokens
[i
] = tokens
[list
->count
- 1];
1016 return NDR_ERR_SUCCESS
;
1020 retrieve a token from a ndr context
1022 _PUBLIC_
enum ndr_err_code
ndr_token_retrieve(struct ndr_token_list
*list
,
1023 const void *key
, uint32_t *v
)
1025 return ndr_token_retrieve_cmp_fn(list
, key
, v
, NULL
, true);
1029 peek at but don't removed a token from a ndr context
1031 _PUBLIC_
uint32_t ndr_token_peek(struct ndr_token_list
*list
, const void *key
)
1034 struct ndr_token
*tokens
= list
->tokens
;
1036 for (i
= list
->count
- 1; i
< list
->count
; i
--) {
1037 if (tokens
[i
].key
== key
) {
1038 return tokens
[i
].value
;
1046 pull an array size field and add it to the array_size_list token list
1048 _PUBLIC_
enum ndr_err_code
ndr_pull_array_size(struct ndr_pull
*ndr
, const void *p
)
1051 NDR_CHECK(ndr_pull_uint3264(ndr
, NDR_SCALARS
, &size
));
1052 return ndr_token_store(ndr
, &ndr
->array_size_list
, p
, size
);
1056 get the stored array size field
1058 _PUBLIC_
uint32_t ndr_get_array_size(struct ndr_pull
*ndr
, const void *p
)
1060 return ndr_token_peek(&ndr
->array_size_list
, p
);
1064 check the stored array size field
1066 _PUBLIC_
enum ndr_err_code
ndr_check_array_size(struct ndr_pull
*ndr
, void *p
, uint32_t size
)
1069 stored
= ndr_token_peek(&ndr
->array_size_list
, p
);
1070 if (stored
!= size
) {
1071 return ndr_pull_error(ndr
, NDR_ERR_ARRAY_SIZE
,
1072 "Bad array size - got %u expected %u\n",
1075 return NDR_ERR_SUCCESS
;
1079 pull an array length field and add it to the array_length_list token list
1081 _PUBLIC_
enum ndr_err_code
ndr_pull_array_length(struct ndr_pull
*ndr
, const void *p
)
1083 uint32_t length
, offset
;
1084 NDR_CHECK(ndr_pull_uint3264(ndr
, NDR_SCALARS
, &offset
));
1086 return ndr_pull_error(ndr
, NDR_ERR_ARRAY_SIZE
,
1087 "non-zero array offset %u\n", offset
);
1089 NDR_CHECK(ndr_pull_uint3264(ndr
, NDR_SCALARS
, &length
));
1090 return ndr_token_store(ndr
, &ndr
->array_length_list
, p
, length
);
1094 get the stored array length field
1096 _PUBLIC_
uint32_t ndr_get_array_length(struct ndr_pull
*ndr
, const void *p
)
1098 return ndr_token_peek(&ndr
->array_length_list
, p
);
1102 check the stored array length field
1104 _PUBLIC_
enum ndr_err_code
ndr_check_array_length(struct ndr_pull
*ndr
, void *p
, uint32_t length
)
1107 stored
= ndr_token_peek(&ndr
->array_length_list
, p
);
1108 if (stored
!= length
) {
1109 return ndr_pull_error(ndr
, NDR_ERR_ARRAY_SIZE
,
1110 "Bad array length - got %u expected %u\n",
1113 return NDR_ERR_SUCCESS
;
1116 _PUBLIC_
enum ndr_err_code
ndr_push_pipe_chunk_trailer(struct ndr_push
*ndr
, int ndr_flags
, uint32_t count
)
1118 if (ndr
->flags
& LIBNDR_FLAG_NDR64
) {
1119 int64_t tmp
= 0 - (int64_t)count
;
1120 uint64_t ncount
= tmp
;
1122 NDR_CHECK(ndr_push_hyper(ndr
, ndr_flags
, ncount
));
1125 return NDR_ERR_SUCCESS
;
1128 _PUBLIC_
enum ndr_err_code
ndr_check_pipe_chunk_trailer(struct ndr_pull
*ndr
, int ndr_flags
, uint32_t count
)
1130 if (ndr
->flags
& LIBNDR_FLAG_NDR64
) {
1131 int64_t tmp
= 0 - (int64_t)count
;
1132 uint64_t ncount1
= tmp
;
1135 NDR_CHECK(ndr_pull_hyper(ndr
, ndr_flags
, &ncount2
));
1136 if (ncount1
== ncount2
) {
1137 return NDR_ERR_SUCCESS
;
1140 return ndr_pull_error(ndr
, NDR_ERR_ARRAY_SIZE
,
1141 "Bad pipe trailer[%lld should be %lld] size was %lu\"",
1142 (unsigned long long)ncount2
,
1143 (unsigned long long)ncount1
,
1144 (unsigned long)count
);
1147 return NDR_ERR_SUCCESS
;
1151 store a switch value
1153 _PUBLIC_
enum ndr_err_code
ndr_push_set_switch_value(struct ndr_push
*ndr
, const void *p
, uint32_t val
)
1155 return ndr_token_store(ndr
, &ndr
->switch_list
, p
, val
);
1158 _PUBLIC_
enum ndr_err_code
ndr_pull_set_switch_value(struct ndr_pull
*ndr
, const void *p
, uint32_t val
)
1160 return ndr_token_store(ndr
, &ndr
->switch_list
, p
, val
);
1163 _PUBLIC_
enum ndr_err_code
ndr_print_set_switch_value(struct ndr_print
*ndr
, const void *p
, uint32_t val
)
1165 return ndr_token_store(ndr
, &ndr
->switch_list
, p
, val
);
1169 retrieve a switch value
1171 _PUBLIC_
uint32_t ndr_push_get_switch_value(struct ndr_push
*ndr
, const void *p
)
1173 return ndr_token_peek(&ndr
->switch_list
, p
);
1176 _PUBLIC_
uint32_t ndr_pull_get_switch_value(struct ndr_pull
*ndr
, const void *p
)
1178 return ndr_token_peek(&ndr
->switch_list
, p
);
1181 _PUBLIC_
uint32_t ndr_print_get_switch_value(struct ndr_print
*ndr
, const void *p
)
1183 return ndr_token_peek(&ndr
->switch_list
, p
);
1186 /* retrieve a switch value and remove it from the list */
1187 _PUBLIC_
uint32_t ndr_pull_steal_switch_value(struct ndr_pull
*ndr
, const void *p
)
1189 enum ndr_err_code status
;
1192 status
= ndr_token_retrieve(&ndr
->switch_list
, p
, &v
);
1193 if (!NDR_ERR_CODE_IS_SUCCESS(status
)) {
1201 pull a struct from a blob using NDR
1203 _PUBLIC_
enum ndr_err_code
ndr_pull_struct_blob(const DATA_BLOB
*blob
, TALLOC_CTX
*mem_ctx
, void *p
,
1204 ndr_pull_flags_fn_t fn
)
1206 struct ndr_pull
*ndr
;
1207 ndr
= ndr_pull_init_blob(blob
, mem_ctx
);
1208 NDR_ERR_HAVE_NO_MEMORY(ndr
);
1209 NDR_CHECK_FREE(fn(ndr
, NDR_SCALARS
|NDR_BUFFERS
, p
));
1211 return NDR_ERR_SUCCESS
;
1215 pull a struct from a blob using NDR - failing if all bytes are not consumed
1217 _PUBLIC_
enum ndr_err_code
ndr_pull_struct_blob_all(const DATA_BLOB
*blob
, TALLOC_CTX
*mem_ctx
,
1218 void *p
, ndr_pull_flags_fn_t fn
)
1220 struct ndr_pull
*ndr
;
1221 uint32_t highest_ofs
;
1222 ndr
= ndr_pull_init_blob(blob
, mem_ctx
);
1223 NDR_ERR_HAVE_NO_MEMORY(ndr
);
1224 NDR_CHECK_FREE(fn(ndr
, NDR_SCALARS
|NDR_BUFFERS
, p
));
1225 if (ndr
->offset
> ndr
->relative_highest_offset
) {
1226 highest_ofs
= ndr
->offset
;
1228 highest_ofs
= ndr
->relative_highest_offset
;
1230 if (highest_ofs
< ndr
->data_size
) {
1231 enum ndr_err_code ret
;
1232 ret
= ndr_pull_error(ndr
, NDR_ERR_UNREAD_BYTES
,
1233 "not all bytes consumed ofs[%u] size[%u]",
1234 highest_ofs
, ndr
->data_size
);
1239 return NDR_ERR_SUCCESS
;
1243 pull a struct from a blob using NDR - failing if all bytes are not consumed
1245 This only works for structures with NO allocated memory, like
1246 objectSID and GUID. This helps because we parse these a lot.
1248 _PUBLIC_
enum ndr_err_code
ndr_pull_struct_blob_all_noalloc(const DATA_BLOB
*blob
,
1249 void *p
, ndr_pull_flags_fn_t fn
)
1252 * We init this structure on the stack here, to avoid a
1253 * talloc() as otherwise this call to the fn() is assured not
1254 * to be doing any allocation, eg SIDs and GUIDs.
1256 * This allows us to keep the safety of the PIDL-generated
1257 * code without the talloc() overhead.
1259 struct ndr_pull ndr
= {
1261 .data_size
= blob
->length
,
1262 .current_mem_ctx
= (void *)-1
1264 uint32_t highest_ofs
;
1265 NDR_CHECK(fn(&ndr
, NDR_SCALARS
|NDR_BUFFERS
, p
));
1266 if (ndr
.offset
> ndr
.relative_highest_offset
) {
1267 highest_ofs
= ndr
.offset
;
1269 highest_ofs
= ndr
.relative_highest_offset
;
1271 if (highest_ofs
< ndr
.data_size
) {
1272 enum ndr_err_code ret
;
1273 ret
= ndr_pull_error(&ndr
, NDR_ERR_UNREAD_BYTES
,
1274 "not all bytes consumed ofs[%u] size[%u]",
1275 highest_ofs
, ndr
.data_size
);
1278 return NDR_ERR_SUCCESS
;
1282 pull a union from a blob using NDR, given the union discriminator
1284 _PUBLIC_
enum ndr_err_code
ndr_pull_union_blob(const DATA_BLOB
*blob
, TALLOC_CTX
*mem_ctx
,
1286 uint32_t level
, ndr_pull_flags_fn_t fn
)
1288 struct ndr_pull
*ndr
;
1289 ndr
= ndr_pull_init_blob(blob
, mem_ctx
);
1290 NDR_ERR_HAVE_NO_MEMORY(ndr
);
1291 NDR_CHECK_FREE(ndr_pull_set_switch_value(ndr
, p
, level
));
1292 NDR_CHECK_FREE(fn(ndr
, NDR_SCALARS
|NDR_BUFFERS
, p
));
1294 return NDR_ERR_SUCCESS
;
1298 pull a union from a blob using NDR, given the union discriminator,
1299 failing if all bytes are not consumed
1301 _PUBLIC_
enum ndr_err_code
ndr_pull_union_blob_all(const DATA_BLOB
*blob
, TALLOC_CTX
*mem_ctx
,
1303 uint32_t level
, ndr_pull_flags_fn_t fn
)
1305 struct ndr_pull
*ndr
;
1306 uint32_t highest_ofs
;
1307 ndr
= ndr_pull_init_blob(blob
, mem_ctx
);
1308 NDR_ERR_HAVE_NO_MEMORY(ndr
);
1309 NDR_CHECK_FREE(ndr_pull_set_switch_value(ndr
, p
, level
));
1310 NDR_CHECK_FREE(fn(ndr
, NDR_SCALARS
|NDR_BUFFERS
, p
));
1311 if (ndr
->offset
> ndr
->relative_highest_offset
) {
1312 highest_ofs
= ndr
->offset
;
1314 highest_ofs
= ndr
->relative_highest_offset
;
1316 if (highest_ofs
< ndr
->data_size
) {
1317 enum ndr_err_code ret
;
1318 ret
= ndr_pull_error(ndr
, NDR_ERR_UNREAD_BYTES
,
1319 "not all bytes consumed ofs[%u] size[%u]",
1320 highest_ofs
, ndr
->data_size
);
1325 return NDR_ERR_SUCCESS
;
1329 push a struct to a blob using NDR
1331 _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
)
1333 struct ndr_push
*ndr
;
1334 ndr
= ndr_push_init_ctx(mem_ctx
);
1335 NDR_ERR_HAVE_NO_MEMORY(ndr
);
1337 NDR_CHECK(fn(ndr
, NDR_SCALARS
|NDR_BUFFERS
, p
));
1339 *blob
= ndr_push_blob(ndr
);
1340 talloc_steal(mem_ctx
, blob
->data
);
1343 return NDR_ERR_SUCCESS
;
1347 push a struct into a provided blob using NDR.
1349 We error because we want to have the performance issue (extra
1350 talloc() calls) show up as an error, not just slower code. This is
1351 used for things like GUIDs, which we expect to be a fixed size, and
1352 SIDs that we can pre-calculate the size for.
1354 _PUBLIC_
enum ndr_err_code
ndr_push_struct_into_fixed_blob(
1355 DATA_BLOB
*blob
, const void *p
, ndr_push_flags_fn_t fn
)
1357 struct ndr_push ndr
= {
1359 .alloc_size
= blob
->length
,
1360 .fixed_buf_size
= true
1363 NDR_CHECK(fn(&ndr
, NDR_SCALARS
|NDR_BUFFERS
, p
));
1365 if (ndr
.offset
!= blob
->length
) {
1366 return ndr_push_error(&ndr
, NDR_ERR_BUFSIZE
,
1367 "buffer was either to large or small "
1368 "ofs[%u] size[%zu]",
1369 ndr
.offset
, blob
->length
);
1372 return NDR_ERR_SUCCESS
;
1376 push a union to a blob using NDR
1378 _PUBLIC_
enum ndr_err_code
ndr_push_union_blob(DATA_BLOB
*blob
, TALLOC_CTX
*mem_ctx
, void *p
,
1379 uint32_t level
, ndr_push_flags_fn_t fn
)
1381 struct ndr_push
*ndr
;
1382 ndr
= ndr_push_init_ctx(mem_ctx
);
1383 NDR_ERR_HAVE_NO_MEMORY(ndr
);
1385 NDR_CHECK(ndr_push_set_switch_value(ndr
, p
, level
));
1386 NDR_CHECK(fn(ndr
, NDR_SCALARS
|NDR_BUFFERS
, p
));
1388 *blob
= ndr_push_blob(ndr
);
1389 talloc_steal(mem_ctx
, blob
->data
);
1392 return NDR_ERR_SUCCESS
;
1396 generic ndr_size_*() handler for structures
1398 _PUBLIC_
size_t ndr_size_struct(const void *p
, int flags
, ndr_push_flags_fn_t push
)
1400 struct ndr_push
*ndr
;
1401 enum ndr_err_code status
;
1404 /* avoid recursion */
1405 if (flags
& LIBNDR_FLAG_NO_NDR_SIZE
) return 0;
1407 ndr
= ndr_push_init_ctx(NULL
);
1409 ndr
->flags
|= flags
| LIBNDR_FLAG_NO_NDR_SIZE
;
1410 status
= push(ndr
, NDR_SCALARS
|NDR_BUFFERS
, discard_const(p
));
1411 if (!NDR_ERR_CODE_IS_SUCCESS(status
)) {
1421 generic ndr_size_*() handler for unions
1423 _PUBLIC_
size_t ndr_size_union(const void *p
, int flags
, uint32_t level
, ndr_push_flags_fn_t push
)
1425 struct ndr_push
*ndr
;
1426 enum ndr_err_code status
;
1429 /* avoid recursion */
1430 if (flags
& LIBNDR_FLAG_NO_NDR_SIZE
) return 0;
1432 ndr
= ndr_push_init_ctx(NULL
);
1434 ndr
->flags
|= flags
| LIBNDR_FLAG_NO_NDR_SIZE
;
1436 status
= ndr_push_set_switch_value(ndr
, p
, level
);
1437 if (!NDR_ERR_CODE_IS_SUCCESS(status
)) {
1441 status
= push(ndr
, NDR_SCALARS
|NDR_BUFFERS
, p
);
1442 if (!NDR_ERR_CODE_IS_SUCCESS(status
)) {
1452 get the current base for relative pointers for the push
1454 _PUBLIC_
uint32_t ndr_push_get_relative_base_offset(struct ndr_push
*ndr
)
1456 return ndr
->relative_base_offset
;
1460 restore the old base for relative pointers for the push
1462 _PUBLIC_
void ndr_push_restore_relative_base_offset(struct ndr_push
*ndr
, uint32_t offset
)
1464 ndr
->relative_base_offset
= offset
;
1468 setup the current base for relative pointers for the push
1469 called in the NDR_SCALAR stage
1471 _PUBLIC_
enum ndr_err_code
ndr_push_setup_relative_base_offset1(struct ndr_push
*ndr
, const void *p
, uint32_t offset
)
1473 ndr
->relative_base_offset
= offset
;
1474 return ndr_token_store(ndr
, &ndr
->relative_base_list
, p
, offset
);
1478 setup the current base for relative pointers for the push
1479 called in the NDR_BUFFERS stage
1481 _PUBLIC_
enum ndr_err_code
ndr_push_setup_relative_base_offset2(struct ndr_push
*ndr
, const void *p
)
1483 return ndr_token_retrieve(&ndr
->relative_base_list
, p
, &ndr
->relative_base_offset
);
1487 push a relative object - stage1
1488 this is called during SCALARS processing
1490 _PUBLIC_
enum ndr_err_code
ndr_push_relative_ptr1(struct ndr_push
*ndr
, const void *p
)
1493 NDR_CHECK(ndr_push_uint32(ndr
, NDR_SCALARS
, 0));
1494 return NDR_ERR_SUCCESS
;
1496 NDR_CHECK(ndr_push_align(ndr
, 4));
1497 NDR_CHECK(ndr_token_store(ndr
, &ndr
->relative_list
, p
, ndr
->offset
));
1498 return ndr_push_uint32(ndr
, NDR_SCALARS
, 0xFFFFFFFF);
1502 push a short relative object - stage1
1503 this is called during SCALARS processing
1505 _PUBLIC_
enum ndr_err_code
ndr_push_short_relative_ptr1(struct ndr_push
*ndr
, const void *p
)
1508 NDR_CHECK(ndr_push_uint16(ndr
, NDR_SCALARS
, 0));
1509 return NDR_ERR_SUCCESS
;
1511 NDR_CHECK(ndr_push_align(ndr
, 2));
1512 NDR_CHECK(ndr_token_store(ndr
, &ndr
->relative_list
, p
, ndr
->offset
));
1513 return ndr_push_uint16(ndr
, NDR_SCALARS
, 0xFFFF);
1516 push a relative object - stage2
1517 this is called during buffers processing
1519 static enum ndr_err_code
ndr_push_relative_ptr2(struct ndr_push
*ndr
, const void *p
)
1521 uint32_t save_offset
;
1522 uint32_t ptr_offset
= 0xFFFFFFFF;
1524 return NDR_ERR_SUCCESS
;
1526 save_offset
= ndr
->offset
;
1527 NDR_CHECK(ndr_token_retrieve(&ndr
->relative_list
, p
, &ptr_offset
));
1528 if (ptr_offset
> ndr
->offset
) {
1529 return ndr_push_error(ndr
, NDR_ERR_BUFSIZE
,
1530 "ndr_push_relative_ptr2 ptr_offset(%u) > ndr->offset(%u)",
1531 ptr_offset
, ndr
->offset
);
1533 ndr
->offset
= ptr_offset
;
1534 if (save_offset
< ndr
->relative_base_offset
) {
1535 return ndr_push_error(ndr
, NDR_ERR_BUFSIZE
,
1536 "ndr_push_relative_ptr2 save_offset(%u) < ndr->relative_base_offset(%u)",
1537 save_offset
, ndr
->relative_base_offset
);
1539 NDR_CHECK(ndr_push_uint32(ndr
, NDR_SCALARS
, save_offset
- ndr
->relative_base_offset
));
1540 ndr
->offset
= save_offset
;
1541 return NDR_ERR_SUCCESS
;
1544 push a short relative object - stage2
1545 this is called during buffers processing
1547 _PUBLIC_
enum ndr_err_code
ndr_push_short_relative_ptr2(struct ndr_push
*ndr
, const void *p
)
1549 uint32_t save_offset
;
1550 uint32_t ptr_offset
= 0xFFFF;
1551 uint32_t relative_offset
;
1556 return NDR_ERR_SUCCESS
;
1559 if (ndr
->offset
< ndr
->relative_base_offset
) {
1560 return ndr_push_error(ndr
, NDR_ERR_BUFSIZE
,
1561 "ndr_push_relative_ptr2 ndr->offset(%u) < ndr->relative_base_offset(%u)",
1562 ndr
->offset
, ndr
->relative_base_offset
);
1565 relative_offset
= ndr
->offset
- ndr
->relative_base_offset
;
1567 if (ndr
->flags
& LIBNDR_FLAG_NOALIGN
) {
1569 } else if (ndr
->flags
& LIBNDR_FLAG_ALIGN2
) {
1571 } else if (ndr
->flags
& LIBNDR_FLAG_ALIGN4
) {
1573 } else if (ndr
->flags
& LIBNDR_FLAG_ALIGN8
) {
1577 pad
= ndr_align_size(relative_offset
, align
);
1579 NDR_CHECK(ndr_push_zero(ndr
, pad
));
1582 relative_offset
= ndr
->offset
- ndr
->relative_base_offset
;
1583 if (relative_offset
> UINT16_MAX
) {
1584 return ndr_push_error(ndr
, NDR_ERR_BUFSIZE
,
1585 "ndr_push_relative_ptr2 relative_offset(%u) > UINT16_MAX",
1589 save_offset
= ndr
->offset
;
1590 NDR_CHECK(ndr_token_retrieve(&ndr
->relative_list
, p
, &ptr_offset
));
1591 if (ptr_offset
> ndr
->offset
) {
1592 return ndr_push_error(ndr
, NDR_ERR_BUFSIZE
,
1593 "ndr_push_short_relative_ptr2 ptr_offset(%u) > ndr->offset(%u)",
1594 ptr_offset
, ndr
->offset
);
1596 ndr
->offset
= ptr_offset
;
1597 NDR_CHECK(ndr_push_uint16(ndr
, NDR_SCALARS
, relative_offset
));
1598 ndr
->offset
= save_offset
;
1599 return NDR_ERR_SUCCESS
;
1603 push a relative object - stage2 start
1604 this is called during buffers processing
1606 _PUBLIC_
enum ndr_err_code
ndr_push_relative_ptr2_start(struct ndr_push
*ndr
, const void *p
)
1609 return NDR_ERR_SUCCESS
;
1611 if (!(ndr
->flags
& LIBNDR_FLAG_RELATIVE_REVERSE
)) {
1612 uint32_t relative_offset
;
1616 if (ndr
->offset
< ndr
->relative_base_offset
) {
1617 return ndr_push_error(ndr
, NDR_ERR_BUFSIZE
,
1618 "ndr_push_relative_ptr2_start ndr->offset(%u) < ndr->relative_base_offset(%u)",
1619 ndr
->offset
, ndr
->relative_base_offset
);
1622 relative_offset
= ndr
->offset
- ndr
->relative_base_offset
;
1624 if (ndr
->flags
& LIBNDR_FLAG_NOALIGN
) {
1626 } else if (ndr
->flags
& LIBNDR_FLAG_ALIGN2
) {
1628 } else if (ndr
->flags
& LIBNDR_FLAG_ALIGN4
) {
1630 } else if (ndr
->flags
& LIBNDR_FLAG_ALIGN8
) {
1634 pad
= ndr_align_size(relative_offset
, align
);
1636 NDR_CHECK(ndr_push_zero(ndr
, pad
));
1639 return ndr_push_relative_ptr2(ndr
, p
);
1641 if (ndr
->relative_end_offset
== -1) {
1642 return ndr_push_error(ndr
, NDR_ERR_RELATIVE
,
1643 "ndr_push_relative_ptr2_start RELATIVE_REVERSE flag set and relative_end_offset %d",
1644 ndr
->relative_end_offset
);
1646 NDR_CHECK(ndr_token_store(ndr
, &ndr
->relative_begin_list
, p
, ndr
->offset
));
1647 return NDR_ERR_SUCCESS
;
1651 push a relative object - stage2 end
1652 this is called during buffers processing
1654 _PUBLIC_
enum ndr_err_code
ndr_push_relative_ptr2_end(struct ndr_push
*ndr
, const void *p
)
1656 uint32_t begin_offset
= 0xFFFFFFFF;
1658 uint32_t correct_offset
= 0;
1663 return NDR_ERR_SUCCESS
;
1666 if (!(ndr
->flags
& LIBNDR_FLAG_RELATIVE_REVERSE
)) {
1667 return NDR_ERR_SUCCESS
;
1670 if (ndr
->flags
& LIBNDR_FLAG_NO_NDR_SIZE
) {
1671 /* better say more than calculation a too small buffer */
1672 NDR_PUSH_ALIGN(ndr
, 8);
1673 return NDR_ERR_SUCCESS
;
1676 if (ndr
->relative_end_offset
< ndr
->offset
) {
1677 return ndr_push_error(ndr
, NDR_ERR_RELATIVE
,
1678 "ndr_push_relative_ptr2_end:"
1679 "relative_end_offset %u < offset %u",
1680 ndr
->relative_end_offset
, ndr
->offset
);
1683 NDR_CHECK(ndr_token_retrieve(&ndr
->relative_begin_list
, p
, &begin_offset
));
1685 /* we have marshalled a buffer, see how long it was */
1686 len
= ndr
->offset
- begin_offset
;
1689 return ndr_push_error(ndr
, NDR_ERR_RELATIVE
,
1690 "ndr_push_relative_ptr2_end:"
1691 "offset %u - begin_offset %u < 0",
1692 ndr
->offset
, begin_offset
);
1695 if (ndr
->relative_end_offset
< len
) {
1696 return ndr_push_error(ndr
, NDR_ERR_RELATIVE
,
1697 "ndr_push_relative_ptr2_end:"
1698 "relative_end_offset %u < len %lld",
1699 ndr
->offset
, (long long)len
);
1702 /* the reversed offset is at the end of the main buffer */
1703 correct_offset
= ndr
->relative_end_offset
- len
;
1705 if (ndr
->flags
& LIBNDR_FLAG_NOALIGN
) {
1707 } else if (ndr
->flags
& LIBNDR_FLAG_ALIGN2
) {
1709 } else if (ndr
->flags
& LIBNDR_FLAG_ALIGN4
) {
1711 } else if (ndr
->flags
& LIBNDR_FLAG_ALIGN8
) {
1715 pad
= ndr_align_size(correct_offset
, align
);
1717 correct_offset
+= pad
;
1718 correct_offset
-= align
;
1721 if (correct_offset
< begin_offset
) {
1722 return ndr_push_error(ndr
, NDR_ERR_RELATIVE
,
1723 "ndr_push_relative_ptr2_end: "
1724 "correct_offset %u < begin_offset %u",
1725 correct_offset
, begin_offset
);
1729 uint32_t clear_size
= correct_offset
- begin_offset
;
1731 clear_size
= MIN(clear_size
, len
);
1733 /* now move the marshalled buffer to the end of the main buffer */
1734 memmove(ndr
->data
+ correct_offset
, ndr
->data
+ begin_offset
, len
);
1737 /* and wipe out old buffer within the main buffer */
1738 memset(ndr
->data
+ begin_offset
, '\0', clear_size
);
1742 /* and set the end offset for the next buffer */
1743 ndr
->relative_end_offset
= correct_offset
;
1745 /* finally write the offset to the main buffer */
1746 ndr
->offset
= correct_offset
;
1747 NDR_CHECK(ndr_push_relative_ptr2(ndr
, p
));
1749 /* restore to where we were in the main buffer */
1750 ndr
->offset
= begin_offset
;
1752 return NDR_ERR_SUCCESS
;
1756 get the current base for relative pointers for the pull
1758 _PUBLIC_
uint32_t ndr_pull_get_relative_base_offset(struct ndr_pull
*ndr
)
1760 return ndr
->relative_base_offset
;
1764 restore the old base for relative pointers for the pull
1766 _PUBLIC_
void ndr_pull_restore_relative_base_offset(struct ndr_pull
*ndr
, uint32_t offset
)
1768 ndr
->relative_base_offset
= offset
;
1772 setup the current base for relative pointers for the pull
1773 called in the NDR_SCALAR stage
1775 _PUBLIC_
enum ndr_err_code
ndr_pull_setup_relative_base_offset1(struct ndr_pull
*ndr
, const void *p
, uint32_t offset
)
1777 ndr
->relative_base_offset
= offset
;
1778 return ndr_token_store(ndr
, &ndr
->relative_base_list
, p
, offset
);
1782 setup the current base for relative pointers for the pull
1783 called in the NDR_BUFFERS stage
1785 _PUBLIC_
enum ndr_err_code
ndr_pull_setup_relative_base_offset2(struct ndr_pull
*ndr
, const void *p
)
1787 return ndr_token_retrieve(&ndr
->relative_base_list
, p
, &ndr
->relative_base_offset
);
1791 pull a relative object - stage1
1792 called during SCALARS processing
1794 _PUBLIC_
enum ndr_err_code
ndr_pull_relative_ptr1(struct ndr_pull
*ndr
, const void *p
, uint32_t rel_offset
)
1796 rel_offset
+= ndr
->relative_base_offset
;
1797 if (rel_offset
> ndr
->data_size
) {
1798 return ndr_pull_error(ndr
, NDR_ERR_BUFSIZE
,
1799 "ndr_pull_relative_ptr1 rel_offset(%u) > ndr->data_size(%u)",
1800 rel_offset
, ndr
->data_size
);
1802 return ndr_token_store(ndr
, &ndr
->relative_list
, p
, rel_offset
);
1806 pull a relative object - stage2
1807 called during BUFFERS processing
1809 _PUBLIC_
enum ndr_err_code
ndr_pull_relative_ptr2(struct ndr_pull
*ndr
, const void *p
)
1811 uint32_t rel_offset
;
1812 NDR_CHECK(ndr_token_retrieve(&ndr
->relative_list
, p
, &rel_offset
));
1813 return ndr_pull_set_offset(ndr
, rel_offset
);
1816 const static struct {
1817 enum ndr_err_code err
;
1819 } ndr_err_code_strings
[] = {
1820 { NDR_ERR_SUCCESS
, "Success" },
1821 { NDR_ERR_ARRAY_SIZE
, "Bad Array Size" },
1822 { NDR_ERR_BAD_SWITCH
, "Bad Switch" },
1823 { NDR_ERR_OFFSET
, "Offset Error" },
1824 { NDR_ERR_RELATIVE
, "Relative Pointer Error" },
1825 { NDR_ERR_CHARCNV
, "Character Conversion Error" },
1826 { NDR_ERR_LENGTH
, "Length Error" },
1827 { NDR_ERR_SUBCONTEXT
, "Subcontext Error" },
1828 { NDR_ERR_COMPRESSION
, "Compression Error" },
1829 { NDR_ERR_STRING
, "String Error" },
1830 { NDR_ERR_VALIDATE
, "Validate Error" },
1831 { NDR_ERR_BUFSIZE
, "Buffer Size Error" },
1832 { NDR_ERR_ALLOC
, "Allocation Error" },
1833 { NDR_ERR_RANGE
, "Range Error" },
1834 { NDR_ERR_TOKEN
, "Token Error" },
1835 { NDR_ERR_IPV4ADDRESS
, "IPv4 Address Error" },
1836 { NDR_ERR_INVALID_POINTER
, "Invalid Pointer" },
1837 { NDR_ERR_UNREAD_BYTES
, "Unread Bytes" },
1838 { NDR_ERR_NDR64
, "NDR64 assertion error" },
1839 { NDR_ERR_INCOMPLETE_BUFFER
, "Incomplete Buffer" },
1843 _PUBLIC_
const char *ndr_map_error2string(enum ndr_err_code ndr_err
)
1846 for (i
= 0; ndr_err_code_strings
[i
].string
!= NULL
; i
++) {
1847 if (ndr_err_code_strings
[i
].err
== ndr_err
)
1848 return ndr_err_code_strings
[i
].string
;
1850 return "Unknown error";