param: Rename variable used for lp_addprinter_cmd szAddPrinterCommand
[Samba.git] / librpc / ndr / ndr.c
blob3ed0310a639247041ea654a0c8f957ca1885dc38
1 /*
2 Unix SMB/CIFS implementation.
4 libndr interface
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
27 of NDR encoding rules
30 #include "includes.h"
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)
66 struct ndr_pull *ndr;
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;
75 return ndr;
79 advance by 'size' bytes
81 _PUBLIC_ enum ndr_err_code ndr_pull_advance(struct ndr_pull *ndr, uint32_t size)
83 ndr->offset += size;
84 if (ndr->offset > ndr->data_size) {
85 return ndr_pull_error(ndr, NDR_ERR_BUFSIZE,
86 "ndr_pull_advance by %u failed",
87 size);
89 return NDR_ERR_SUCCESS;
93 set the parse offset to 'ofs'
95 static enum ndr_err_code ndr_pull_set_offset(struct ndr_pull *ndr, uint32_t ofs)
97 ndr->offset = ofs;
98 if (ndr->offset > ndr->data_size) {
99 return ndr_pull_error(ndr, NDR_ERR_BUFSIZE,
100 "ndr_pull_set_offset %u failed",
101 ofs);
103 return NDR_ERR_SUCCESS;
106 /* create a ndr_push structure, ready for some marshalling */
107 _PUBLIC_ struct ndr_push *ndr_push_init_ctx(TALLOC_CTX *mem_ctx)
109 struct ndr_push *ndr;
111 ndr = talloc_zero(mem_ctx, struct ndr_push);
112 if (!ndr) {
113 return NULL;
116 ndr->flags = 0;
117 ndr->alloc_size = NDR_BASE_MARSHALL_SIZE;
118 ndr->data = talloc_array(ndr, uint8_t, ndr->alloc_size);
119 if (!ndr->data) {
120 talloc_free(ndr);
121 return NULL;
124 return ndr;
127 /* return a DATA_BLOB structure for the current ndr_push marshalled data */
128 _PUBLIC_ DATA_BLOB ndr_push_blob(struct ndr_push *ndr)
130 DATA_BLOB blob;
131 blob = data_blob_const(ndr->data, ndr->offset);
132 if (ndr->alloc_size > ndr->offset) {
133 ndr->data[ndr->offset] = 0;
135 return blob;
140 expand the available space in the buffer to ndr->offset + extra_size
142 _PUBLIC_ enum ndr_err_code ndr_push_expand(struct ndr_push *ndr, uint32_t extra_size)
144 uint32_t size = extra_size + ndr->offset;
146 if (size < ndr->offset) {
147 /* extra_size overflowed the offset */
148 return ndr_push_error(ndr, NDR_ERR_BUFSIZE, "Overflow in push_expand to %u",
149 size);
152 if (ndr->alloc_size > size) {
153 return NDR_ERR_SUCCESS;
156 ndr->alloc_size += NDR_BASE_MARSHALL_SIZE;
157 if (size+1 > ndr->alloc_size) {
158 ndr->alloc_size = size+1;
160 ndr->data = talloc_realloc(ndr, ndr->data, uint8_t, ndr->alloc_size);
161 if (!ndr->data) {
162 return ndr_push_error(ndr, NDR_ERR_ALLOC, "Failed to push_expand to %u",
163 ndr->alloc_size);
166 return NDR_ERR_SUCCESS;
169 _PUBLIC_ void ndr_print_debugc_helper(struct ndr_print *ndr, const char *format, ...)
171 va_list ap;
172 char *s = NULL;
173 uint32_t i;
174 int ret;
175 int dbgc_class;
177 va_start(ap, format);
178 ret = vasprintf(&s, format, ap);
179 va_end(ap);
181 if (ret == -1) {
182 return;
185 dbgc_class = *(int *)ndr->private_data;
187 if (ndr->no_newline) {
188 DEBUGADDC(dbgc_class, 1,("%s", s));
189 free(s);
190 return;
193 for (i=0;i<ndr->depth;i++) {
194 DEBUGADDC(dbgc_class, 1,(" "));
197 DEBUGADDC(dbgc_class, 1,("%s\n", s));
198 free(s);
201 _PUBLIC_ void ndr_print_debug_helper(struct ndr_print *ndr, const char *format, ...)
203 va_list ap;
204 char *s = NULL;
205 uint32_t i;
206 int ret;
208 va_start(ap, format);
209 ret = vasprintf(&s, format, ap);
210 va_end(ap);
212 if (ret == -1) {
213 return;
216 if (ndr->no_newline) {
217 DEBUGADD(1,("%s", s));
218 free(s);
219 return;
222 for (i=0;i<ndr->depth;i++) {
223 DEBUGADD(1,(" "));
226 DEBUGADD(1,("%s\n", s));
227 free(s);
230 _PUBLIC_ void ndr_print_printf_helper(struct ndr_print *ndr, const char *format, ...)
232 va_list ap;
233 uint32_t i;
235 if (!ndr->no_newline) {
236 for (i=0;i<ndr->depth;i++) {
237 printf(" ");
241 va_start(ap, format);
242 vprintf(format, ap);
243 va_end(ap);
244 if (!ndr->no_newline) {
245 printf("\n");
249 _PUBLIC_ void ndr_print_string_helper(struct ndr_print *ndr, const char *format, ...)
251 va_list ap;
252 uint32_t i;
254 if (!ndr->no_newline) {
255 for (i=0;i<ndr->depth;i++) {
256 ndr->private_data = talloc_asprintf_append_buffer(
257 (char *)ndr->private_data, " ");
261 va_start(ap, format);
262 ndr->private_data = talloc_vasprintf_append_buffer((char *)ndr->private_data,
263 format, ap);
264 va_end(ap);
265 if (!ndr->no_newline) {
266 ndr->private_data = talloc_asprintf_append_buffer((char *)ndr->private_data,
267 "\n");
272 a useful helper function for printing idl structures via DEBUGC()
274 _PUBLIC_ void ndr_print_debugc(int dbgc_class, ndr_print_fn_t fn, const char *name, void *ptr)
276 struct ndr_print *ndr;
278 DEBUGC(dbgc_class, 1,(" "));
280 ndr = talloc_zero(NULL, struct ndr_print);
281 if (!ndr) return;
282 ndr->private_data = &dbgc_class;
283 ndr->print = ndr_print_debugc_helper;
284 ndr->depth = 1;
285 ndr->flags = 0;
286 fn(ndr, name, ptr);
287 talloc_free(ndr);
291 a useful helper function for printing idl structures via DEBUG()
293 _PUBLIC_ void ndr_print_debug(ndr_print_fn_t fn, const char *name, void *ptr)
295 struct ndr_print *ndr;
297 DEBUG(1,(" "));
299 ndr = talloc_zero(NULL, struct ndr_print);
300 if (!ndr) return;
301 ndr->print = ndr_print_debug_helper;
302 ndr->depth = 1;
303 ndr->flags = 0;
304 fn(ndr, name, ptr);
305 talloc_free(ndr);
309 a useful helper function for printing idl unions via DEBUG()
311 _PUBLIC_ void ndr_print_union_debug(ndr_print_fn_t fn, const char *name, uint32_t level, void *ptr)
313 struct ndr_print *ndr;
315 DEBUG(1,(" "));
317 ndr = talloc_zero(NULL, struct ndr_print);
318 if (!ndr) return;
319 ndr->print = ndr_print_debug_helper;
320 ndr->depth = 1;
321 ndr->flags = 0;
322 ndr_print_set_switch_value(ndr, ptr, level);
323 fn(ndr, name, ptr);
324 talloc_free(ndr);
328 a useful helper function for printing idl function calls via DEBUG()
330 _PUBLIC_ void ndr_print_function_debug(ndr_print_function_t fn, const char *name, int flags, void *ptr)
332 struct ndr_print *ndr;
334 DEBUG(1,(" "));
336 ndr = talloc_zero(NULL, struct ndr_print);
337 if (!ndr) return;
338 ndr->print = ndr_print_debug_helper;
339 ndr->depth = 1;
340 ndr->flags = 0;
342 fn(ndr, name, flags, ptr);
343 talloc_free(ndr);
347 a useful helper function for printing idl structures to a string
349 _PUBLIC_ char *ndr_print_struct_string(TALLOC_CTX *mem_ctx, ndr_print_fn_t fn, const char *name, void *ptr)
351 struct ndr_print *ndr;
352 char *ret = NULL;
354 ndr = talloc_zero(mem_ctx, struct ndr_print);
355 if (!ndr) return NULL;
356 ndr->private_data = talloc_strdup(ndr, "");
357 if (!ndr->private_data) {
358 goto failed;
360 ndr->print = ndr_print_string_helper;
361 ndr->depth = 1;
362 ndr->flags = 0;
364 fn(ndr, name, ptr);
365 ret = talloc_steal(mem_ctx, (char *)ndr->private_data);
366 failed:
367 talloc_free(ndr);
368 return ret;
372 a useful helper function for printing idl unions to a string
374 _PUBLIC_ char *ndr_print_union_string(TALLOC_CTX *mem_ctx, ndr_print_fn_t fn, const char *name, uint32_t level, void *ptr)
376 struct ndr_print *ndr;
377 char *ret = NULL;
379 ndr = talloc_zero(mem_ctx, struct ndr_print);
380 if (!ndr) return NULL;
381 ndr->private_data = talloc_strdup(ndr, "");
382 if (!ndr->private_data) {
383 goto failed;
385 ndr->print = ndr_print_string_helper;
386 ndr->depth = 1;
387 ndr->flags = 0;
388 ndr_print_set_switch_value(ndr, ptr, level);
389 fn(ndr, name, ptr);
390 ret = talloc_steal(mem_ctx, (char *)ndr->private_data);
391 failed:
392 talloc_free(ndr);
393 return ret;
397 a useful helper function for printing idl function calls to a string
399 _PUBLIC_ char *ndr_print_function_string(TALLOC_CTX *mem_ctx,
400 ndr_print_function_t fn, const char *name,
401 int flags, void *ptr)
403 struct ndr_print *ndr;
404 char *ret = NULL;
406 ndr = talloc_zero(mem_ctx, struct ndr_print);
407 if (!ndr) return NULL;
408 ndr->private_data = talloc_strdup(ndr, "");
409 if (!ndr->private_data) {
410 goto failed;
412 ndr->print = ndr_print_string_helper;
413 ndr->depth = 1;
414 ndr->flags = 0;
415 fn(ndr, name, flags, ptr);
416 ret = talloc_steal(mem_ctx, (char *)ndr->private_data);
417 failed:
418 talloc_free(ndr);
419 return ret;
422 _PUBLIC_ void ndr_set_flags(uint32_t *pflags, uint32_t new_flags)
424 /* the big/little endian flags are inter-dependent */
425 if (new_flags & LIBNDR_FLAG_LITTLE_ENDIAN) {
426 (*pflags) &= ~LIBNDR_FLAG_BIGENDIAN;
427 (*pflags) &= ~LIBNDR_FLAG_NDR64;
429 if (new_flags & LIBNDR_FLAG_BIGENDIAN) {
430 (*pflags) &= ~LIBNDR_FLAG_LITTLE_ENDIAN;
431 (*pflags) &= ~LIBNDR_FLAG_NDR64;
433 if (new_flags & LIBNDR_ALIGN_FLAGS) {
434 /* Ensure we only have the passed-in
435 align flag set in the new_flags,
436 remove any old align flag. */
437 (*pflags) &= ~LIBNDR_ALIGN_FLAGS;
439 if (new_flags & LIBNDR_FLAG_NO_RELATIVE_REVERSE) {
440 (*pflags) &= ~LIBNDR_FLAG_RELATIVE_REVERSE;
442 (*pflags) |= new_flags;
446 return and possibly log an NDR error
448 _PUBLIC_ enum ndr_err_code ndr_pull_error(struct ndr_pull *ndr,
449 enum ndr_err_code ndr_err,
450 const char *format, ...)
452 char *s=NULL;
453 va_list ap;
454 int ret;
456 va_start(ap, format);
457 ret = vasprintf(&s, format, ap);
458 va_end(ap);
460 if (ret == -1) {
461 return NDR_ERR_ALLOC;
464 DEBUG(1,("ndr_pull_error(%u): %s\n", ndr_err, s));
466 free(s);
468 return ndr_err;
472 return and possibly log an NDR error
474 _PUBLIC_ enum ndr_err_code ndr_push_error(struct ndr_push *ndr,
475 enum ndr_err_code ndr_err,
476 const char *format, ...)
478 char *s=NULL;
479 va_list ap;
480 int ret;
482 va_start(ap, format);
483 ret = vasprintf(&s, format, ap);
484 va_end(ap);
486 if (ret == -1) {
487 return NDR_ERR_ALLOC;
490 DEBUG(1,("ndr_push_error(%u): %s\n", ndr_err, s));
492 free(s);
494 return ndr_err;
498 handle subcontext buffers, which in midl land are user-marshalled, but
499 we use magic in pidl to make them easier to cope with
501 _PUBLIC_ enum ndr_err_code ndr_pull_subcontext_start(struct ndr_pull *ndr,
502 struct ndr_pull **_subndr,
503 size_t header_size,
504 ssize_t size_is)
506 struct ndr_pull *subndr;
507 uint32_t r_content_size;
508 bool force_le = false;
509 bool force_be = false;
511 switch (header_size) {
512 case 0: {
513 uint32_t content_size = ndr->data_size - ndr->offset;
514 if (size_is >= 0) {
515 content_size = size_is;
517 r_content_size = content_size;
518 break;
521 case 2: {
522 uint16_t content_size;
523 NDR_CHECK(ndr_pull_uint16(ndr, NDR_SCALARS, &content_size));
524 if (size_is >= 0 && size_is != content_size) {
525 return ndr_pull_error(ndr, NDR_ERR_SUBCONTEXT, "Bad subcontext (PULL) size_is(%d) mismatch content_size %d",
526 (int)size_is, (int)content_size);
528 r_content_size = content_size;
529 break;
532 case 4: {
533 uint32_t content_size;
534 NDR_CHECK(ndr_pull_uint3264(ndr, NDR_SCALARS, &content_size));
535 if (size_is >= 0 && size_is != content_size) {
536 return ndr_pull_error(ndr, NDR_ERR_SUBCONTEXT, "Bad subcontext (PULL) size_is(%d) mismatch content_size %d",
537 (int)size_is, (int)content_size);
539 r_content_size = content_size;
540 break;
542 case 0xFFFFFC01: {
544 * Common Type Header for the Serialization Stream
545 * See [MS-RPCE] 2.2.6 Type Serialization Version 1
547 uint8_t version;
548 uint8_t drep;
549 uint16_t hdrlen;
550 uint32_t filler;
551 uint32_t content_size;
552 uint32_t reserved;
554 /* version */
555 NDR_CHECK(ndr_pull_uint8(ndr, NDR_SCALARS, &version));
557 if (version != 1) {
558 return ndr_pull_error(ndr, NDR_ERR_SUBCONTEXT,
559 "Bad subcontext (PULL) Common Type Header version %d != 1",
560 (int)version);
564 * 0x10 little endian
565 * 0x00 big endian
567 NDR_CHECK(ndr_pull_uint8(ndr, NDR_SCALARS, &drep));
568 if (drep == 0x10) {
569 force_le = true;
570 } else if (drep == 0x00) {
571 force_be = true;
572 } else {
573 return ndr_pull_error(ndr, NDR_ERR_SUBCONTEXT,
574 "Bad subcontext (PULL) Common Type Header invalid drep 0x%02X",
575 (unsigned int)drep);
578 /* length of the "Private Header for Constructed Type" */
579 NDR_CHECK(ndr_pull_uint16(ndr, NDR_SCALARS, &hdrlen));
580 if (hdrlen != 8) {
581 return ndr_pull_error(ndr, NDR_ERR_SUBCONTEXT,
582 "Bad subcontext (PULL) Common Type Header length %d != 8",
583 (int)hdrlen);
586 /* filler should be ignored */
587 NDR_CHECK(ndr_pull_uint32(ndr, NDR_SCALARS, &filler));
590 * Private Header for Constructed Type
592 /* length - will be updated latter */
593 NDR_CHECK(ndr_pull_uint32(ndr, NDR_SCALARS, &content_size));
594 if (size_is >= 0 && size_is != content_size) {
595 return ndr_pull_error(ndr, NDR_ERR_SUBCONTEXT, "Bad subcontext (PULL) size_is(%d) mismatch content_size %d",
596 (int)size_is, (int)content_size);
598 /* the content size must be a multiple of 8 */
599 if ((content_size % 8) != 0) {
600 return ndr_pull_error(ndr, NDR_ERR_SUBCONTEXT,
601 "Bad subcontext (PULL) size_is(%d) not padded to 8 content_size %d",
602 (int)size_is, (int)content_size);
604 r_content_size = content_size;
606 /* reserved */
607 NDR_CHECK(ndr_pull_uint32(ndr, NDR_SCALARS, &reserved));
608 break;
610 default:
611 return ndr_pull_error(ndr, NDR_ERR_SUBCONTEXT, "Bad subcontext (PULL) header_size %d",
612 (int)header_size);
615 NDR_PULL_NEED_BYTES(ndr, r_content_size);
617 subndr = talloc_zero(ndr, struct ndr_pull);
618 NDR_ERR_HAVE_NO_MEMORY(subndr);
619 subndr->flags = ndr->flags & ~LIBNDR_FLAG_NDR64;
620 subndr->current_mem_ctx = ndr->current_mem_ctx;
622 subndr->data = ndr->data + ndr->offset;
623 subndr->offset = 0;
624 subndr->data_size = r_content_size;
626 if (force_le) {
627 ndr_set_flags(&ndr->flags, LIBNDR_FLAG_LITTLE_ENDIAN);
628 } else if (force_be) {
629 ndr_set_flags(&ndr->flags, LIBNDR_FLAG_BIGENDIAN);
632 *_subndr = subndr;
633 return NDR_ERR_SUCCESS;
636 _PUBLIC_ enum ndr_err_code ndr_pull_subcontext_end(struct ndr_pull *ndr,
637 struct ndr_pull *subndr,
638 size_t header_size,
639 ssize_t size_is)
641 uint32_t advance;
642 uint32_t highest_ofs;
644 if (size_is >= 0) {
645 advance = size_is;
646 } else if (header_size > 0) {
647 advance = subndr->data_size;
648 } else {
649 advance = subndr->offset;
652 if (subndr->offset > ndr->relative_highest_offset) {
653 highest_ofs = subndr->offset;
654 } else {
655 highest_ofs = subndr->relative_highest_offset;
657 if (!(subndr->flags & LIBNDR_FLAG_SUBCONTEXT_NO_UNREAD_BYTES)) {
659 * avoid an error unless SUBCONTEXT_NO_UNREAD_BYTES is specified
661 highest_ofs = advance;
663 if (highest_ofs < advance) {
664 return ndr_pull_error(subndr, NDR_ERR_UNREAD_BYTES,
665 "not all bytes consumed ofs[%u] advance[%u]",
666 highest_ofs, advance);
669 NDR_CHECK(ndr_pull_advance(ndr, advance));
670 return NDR_ERR_SUCCESS;
673 _PUBLIC_ enum ndr_err_code ndr_push_subcontext_start(struct ndr_push *ndr,
674 struct ndr_push **_subndr,
675 size_t header_size,
676 ssize_t size_is)
678 struct ndr_push *subndr;
680 subndr = ndr_push_init_ctx(ndr);
681 NDR_ERR_HAVE_NO_MEMORY(subndr);
682 subndr->flags = ndr->flags & ~LIBNDR_FLAG_NDR64;
684 if (size_is > 0) {
685 NDR_CHECK(ndr_push_zero(subndr, size_is));
686 subndr->offset = 0;
687 subndr->relative_end_offset = size_is;
690 *_subndr = subndr;
691 return NDR_ERR_SUCCESS;
695 push a subcontext header
697 _PUBLIC_ enum ndr_err_code ndr_push_subcontext_end(struct ndr_push *ndr,
698 struct ndr_push *subndr,
699 size_t header_size,
700 ssize_t size_is)
702 ssize_t padding_len;
704 if (size_is >= 0) {
705 padding_len = size_is - subndr->offset;
706 if (padding_len < 0) {
707 return ndr_push_error(ndr, NDR_ERR_SUBCONTEXT, "Bad subcontext (PUSH) content_size %d is larger than size_is(%d)",
708 (int)subndr->offset, (int)size_is);
710 subndr->offset = size_is;
713 switch (header_size) {
714 case 0:
715 break;
717 case 2:
718 NDR_CHECK(ndr_push_uint16(ndr, NDR_SCALARS, subndr->offset));
719 break;
721 case 4:
722 NDR_CHECK(ndr_push_uint3264(ndr, NDR_SCALARS, subndr->offset));
723 break;
725 case 0xFFFFFC01:
727 * Common Type Header for the Serialization Stream
728 * See [MS-RPCE] 2.2.6 Type Serialization Version 1
730 padding_len = NDR_ROUND(subndr->offset, 8) - subndr->offset;
731 if (padding_len > 0) {
732 NDR_CHECK(ndr_push_zero(subndr, padding_len));
735 /* version */
736 NDR_CHECK(ndr_push_uint8(ndr, NDR_SCALARS, 1));
739 * 0x10 little endian
740 * 0x00 big endian
742 NDR_CHECK(ndr_push_uint8(ndr, NDR_SCALARS, NDR_BE(ndr)?0x00:0x10));
744 /* length of the "Private Header for Constructed Type" */
745 NDR_CHECK(ndr_push_uint16(ndr, NDR_SCALARS, 8));
747 /* filler */
748 NDR_CHECK(ndr_push_uint32(ndr, NDR_SCALARS, 0xCCCCCCCC));
751 * Private Header for Constructed Type
753 /* length - will be updated latter */
754 NDR_CHECK(ndr_push_uint32(ndr, NDR_SCALARS, subndr->offset));
756 /* reserved */
757 NDR_CHECK(ndr_push_uint32(ndr, NDR_SCALARS, 0));
758 break;
760 default:
761 return ndr_push_error(ndr, NDR_ERR_SUBCONTEXT, "Bad subcontext header size %d",
762 (int)header_size);
765 NDR_CHECK(ndr_push_bytes(ndr, subndr->data, subndr->offset));
766 return NDR_ERR_SUCCESS;
770 store a token in the ndr context, for later retrieval
772 _PUBLIC_ enum ndr_err_code ndr_token_store(TALLOC_CTX *mem_ctx,
773 struct ndr_token_list **list,
774 const void *key,
775 uint32_t value)
777 struct ndr_token_list *tok;
778 tok = talloc(mem_ctx, struct ndr_token_list);
779 NDR_ERR_HAVE_NO_MEMORY(tok);
780 tok->key = key;
781 tok->value = value;
782 DLIST_ADD((*list), tok);
783 return NDR_ERR_SUCCESS;
787 retrieve a token from a ndr context, using cmp_fn to match the tokens
789 _PUBLIC_ enum ndr_err_code ndr_token_retrieve_cmp_fn(struct ndr_token_list **list, const void *key, uint32_t *v,
790 comparison_fn_t _cmp_fn, bool _remove_tok)
792 struct ndr_token_list *tok;
793 for (tok=*list;tok;tok=tok->next) {
794 if (_cmp_fn && _cmp_fn(tok->key,key)==0) goto found;
795 else if (!_cmp_fn && tok->key == key) goto found;
797 return NDR_ERR_TOKEN;
798 found:
799 *v = tok->value;
800 if (_remove_tok) {
801 DLIST_REMOVE((*list), tok);
802 talloc_free(tok);
804 return NDR_ERR_SUCCESS;
808 retrieve a token from a ndr context
810 _PUBLIC_ enum ndr_err_code ndr_token_retrieve(struct ndr_token_list **list, const void *key, uint32_t *v)
812 return ndr_token_retrieve_cmp_fn(list, key, v, NULL, true);
816 peek at but don't removed a token from a ndr context
818 _PUBLIC_ uint32_t ndr_token_peek(struct ndr_token_list **list, const void *key)
820 enum ndr_err_code status;
821 uint32_t v;
823 status = ndr_token_retrieve_cmp_fn(list, key, &v, NULL, false);
824 if (!NDR_ERR_CODE_IS_SUCCESS(status)) {
825 return 0;
828 return v;
832 pull an array size field and add it to the array_size_list token list
834 _PUBLIC_ enum ndr_err_code ndr_pull_array_size(struct ndr_pull *ndr, const void *p)
836 uint32_t size;
837 NDR_CHECK(ndr_pull_uint3264(ndr, NDR_SCALARS, &size));
838 return ndr_token_store(ndr, &ndr->array_size_list, p, size);
842 get the stored array size field
844 _PUBLIC_ uint32_t ndr_get_array_size(struct ndr_pull *ndr, const void *p)
846 return ndr_token_peek(&ndr->array_size_list, p);
850 check the stored array size field
852 _PUBLIC_ enum ndr_err_code ndr_check_array_size(struct ndr_pull *ndr, void *p, uint32_t size)
854 uint32_t stored;
855 stored = ndr_token_peek(&ndr->array_size_list, p);
856 if (stored != size) {
857 return ndr_pull_error(ndr, NDR_ERR_ARRAY_SIZE,
858 "Bad array size - got %u expected %u\n",
859 stored, size);
861 return NDR_ERR_SUCCESS;
865 pull an array length field and add it to the array_length_list token list
867 _PUBLIC_ enum ndr_err_code ndr_pull_array_length(struct ndr_pull *ndr, const void *p)
869 uint32_t length, offset;
870 NDR_CHECK(ndr_pull_uint3264(ndr, NDR_SCALARS, &offset));
871 if (offset != 0) {
872 return ndr_pull_error(ndr, NDR_ERR_ARRAY_SIZE,
873 "non-zero array offset %u\n", offset);
875 NDR_CHECK(ndr_pull_uint3264(ndr, NDR_SCALARS, &length));
876 return ndr_token_store(ndr, &ndr->array_length_list, p, length);
880 get the stored array length field
882 _PUBLIC_ uint32_t ndr_get_array_length(struct ndr_pull *ndr, const void *p)
884 return ndr_token_peek(&ndr->array_length_list, p);
888 check the stored array length field
890 _PUBLIC_ enum ndr_err_code ndr_check_array_length(struct ndr_pull *ndr, void *p, uint32_t length)
892 uint32_t stored;
893 stored = ndr_token_peek(&ndr->array_length_list, p);
894 if (stored != length) {
895 return ndr_pull_error(ndr, NDR_ERR_ARRAY_SIZE,
896 "Bad array length - got %u expected %u\n",
897 stored, length);
899 return NDR_ERR_SUCCESS;
902 _PUBLIC_ enum ndr_err_code ndr_push_pipe_chunk_trailer(struct ndr_push *ndr, int ndr_flags, uint32_t count)
904 if (ndr->flags & LIBNDR_FLAG_NDR64) {
905 int64_t tmp = 0 - (int64_t)count;
906 uint64_t ncount = tmp;
908 NDR_CHECK(ndr_push_hyper(ndr, ndr_flags, ncount));
911 return NDR_ERR_SUCCESS;
914 _PUBLIC_ enum ndr_err_code ndr_check_pipe_chunk_trailer(struct ndr_pull *ndr, int ndr_flags, uint32_t count)
916 if (ndr->flags & LIBNDR_FLAG_NDR64) {
917 int64_t tmp = 0 - (int64_t)count;
918 uint64_t ncount1 = tmp;
919 uint64_t ncount2;
921 NDR_CHECK(ndr_pull_hyper(ndr, ndr_flags, &ncount2));
922 if (ncount1 == ncount2) {
923 return NDR_ERR_SUCCESS;
926 return ndr_pull_error(ndr, NDR_ERR_ARRAY_SIZE,
927 "Bad pipe trailer[%lld should be %lld] size was %lu\"",
928 (unsigned long long)ncount2,
929 (unsigned long long)ncount1,
930 (unsigned long)count);
933 return NDR_ERR_SUCCESS;
937 store a switch value
939 _PUBLIC_ enum ndr_err_code ndr_push_set_switch_value(struct ndr_push *ndr, const void *p, uint32_t val)
941 return ndr_token_store(ndr, &ndr->switch_list, p, val);
944 _PUBLIC_ enum ndr_err_code ndr_pull_set_switch_value(struct ndr_pull *ndr, const void *p, uint32_t val)
946 return ndr_token_store(ndr, &ndr->switch_list, p, val);
949 _PUBLIC_ enum ndr_err_code ndr_print_set_switch_value(struct ndr_print *ndr, const void *p, uint32_t val)
951 return ndr_token_store(ndr, &ndr->switch_list, p, val);
955 retrieve a switch value
957 _PUBLIC_ uint32_t ndr_push_get_switch_value(struct ndr_push *ndr, const void *p)
959 return ndr_token_peek(&ndr->switch_list, p);
962 _PUBLIC_ uint32_t ndr_pull_get_switch_value(struct ndr_pull *ndr, const void *p)
964 return ndr_token_peek(&ndr->switch_list, p);
967 _PUBLIC_ uint32_t ndr_print_get_switch_value(struct ndr_print *ndr, const void *p)
969 return ndr_token_peek(&ndr->switch_list, p);
973 pull a struct from a blob using NDR
975 _PUBLIC_ enum ndr_err_code ndr_pull_struct_blob(const DATA_BLOB *blob, TALLOC_CTX *mem_ctx, void *p,
976 ndr_pull_flags_fn_t fn)
978 struct ndr_pull *ndr;
979 ndr = ndr_pull_init_blob(blob, mem_ctx);
980 NDR_ERR_HAVE_NO_MEMORY(ndr);
981 NDR_CHECK_FREE(fn(ndr, NDR_SCALARS|NDR_BUFFERS, p));
982 talloc_free(ndr);
983 return NDR_ERR_SUCCESS;
987 pull a struct from a blob using NDR - failing if all bytes are not consumed
989 _PUBLIC_ enum ndr_err_code ndr_pull_struct_blob_all(const DATA_BLOB *blob, TALLOC_CTX *mem_ctx,
990 void *p, ndr_pull_flags_fn_t fn)
992 struct ndr_pull *ndr;
993 uint32_t highest_ofs;
994 ndr = ndr_pull_init_blob(blob, mem_ctx);
995 NDR_ERR_HAVE_NO_MEMORY(ndr);
996 NDR_CHECK_FREE(fn(ndr, NDR_SCALARS|NDR_BUFFERS, p));
997 if (ndr->offset > ndr->relative_highest_offset) {
998 highest_ofs = ndr->offset;
999 } else {
1000 highest_ofs = ndr->relative_highest_offset;
1002 if (highest_ofs < ndr->data_size) {
1003 enum ndr_err_code ret;
1004 ret = ndr_pull_error(ndr, NDR_ERR_UNREAD_BYTES,
1005 "not all bytes consumed ofs[%u] size[%u]",
1006 highest_ofs, ndr->data_size);
1007 talloc_free(ndr);
1008 return ret;
1010 talloc_free(ndr);
1011 return NDR_ERR_SUCCESS;
1015 pull a union from a blob using NDR, given the union discriminator
1017 _PUBLIC_ enum ndr_err_code ndr_pull_union_blob(const DATA_BLOB *blob, TALLOC_CTX *mem_ctx,
1018 void *p,
1019 uint32_t level, ndr_pull_flags_fn_t fn)
1021 struct ndr_pull *ndr;
1022 ndr = ndr_pull_init_blob(blob, mem_ctx);
1023 NDR_ERR_HAVE_NO_MEMORY(ndr);
1024 NDR_CHECK_FREE(ndr_pull_set_switch_value(ndr, p, level));
1025 NDR_CHECK_FREE(fn(ndr, NDR_SCALARS|NDR_BUFFERS, p));
1026 talloc_free(ndr);
1027 return NDR_ERR_SUCCESS;
1031 pull a union from a blob using NDR, given the union discriminator,
1032 failing if all bytes are not consumed
1034 _PUBLIC_ enum ndr_err_code ndr_pull_union_blob_all(const DATA_BLOB *blob, TALLOC_CTX *mem_ctx,
1035 void *p,
1036 uint32_t level, ndr_pull_flags_fn_t fn)
1038 struct ndr_pull *ndr;
1039 uint32_t highest_ofs;
1040 ndr = ndr_pull_init_blob(blob, mem_ctx);
1041 NDR_ERR_HAVE_NO_MEMORY(ndr);
1042 NDR_CHECK_FREE(ndr_pull_set_switch_value(ndr, p, level));
1043 NDR_CHECK_FREE(fn(ndr, NDR_SCALARS|NDR_BUFFERS, p));
1044 if (ndr->offset > ndr->relative_highest_offset) {
1045 highest_ofs = ndr->offset;
1046 } else {
1047 highest_ofs = ndr->relative_highest_offset;
1049 if (highest_ofs < ndr->data_size) {
1050 enum ndr_err_code ret;
1051 ret = ndr_pull_error(ndr, NDR_ERR_UNREAD_BYTES,
1052 "not all bytes consumed ofs[%u] size[%u]",
1053 highest_ofs, ndr->data_size);
1054 talloc_free(ndr);
1055 return ret;
1057 talloc_free(ndr);
1058 return NDR_ERR_SUCCESS;
1062 push a struct to a blob using NDR
1064 _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)
1066 struct ndr_push *ndr;
1067 ndr = ndr_push_init_ctx(mem_ctx);
1068 NDR_ERR_HAVE_NO_MEMORY(ndr);
1070 NDR_CHECK(fn(ndr, NDR_SCALARS|NDR_BUFFERS, p));
1072 *blob = ndr_push_blob(ndr);
1073 talloc_steal(mem_ctx, blob->data);
1074 talloc_free(ndr);
1076 return NDR_ERR_SUCCESS;
1080 push a union to a blob using NDR
1082 _PUBLIC_ enum ndr_err_code ndr_push_union_blob(DATA_BLOB *blob, TALLOC_CTX *mem_ctx, void *p,
1083 uint32_t level, ndr_push_flags_fn_t fn)
1085 struct ndr_push *ndr;
1086 ndr = ndr_push_init_ctx(mem_ctx);
1087 NDR_ERR_HAVE_NO_MEMORY(ndr);
1089 NDR_CHECK(ndr_push_set_switch_value(ndr, p, level));
1090 NDR_CHECK(fn(ndr, NDR_SCALARS|NDR_BUFFERS, p));
1092 *blob = ndr_push_blob(ndr);
1093 talloc_steal(mem_ctx, blob->data);
1094 talloc_free(ndr);
1096 return NDR_ERR_SUCCESS;
1100 generic ndr_size_*() handler for structures
1102 _PUBLIC_ size_t ndr_size_struct(const void *p, int flags, ndr_push_flags_fn_t push)
1104 struct ndr_push *ndr;
1105 enum ndr_err_code status;
1106 size_t ret;
1108 /* avoid recursion */
1109 if (flags & LIBNDR_FLAG_NO_NDR_SIZE) return 0;
1111 ndr = ndr_push_init_ctx(NULL);
1112 if (!ndr) return 0;
1113 ndr->flags |= flags | LIBNDR_FLAG_NO_NDR_SIZE;
1114 status = push(ndr, NDR_SCALARS|NDR_BUFFERS, discard_const(p));
1115 if (!NDR_ERR_CODE_IS_SUCCESS(status)) {
1116 talloc_free(ndr);
1117 return 0;
1119 ret = ndr->offset;
1120 talloc_free(ndr);
1121 return ret;
1125 generic ndr_size_*() handler for unions
1127 _PUBLIC_ size_t ndr_size_union(const void *p, int flags, uint32_t level, ndr_push_flags_fn_t push)
1129 struct ndr_push *ndr;
1130 enum ndr_err_code status;
1131 size_t ret;
1133 /* avoid recursion */
1134 if (flags & LIBNDR_FLAG_NO_NDR_SIZE) return 0;
1136 ndr = ndr_push_init_ctx(NULL);
1137 if (!ndr) return 0;
1138 ndr->flags |= flags | LIBNDR_FLAG_NO_NDR_SIZE;
1140 status = ndr_push_set_switch_value(ndr, p, level);
1141 if (!NDR_ERR_CODE_IS_SUCCESS(status)) {
1142 talloc_free(ndr);
1143 return 0;
1145 status = push(ndr, NDR_SCALARS|NDR_BUFFERS, p);
1146 if (!NDR_ERR_CODE_IS_SUCCESS(status)) {
1147 talloc_free(ndr);
1148 return 0;
1150 ret = ndr->offset;
1151 talloc_free(ndr);
1152 return ret;
1156 get the current base for relative pointers for the push
1158 _PUBLIC_ uint32_t ndr_push_get_relative_base_offset(struct ndr_push *ndr)
1160 return ndr->relative_base_offset;
1164 restore the old base for relative pointers for the push
1166 _PUBLIC_ void ndr_push_restore_relative_base_offset(struct ndr_push *ndr, uint32_t offset)
1168 ndr->relative_base_offset = offset;
1172 setup the current base for relative pointers for the push
1173 called in the NDR_SCALAR stage
1175 _PUBLIC_ enum ndr_err_code ndr_push_setup_relative_base_offset1(struct ndr_push *ndr, const void *p, uint32_t offset)
1177 ndr->relative_base_offset = offset;
1178 return ndr_token_store(ndr, &ndr->relative_base_list, p, offset);
1182 setup the current base for relative pointers for the push
1183 called in the NDR_BUFFERS stage
1185 _PUBLIC_ enum ndr_err_code ndr_push_setup_relative_base_offset2(struct ndr_push *ndr, const void *p)
1187 return ndr_token_retrieve(&ndr->relative_base_list, p, &ndr->relative_base_offset);
1191 push a relative object - stage1
1192 this is called during SCALARS processing
1194 _PUBLIC_ enum ndr_err_code ndr_push_relative_ptr1(struct ndr_push *ndr, const void *p)
1196 if (p == NULL) {
1197 NDR_CHECK(ndr_push_uint32(ndr, NDR_SCALARS, 0));
1198 return NDR_ERR_SUCCESS;
1200 NDR_CHECK(ndr_push_align(ndr, 4));
1201 NDR_CHECK(ndr_token_store(ndr, &ndr->relative_list, p, ndr->offset));
1202 return ndr_push_uint32(ndr, NDR_SCALARS, 0xFFFFFFFF);
1206 push a short relative object - stage1
1207 this is called during SCALARS processing
1209 _PUBLIC_ enum ndr_err_code ndr_push_short_relative_ptr1(struct ndr_push *ndr, const void *p)
1211 if (p == NULL) {
1212 NDR_CHECK(ndr_push_uint16(ndr, NDR_SCALARS, 0));
1213 return NDR_ERR_SUCCESS;
1215 NDR_CHECK(ndr_push_align(ndr, 2));
1216 NDR_CHECK(ndr_token_store(ndr, &ndr->relative_list, p, ndr->offset));
1217 return ndr_push_uint16(ndr, NDR_SCALARS, 0xFFFF);
1220 push a relative object - stage2
1221 this is called during buffers processing
1223 static enum ndr_err_code ndr_push_relative_ptr2(struct ndr_push *ndr, const void *p)
1225 uint32_t save_offset;
1226 uint32_t ptr_offset = 0xFFFFFFFF;
1227 if (p == NULL) {
1228 return NDR_ERR_SUCCESS;
1230 save_offset = ndr->offset;
1231 NDR_CHECK(ndr_token_retrieve(&ndr->relative_list, p, &ptr_offset));
1232 if (ptr_offset > ndr->offset) {
1233 return ndr_push_error(ndr, NDR_ERR_BUFSIZE,
1234 "ndr_push_relative_ptr2 ptr_offset(%u) > ndr->offset(%u)",
1235 ptr_offset, ndr->offset);
1237 ndr->offset = ptr_offset;
1238 if (save_offset < ndr->relative_base_offset) {
1239 return ndr_push_error(ndr, NDR_ERR_BUFSIZE,
1240 "ndr_push_relative_ptr2 save_offset(%u) < ndr->relative_base_offset(%u)",
1241 save_offset, ndr->relative_base_offset);
1243 NDR_CHECK(ndr_push_uint32(ndr, NDR_SCALARS, save_offset - ndr->relative_base_offset));
1244 ndr->offset = save_offset;
1245 return NDR_ERR_SUCCESS;
1248 push a short relative object - stage2
1249 this is called during buffers processing
1251 _PUBLIC_ enum ndr_err_code ndr_push_short_relative_ptr2(struct ndr_push *ndr, const void *p)
1253 uint32_t save_offset;
1254 uint32_t ptr_offset = 0xFFFF;
1255 if (p == NULL) {
1256 return NDR_ERR_SUCCESS;
1258 save_offset = ndr->offset;
1259 NDR_CHECK(ndr_token_retrieve(&ndr->relative_list, p, &ptr_offset));
1260 if (ptr_offset > ndr->offset) {
1261 return ndr_push_error(ndr, NDR_ERR_BUFSIZE,
1262 "ndr_push_short_relative_ptr2 ptr_offset(%u) > ndr->offset(%u)",
1263 ptr_offset, ndr->offset);
1265 ndr->offset = ptr_offset;
1266 if (save_offset < ndr->relative_base_offset) {
1267 return ndr_push_error(ndr, NDR_ERR_BUFSIZE,
1268 "ndr_push_relative_ptr2 save_offset(%u) < ndr->relative_base_offset(%u)",
1269 save_offset, ndr->relative_base_offset);
1271 NDR_CHECK(ndr_push_uint16(ndr, NDR_SCALARS, save_offset - ndr->relative_base_offset));
1272 ndr->offset = save_offset;
1273 return NDR_ERR_SUCCESS;
1277 push a relative object - stage2 start
1278 this is called during buffers processing
1280 _PUBLIC_ enum ndr_err_code ndr_push_relative_ptr2_start(struct ndr_push *ndr, const void *p)
1282 if (p == NULL) {
1283 return NDR_ERR_SUCCESS;
1285 if (!(ndr->flags & LIBNDR_FLAG_RELATIVE_REVERSE)) {
1286 uint32_t relative_offset;
1287 size_t pad;
1288 size_t align = 1;
1290 if (ndr->offset < ndr->relative_base_offset) {
1291 return ndr_push_error(ndr, NDR_ERR_BUFSIZE,
1292 "ndr_push_relative_ptr2_start ndr->offset(%u) < ndr->relative_base_offset(%u)",
1293 ndr->offset, ndr->relative_base_offset);
1296 relative_offset = ndr->offset - ndr->relative_base_offset;
1298 if (ndr->flags & LIBNDR_FLAG_NOALIGN) {
1299 align = 1;
1300 } else if (ndr->flags & LIBNDR_FLAG_ALIGN2) {
1301 align = 2;
1302 } else if (ndr->flags & LIBNDR_FLAG_ALIGN4) {
1303 align = 4;
1304 } else if (ndr->flags & LIBNDR_FLAG_ALIGN8) {
1305 align = 8;
1308 pad = ndr_align_size(relative_offset, align);
1309 if (pad) {
1310 NDR_CHECK(ndr_push_zero(ndr, pad));
1313 return ndr_push_relative_ptr2(ndr, p);
1315 if (ndr->relative_end_offset == -1) {
1316 return ndr_push_error(ndr, NDR_ERR_RELATIVE,
1317 "ndr_push_relative_ptr2_start RELATIVE_REVERSE flag set and relative_end_offset %d",
1318 ndr->relative_end_offset);
1320 NDR_CHECK(ndr_token_store(ndr, &ndr->relative_begin_list, p, ndr->offset));
1321 return NDR_ERR_SUCCESS;
1325 push a relative object - stage2 end
1326 this is called during buffers processing
1328 _PUBLIC_ enum ndr_err_code ndr_push_relative_ptr2_end(struct ndr_push *ndr, const void *p)
1330 uint32_t begin_offset = 0xFFFFFFFF;
1331 ssize_t len;
1332 uint32_t correct_offset = 0;
1333 uint32_t align = 1;
1334 uint32_t pad = 0;
1336 if (p == NULL) {
1337 return NDR_ERR_SUCCESS;
1340 if (!(ndr->flags & LIBNDR_FLAG_RELATIVE_REVERSE)) {
1341 return NDR_ERR_SUCCESS;
1344 if (ndr->flags & LIBNDR_FLAG_NO_NDR_SIZE) {
1345 /* better say more than calculation a too small buffer */
1346 NDR_PUSH_ALIGN(ndr, 8);
1347 return NDR_ERR_SUCCESS;
1350 if (ndr->relative_end_offset < ndr->offset) {
1351 return ndr_push_error(ndr, NDR_ERR_RELATIVE,
1352 "ndr_push_relative_ptr2_end:"
1353 "relative_end_offset %u < offset %u",
1354 ndr->relative_end_offset, ndr->offset);
1357 NDR_CHECK(ndr_token_retrieve(&ndr->relative_begin_list, p, &begin_offset));
1359 /* we have marshalled a buffer, see how long it was */
1360 len = ndr->offset - begin_offset;
1362 if (len < 0) {
1363 return ndr_push_error(ndr, NDR_ERR_RELATIVE,
1364 "ndr_push_relative_ptr2_end:"
1365 "offset %u - begin_offset %u < 0",
1366 ndr->offset, begin_offset);
1369 if (ndr->relative_end_offset < len) {
1370 return ndr_push_error(ndr, NDR_ERR_RELATIVE,
1371 "ndr_push_relative_ptr2_end:"
1372 "relative_end_offset %u < len %lld",
1373 ndr->offset, (long long)len);
1376 /* the reversed offset is at the end of the main buffer */
1377 correct_offset = ndr->relative_end_offset - len;
1379 if (ndr->flags & LIBNDR_FLAG_NOALIGN) {
1380 align = 1;
1381 } else if (ndr->flags & LIBNDR_FLAG_ALIGN2) {
1382 align = 2;
1383 } else if (ndr->flags & LIBNDR_FLAG_ALIGN4) {
1384 align = 4;
1385 } else if (ndr->flags & LIBNDR_FLAG_ALIGN8) {
1386 align = 8;
1389 pad = ndr_align_size(correct_offset, align);
1390 if (pad) {
1391 correct_offset += pad;
1392 correct_offset -= align;
1395 if (correct_offset < begin_offset) {
1396 return ndr_push_error(ndr, NDR_ERR_RELATIVE,
1397 "ndr_push_relative_ptr2_end: "
1398 "correct_offset %u < begin_offset %u",
1399 correct_offset, begin_offset);
1402 if (len > 0) {
1403 uint32_t clear_size = correct_offset - begin_offset;
1405 clear_size = MIN(clear_size, len);
1407 /* now move the marshalled buffer to the end of the main buffer */
1408 memmove(ndr->data + correct_offset, ndr->data + begin_offset, len);
1410 if (clear_size) {
1411 /* and wipe out old buffer within the main buffer */
1412 memset(ndr->data + begin_offset, '\0', clear_size);
1416 /* and set the end offset for the next buffer */
1417 ndr->relative_end_offset = correct_offset;
1419 /* finally write the offset to the main buffer */
1420 ndr->offset = correct_offset;
1421 NDR_CHECK(ndr_push_relative_ptr2(ndr, p));
1423 /* restore to where we were in the main buffer */
1424 ndr->offset = begin_offset;
1426 return NDR_ERR_SUCCESS;
1430 get the current base for relative pointers for the pull
1432 _PUBLIC_ uint32_t ndr_pull_get_relative_base_offset(struct ndr_pull *ndr)
1434 return ndr->relative_base_offset;
1438 restore the old base for relative pointers for the pull
1440 _PUBLIC_ void ndr_pull_restore_relative_base_offset(struct ndr_pull *ndr, uint32_t offset)
1442 ndr->relative_base_offset = offset;
1446 setup the current base for relative pointers for the pull
1447 called in the NDR_SCALAR stage
1449 _PUBLIC_ enum ndr_err_code ndr_pull_setup_relative_base_offset1(struct ndr_pull *ndr, const void *p, uint32_t offset)
1451 ndr->relative_base_offset = offset;
1452 return ndr_token_store(ndr, &ndr->relative_base_list, p, offset);
1456 setup the current base for relative pointers for the pull
1457 called in the NDR_BUFFERS stage
1459 _PUBLIC_ enum ndr_err_code ndr_pull_setup_relative_base_offset2(struct ndr_pull *ndr, const void *p)
1461 return ndr_token_retrieve(&ndr->relative_base_list, p, &ndr->relative_base_offset);
1465 pull a relative object - stage1
1466 called during SCALARS processing
1468 _PUBLIC_ enum ndr_err_code ndr_pull_relative_ptr1(struct ndr_pull *ndr, const void *p, uint32_t rel_offset)
1470 rel_offset += ndr->relative_base_offset;
1471 if (rel_offset > ndr->data_size) {
1472 return ndr_pull_error(ndr, NDR_ERR_BUFSIZE,
1473 "ndr_pull_relative_ptr1 rel_offset(%u) > ndr->data_size(%u)",
1474 rel_offset, ndr->data_size);
1476 return ndr_token_store(ndr, &ndr->relative_list, p, rel_offset);
1480 pull a relative object - stage2
1481 called during BUFFERS processing
1483 _PUBLIC_ enum ndr_err_code ndr_pull_relative_ptr2(struct ndr_pull *ndr, const void *p)
1485 uint32_t rel_offset;
1486 NDR_CHECK(ndr_token_retrieve(&ndr->relative_list, p, &rel_offset));
1487 return ndr_pull_set_offset(ndr, rel_offset);
1490 const static struct {
1491 enum ndr_err_code err;
1492 const char *string;
1493 } ndr_err_code_strings[] = {
1494 { NDR_ERR_SUCCESS, "Success" },
1495 { NDR_ERR_ARRAY_SIZE, "Bad Array Size" },
1496 { NDR_ERR_BAD_SWITCH, "Bad Switch" },
1497 { NDR_ERR_OFFSET, "Offset Error" },
1498 { NDR_ERR_RELATIVE, "Relative Pointer Error" },
1499 { NDR_ERR_CHARCNV, "Character Conversion Error" },
1500 { NDR_ERR_LENGTH, "Length Error" },
1501 { NDR_ERR_SUBCONTEXT, "Subcontext Error" },
1502 { NDR_ERR_COMPRESSION, "Compression Error" },
1503 { NDR_ERR_STRING, "String Error" },
1504 { NDR_ERR_VALIDATE, "Validate Error" },
1505 { NDR_ERR_BUFSIZE, "Buffer Size Error" },
1506 { NDR_ERR_ALLOC, "Allocation Error" },
1507 { NDR_ERR_RANGE, "Range Error" },
1508 { NDR_ERR_TOKEN, "Token Error" },
1509 { NDR_ERR_IPV4ADDRESS, "IPv4 Address Error" },
1510 { NDR_ERR_INVALID_POINTER, "Invalid Pointer" },
1511 { NDR_ERR_UNREAD_BYTES, "Unread Bytes" },
1512 { NDR_ERR_NDR64, "NDR64 assertion error" },
1513 { 0, NULL }
1516 _PUBLIC_ const char *ndr_map_error2string(enum ndr_err_code ndr_err)
1518 int i;
1519 for (i = 0; ndr_err_code_strings[i].string != NULL; i++) {
1520 if (ndr_err_code_strings[i].err == ndr_err)
1521 return ndr_err_code_strings[i].string;
1523 return "Unknown error";