LCOV - code coverage report
Current view: top level - librpc/ndr - ndr.c (source / functions) Hit Total Coverage
Test: coverage report for master 2f515e9b Lines: 681 914 74.5 %
Date: 2024-04-21 15:09:00 Functions: 69 77 89.6 %

          Line data    Source code
       1             : /*
       2             :    Unix SMB/CIFS implementation.
       3             : 
       4             :    libndr interface
       5             : 
       6             :    Copyright (C) Andrew Tridgell 2003
       7             :    Copyright (C) Jelmer Vernooij 2005-2008
       8             : 
       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.
      13             : 
      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.
      18             : 
      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/>.
      21             : */
      22             : 
      23             : /*
      24             :   this provides the core routines for NDR parsing functions
      25             : 
      26             :   see http://www.opengroup.org/onlinepubs/9629399/chap14.htm for details
      27             :   of NDR encoding rules
      28             : */
      29             : 
      30             : #include "includes.h"
      31             : #include "librpc/ndr/libndr.h"
      32             : #include "librpc/ndr/ndr_private.h"
      33             : #include "../lib/util/dlinklist.h"
      34             : 
      35             : #undef DBGC_CLASS
      36             : #define DBGC_CLASS DBGC_RPC_PARSE
      37             : 
      38             : #define NDR_BASE_MARSHALL_SIZE 1024
      39             : 
      40             : /*
      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
      43             :  * malicious packet.
      44             :  *
      45             :  * In an ideal world this would be controlled by range() restrictions
      46             :  * on array sizes and careful IDL construction to avoid arbitrary
      47             :  * linked lists, but this is a backstop for now.
      48             :  */
      49             : #define NDR_TOKEN_MAX_LIST_SIZE 65535
      50             : 
      51           1 : size_t ndr_token_max_list_size(void) {
      52           1 :         return NDR_TOKEN_MAX_LIST_SIZE;
      53             : };
      54             : 
      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} },
      58             :   2
      59             : };
      60             : 
      61             : const struct ndr_syntax_id ndr_transfer_syntax_ndr64 = {
      62             :   { 0x71710533, 0xbeba, 0x4937, {0x83, 0x19}, {0xb5,0xdb,0xef,0x9c,0xcc,0x36} },
      63             :   1
      64             : };
      65             : 
      66             : const struct ndr_syntax_id ndr_syntax_id_null = {
      67             :   { 0, 0, 0, { 0, 0 }, { 0, 0, 0, 0, 0, 0 } },
      68             :   0
      69             : };
      70             : 
      71             : /*
      72             :   work out the number of bytes needed to align on a n byte boundary
      73             : */
      74    19816942 : _PUBLIC_ size_t ndr_align_size(uint32_t offset, size_t n)
      75             : {
      76    19816942 :         if ((offset & (n-1)) == 0) return 0;
      77      558749 :         return n - (offset & (n-1));
      78             : }
      79             : 
      80             : /*
      81             :   initialise a ndr parse structure from a data blob
      82             : */
      83   112400013 : _PUBLIC_ struct ndr_pull *ndr_pull_init_blob(const DATA_BLOB *blob, TALLOC_CTX *mem_ctx)
      84             : {
      85     1116962 :         struct ndr_pull *ndr;
      86             : 
      87   112400013 :         ndr = talloc_zero(mem_ctx, struct ndr_pull);
      88   112400013 :         if (!ndr) return NULL;
      89   112400013 :         ndr->current_mem_ctx = mem_ctx;
      90             : 
      91   112400013 :         ndr->data = blob->data;
      92   112400013 :         ndr->data_size = blob->length;
      93             : 
      94   112400013 :         return ndr;
      95             : }
      96             : 
      97           0 : _PUBLIC_ enum ndr_err_code ndr_pull_append(struct ndr_pull *ndr, DATA_BLOB *blob)
      98             : {
      99           0 :         enum ndr_err_code ndr_err;
     100           0 :         DATA_BLOB b;
     101           0 :         uint32_t append = 0;
     102           0 :         bool ok;
     103             : 
     104           0 :         if (blob->length == 0) {
     105           0 :                 return NDR_ERR_SUCCESS;
     106             :         }
     107             : 
     108           0 :         ndr_err = ndr_token_retrieve(&ndr->array_size_list, ndr, &append);
     109           0 :         if (ndr_err == NDR_ERR_TOKEN) {
     110           0 :                 append = 0;
     111           0 :                 ndr_err = NDR_ERR_SUCCESS;
     112             :         }
     113           0 :         NDR_CHECK(ndr_err);
     114             : 
     115           0 :         if (ndr->data_size == 0) {
     116           0 :                 ndr->data = NULL;
     117           0 :                 append = UINT32_MAX;
     118             :         }
     119             : 
     120           0 :         if (append == UINT32_MAX) {
     121             :                 /*
     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
     127             :                  */
     128           0 :                 b = data_blob_const(ndr->data, ndr->data_size);
     129             :         } else {
     130           0 :                 b = data_blob_talloc(ndr, ndr->data, ndr->data_size);
     131           0 :                 if (b.data == NULL) {
     132           0 :                         return ndr_pull_error(ndr, NDR_ERR_ALLOC, "%s", __location__);
     133             :                 }
     134             :         }
     135             : 
     136           0 :         ok = data_blob_append(ndr, &b, blob->data, blob->length);
     137           0 :         if (!ok) {
     138           0 :                 return ndr_pull_error(ndr, NDR_ERR_ALLOC, "%s", __location__);
     139             :         }
     140             : 
     141           0 :         ndr->data = b.data;
     142           0 :         ndr->data_size = b.length;
     143             : 
     144           0 :         return ndr_token_store(ndr, &ndr->array_size_list, ndr, UINT32_MAX);
     145             : }
     146             : 
     147           0 : _PUBLIC_ enum ndr_err_code ndr_pull_pop(struct ndr_pull *ndr)
     148             : {
     149           0 :         uint32_t skip = 0;
     150           0 :         uint32_t append = 0;
     151           0 :         enum ndr_err_code ndr_err;
     152             : 
     153           0 :         if (ndr->relative_base_offset != 0) {
     154           0 :                 return ndr_pull_error(ndr, NDR_ERR_RELATIVE,
     155             :                                       "%s", __location__);
     156             :         }
     157           0 :         if (ndr->relative_highest_offset != 0) {
     158           0 :                 return ndr_pull_error(ndr, NDR_ERR_RELATIVE,
     159             :                                       "%s", __location__);
     160             :         }
     161           0 :         if (ndr->relative_list.count != 0) {
     162           0 :                 return ndr_pull_error(ndr, NDR_ERR_RELATIVE,
     163             :                                       "%s", __location__);
     164             :         }
     165           0 :         if (ndr->relative_base_list.count != 0) {
     166           0 :                 return ndr_pull_error(ndr, NDR_ERR_RELATIVE,
     167             :                                       "%s", __location__);
     168             :         }
     169             : 
     170             :         /*
     171             :          * we need to keep up to 7 bytes
     172             :          * in order to get the alignment right.
     173             :          */
     174           0 :         skip = ndr->offset & 0xFFFFFFF8;
     175             : 
     176           0 :         if (skip == 0) {
     177           0 :                 return NDR_ERR_SUCCESS;
     178             :         }
     179             : 
     180           0 :         ndr->offset -= skip;
     181           0 :         ndr->data_size -= skip;
     182             : 
     183           0 :         ndr_err = ndr_token_peek(&ndr->array_size_list, ndr, &append);
     184           0 :         if (ndr_err == NDR_ERR_TOKEN) {
     185             :                 /*
     186             :                  * here we assume, that ndr->data is not a
     187             :                  * talloc child of ndr.
     188             :                  */
     189           0 :                 ndr->data += skip;
     190           0 :                 return NDR_ERR_SUCCESS;
     191             :         }
     192             : 
     193           0 :         memmove(ndr->data, ndr->data + skip, ndr->data_size);
     194             : 
     195           0 :         ndr->data = talloc_realloc(ndr, ndr->data, uint8_t, ndr->data_size);
     196           0 :         if (ndr->data_size != 0 && ndr->data == NULL) {
     197           0 :                 return ndr_pull_error(ndr, NDR_ERR_ALLOC, "%s", __location__);
     198             :         }
     199             : 
     200           0 :         return NDR_ERR_SUCCESS;
     201             : }
     202             : 
     203             : /*
     204             :   advance by 'size' bytes
     205             : */
     206   139067404 : _PUBLIC_ enum ndr_err_code ndr_pull_advance(struct ndr_pull *ndr, uint32_t size)
     207             : {
     208   139067404 :         NDR_PULL_NEED_BYTES(ndr, size);
     209   139067403 :         ndr->offset += size;
     210   139067403 :         return NDR_ERR_SUCCESS;
     211             : }
     212             : 
     213             : /*
     214             :   set the parse offset to 'ofs'
     215             : */
     216    46385510 : static enum ndr_err_code ndr_pull_set_offset(struct ndr_pull *ndr, uint32_t ofs)
     217             : {
     218    46385510 :         ndr->offset = ofs;
     219    46385510 :         if (ndr->offset > ndr->data_size) {
     220           0 :                 return ndr_pull_error(ndr, NDR_ERR_BUFSIZE,
     221             :                                       "ndr_pull_set_offset %"PRIu32" failed",
     222             :                                       ofs);
     223             :         }
     224    44422522 :         return NDR_ERR_SUCCESS;
     225             : }
     226             : 
     227             : /* create a ndr_push structure, ready for some marshalling */
     228    96072805 : _PUBLIC_ struct ndr_push *ndr_push_init_ctx(TALLOC_CTX *mem_ctx)
     229             : {
     230      596308 :         struct ndr_push *ndr;
     231             : 
     232    96072805 :         ndr = talloc_zero(mem_ctx, struct ndr_push);
     233    96072805 :         if (!ndr) {
     234           0 :                 return NULL;
     235             :         }
     236             : 
     237    96072805 :         ndr->flags = 0;
     238    96072805 :         ndr->alloc_size = NDR_BASE_MARSHALL_SIZE;
     239    96072805 :         ndr->data = talloc_array(ndr, uint8_t, ndr->alloc_size);
     240    96072805 :         if (!ndr->data) {
     241           0 :                 talloc_free(ndr);
     242           0 :                 return NULL;
     243             :         }
     244             : 
     245    95476497 :         return ndr;
     246             : }
     247             : 
     248             : /* return a DATA_BLOB structure for the current ndr_push marshalled data */
     249    85039340 : _PUBLIC_ DATA_BLOB ndr_push_blob(struct ndr_push *ndr)
     250             : {
     251      530586 :         DATA_BLOB blob;
     252    85039340 :         blob = data_blob_const(ndr->data, ndr->offset);
     253    85039340 :         if (ndr->alloc_size > ndr->offset) {
     254    85039340 :                 ndr->data[ndr->offset] = 0;
     255             :         }
     256    85039340 :         return blob;
     257             : }
     258             : 
     259             : 
     260             : /*
     261             :   expand the available space in the buffer to ndr->offset + extra_size
     262             : */
     263  5341029711 : _PUBLIC_ enum ndr_err_code ndr_push_expand(struct ndr_push *ndr, uint32_t extra_size)
     264             : {
     265  5341029711 :         uint32_t size = extra_size + ndr->offset;
     266             : 
     267  5341029711 :         if (size < ndr->offset) {
     268             :                 /* extra_size overflowed the offset */
     269           0 :                 return ndr_push_error(ndr, NDR_ERR_BUFSIZE, "Overflow in push_expand to %"PRIu32,
     270             :                                       size);
     271             :         }
     272             : 
     273  5341029711 :         if (ndr->fixed_buf_size) {
     274   805386013 :                 if (ndr->alloc_size >= size) {
     275   795998663 :                         return NDR_ERR_SUCCESS;
     276             :                 }
     277           2 :                 return ndr_push_error(ndr,
     278             :                                       NDR_ERR_BUFSIZE,
     279             :                                       "Overflow of fixed buffer in "
     280             :                                       "push_expand to %"PRIu32,
     281             :                                       size);
     282             :         }
     283             : 
     284  4535643698 :         if (ndr->alloc_size > size) {
     285  4467875945 :                 return NDR_ERR_SUCCESS;
     286             :         }
     287             : 
     288    16123142 :         ndr->alloc_size += NDR_BASE_MARSHALL_SIZE;
     289    16123142 :         if (size == UINT32_MAX) {
     290           0 :                 return ndr_push_error(ndr, NDR_ERR_BUFSIZE, "Overflow in push_expand");
     291             :         }
     292    16123142 :         if (size+1 > ndr->alloc_size) {
     293     1808676 :                 ndr->alloc_size = size+1;
     294             :         }
     295    16123142 :         ndr->data = talloc_realloc(ndr, ndr->data, uint8_t, ndr->alloc_size);
     296    16123142 :         if (!ndr->data) {
     297           0 :                 return ndr_push_error(ndr, NDR_ERR_ALLOC, "Failed to push_expand to %"PRIu32,
     298             :                                       ndr->alloc_size);
     299             :         }
     300             : 
     301    16059830 :         return NDR_ERR_SUCCESS;
     302             : }
     303             : 
     304           0 : _PUBLIC_ void ndr_print_debugc_helper(struct ndr_print *ndr, const char *format, ...)
     305             : {
     306           0 :         va_list ap;
     307           0 :         char *s = NULL;
     308           0 :         uint32_t i;
     309           0 :         int ret;
     310           0 :         int dbgc_class;
     311             : 
     312           0 :         va_start(ap, format);
     313           0 :         ret = vasprintf(&s, format, ap);
     314           0 :         va_end(ap);
     315             : 
     316           0 :         if (ret == -1) {
     317           0 :                 return;
     318             :         }
     319             : 
     320           0 :         dbgc_class = *(int *)ndr->private_data;
     321             : 
     322           0 :         if (ndr->no_newline) {
     323           0 :                 DEBUGADDC(dbgc_class, 1,("%s", s));
     324           0 :                 free(s);
     325           0 :                 return;
     326             :         }
     327             : 
     328           0 :         for (i=0;i<ndr->depth;i++) {
     329           0 :                 DEBUGADDC(dbgc_class, 1,("    "));
     330             :         }
     331             : 
     332           0 :         DEBUGADDC(dbgc_class, 1,("%s\n", s));
     333           0 :         free(s);
     334             : }
     335             : 
     336      260458 : _PUBLIC_ void ndr_print_debug_helper(struct ndr_print *ndr, const char *format, ...)
     337             : {
     338       45005 :         va_list ap;
     339      260458 :         char *s = NULL;
     340       45005 :         uint32_t i;
     341       45005 :         int ret;
     342             : 
     343      260458 :         va_start(ap, format);
     344      260458 :         ret = vasprintf(&s, format, ap);
     345      260458 :         va_end(ap);
     346             : 
     347      260458 :         if (ret == -1) {
     348       67987 :                 return;
     349             :         }
     350             : 
     351      260458 :         if (ndr->no_newline) {
     352       67987 :                 DEBUGADD(1,("%s", s));
     353       67987 :                 free(s);
     354       67987 :                 return;
     355             :         }
     356             : 
     357     1022500 :         for (i=0;i<ndr->depth;i++) {
     358      830029 :                 DEBUGADD(1,("    "));
     359             :         }
     360             : 
     361      192471 :         DEBUGADD(1,("%s\n", s));
     362      192471 :         free(s);
     363             : }
     364             : 
     365       48354 : _PUBLIC_ void ndr_print_printf_helper(struct ndr_print *ndr, const char *format, ...)
     366             : {
     367       47836 :         va_list ap;
     368       47836 :         uint32_t i;
     369             : 
     370       48354 :         if (!ndr->no_newline) {
     371       20581 :                 for (i=0;i<ndr->depth;i++) {
     372       18051 :                         printf("    ");
     373             :                 }
     374             :         }
     375             : 
     376       48354 :         va_start(ap, format);
     377       48354 :         vprintf(format, ap);
     378       48354 :         va_end(ap);
     379       48354 :         if (!ndr->no_newline) {
     380        2530 :                 printf("\n");
     381             :         }
     382       48354 : }
     383             : 
     384    38436565 : _PUBLIC_ void ndr_print_string_helper(struct ndr_print *ndr, const char *format, ...)
     385             : {
     386     1533506 :         va_list ap;
     387     1533506 :         uint32_t i;
     388             : 
     389    38436565 :         if (!ndr->no_newline) {
     390    62904708 :                 for (i=0;i<ndr->depth;i++) {
     391    57348473 :                         ndr->private_data = talloc_asprintf_append_buffer(
     392    57348473 :                                 (char *)ndr->private_data, "    ");
     393             :                 }
     394             :         }
     395             : 
     396    38436565 :         va_start(ap, format);
     397    38436565 :         ndr->private_data = talloc_vasprintf_append_buffer((char *)ndr->private_data,
     398             :                                                     format, ap);
     399    38436565 :         va_end(ap);
     400    38436565 :         if (!ndr->no_newline) {
     401     5556235 :                 ndr->private_data = talloc_asprintf_append_buffer((char *)ndr->private_data,
     402             :                                                                   "\n");
     403             :         }
     404    38436565 : }
     405             : 
     406             : /*
     407             :   a useful helper function for printing idl structures via DEBUGC()
     408             : */
     409           0 : _PUBLIC_ void ndr_print_debugc(int dbgc_class, ndr_print_fn_t fn, const char *name, void *ptr)
     410             : {
     411           0 :         struct ndr_print *ndr;
     412             : 
     413           0 :         DEBUGC(dbgc_class, 1,(" "));
     414             : 
     415           0 :         ndr = talloc_zero(NULL, struct ndr_print);
     416           0 :         if (!ndr) return;
     417           0 :         ndr->private_data = &dbgc_class;
     418           0 :         ndr->print = ndr_print_debugc_helper;
     419           0 :         ndr->depth = 1;
     420           0 :         ndr->flags = 0;
     421             : #ifdef DEBUG_PASSWORD
     422           0 :         if (CHECK_DEBUGLVL(100)) {
     423           0 :                 ndr->print_secrets = true;
     424             :         }
     425             : #endif
     426             : 
     427           0 :         fn(ndr, name, ptr);
     428           0 :         talloc_free(ndr);
     429             : }
     430             : 
     431             : /*
     432             :   a useful helper function for printing idl structures via DEBUG()
     433             : */
     434        3776 : _PUBLIC_ bool ndr_print_debug(int level,
     435             :                               ndr_print_fn_t fn,
     436             :                               const char *name,
     437             :                               void *ptr,
     438             :                               const char *location,
     439             :                               const char *function)
     440             : {
     441           0 :         struct ndr_print *ndr;
     442             : 
     443        3776 :         DEBUGLF(level, (" "), location, function);
     444             : 
     445        3776 :         ndr = talloc_zero(NULL, struct ndr_print);
     446        3776 :         if (!ndr) return false;
     447        3776 :         ndr->print = ndr_print_debug_helper;
     448        3776 :         ndr->depth = 1;
     449        3776 :         ndr->flags = 0;
     450             : #ifdef DEBUG_PASSWORD
     451        3776 :         if (CHECK_DEBUGLVL(100)) {
     452           0 :                 ndr->print_secrets = true;
     453             :         }
     454             : #endif
     455             : 
     456        3776 :         fn(ndr, name, ptr);
     457        3776 :         talloc_free(ndr);
     458        3776 :         return true;
     459             : }
     460             : 
     461             : /*
     462             :   a useful helper function for printing idl unions via DEBUG()
     463             : */
     464           0 : _PUBLIC_ void ndr_print_union_debug(ndr_print_fn_t fn, const char *name, uint32_t level, void *ptr)
     465             : {
     466           0 :         struct ndr_print *ndr;
     467             : 
     468           0 :         DEBUG(1,(" "));
     469             : 
     470           0 :         ndr = talloc_zero(NULL, struct ndr_print);
     471           0 :         if (!ndr) return;
     472           0 :         ndr->print = ndr_print_debug_helper;
     473           0 :         ndr->depth = 1;
     474           0 :         ndr->flags = 0;
     475             : #ifdef DEBUG_PASSWORD
     476           0 :         if (CHECK_DEBUGLVL(100)) {
     477           0 :                 ndr->print_secrets = true;
     478             :         }
     479             : #endif
     480             : 
     481           0 :         ndr_print_set_switch_value(ndr, ptr, level);
     482           0 :         fn(ndr, name, ptr);
     483           0 :         talloc_free(ndr);
     484             : }
     485             : 
     486             : /*
     487             :   a useful helper function for printing idl function calls via DEBUG()
     488             : */
     489         212 : _PUBLIC_ void ndr_print_function_debug(ndr_print_function_t fn, const char *name, ndr_flags_type flags, void *ptr)
     490             : {
     491           0 :         struct ndr_print *ndr;
     492             : 
     493         212 :         DEBUG(1,(" "));
     494             : 
     495         212 :         ndr = talloc_zero(NULL, struct ndr_print);
     496         212 :         if (!ndr) return;
     497         212 :         ndr->print = ndr_print_debug_helper;
     498         212 :         ndr->depth = 1;
     499         212 :         ndr->flags = 0;
     500             : #ifdef DEBUG_PASSWORD
     501         212 :         if (CHECK_DEBUGLVL(100)) {
     502           0 :                 ndr->print_secrets = true;
     503             :         }
     504             : #endif
     505             : 
     506         212 :         fn(ndr, name, flags, ptr);
     507         212 :         talloc_free(ndr);
     508             : }
     509             : 
     510             : /*
     511             :   a useful helper function for printing idl structures to a string
     512             : */
     513         426 : _PUBLIC_ char *ndr_print_struct_string(TALLOC_CTX *mem_ctx, ndr_print_fn_t fn, const char *name, void *ptr)
     514             : {
     515          11 :         struct ndr_print *ndr;
     516         426 :         char *ret = NULL;
     517             : 
     518         426 :         ndr = talloc_zero(mem_ctx, struct ndr_print);
     519         426 :         if (!ndr) return NULL;
     520         426 :         ndr->private_data = talloc_strdup(ndr, "");
     521         426 :         if (!ndr->private_data) {
     522           0 :                 goto failed;
     523             :         }
     524         426 :         ndr->print = ndr_print_string_helper;
     525         426 :         ndr->depth = 1;
     526         426 :         ndr->flags = 0;
     527             : 
     528         426 :         fn(ndr, name, ptr);
     529         426 :         ret = talloc_steal(mem_ctx, (char *)ndr->private_data);
     530         426 : failed:
     531         426 :         talloc_free(ndr);
     532         426 :         return ret;
     533             : }
     534             : 
     535             : /*
     536             :   a useful helper function for printing idl unions to a string
     537             : */
     538           0 : _PUBLIC_ char *ndr_print_union_string(TALLOC_CTX *mem_ctx, ndr_print_fn_t fn, const char *name, uint32_t level, void *ptr)
     539             : {
     540           0 :         struct ndr_print *ndr;
     541           0 :         char *ret = NULL;
     542             : 
     543           0 :         ndr = talloc_zero(mem_ctx, struct ndr_print);
     544           0 :         if (!ndr) return NULL;
     545           0 :         ndr->private_data = talloc_strdup(ndr, "");
     546           0 :         if (!ndr->private_data) {
     547           0 :                 goto failed;
     548             :         }
     549           0 :         ndr->print = ndr_print_string_helper;
     550           0 :         ndr->depth = 1;
     551           0 :         ndr->flags = 0;
     552           0 :         ndr_print_set_switch_value(ndr, ptr, level);
     553           0 :         fn(ndr, name, ptr);
     554           0 :         ret = talloc_steal(mem_ctx, (char *)ndr->private_data);
     555           0 : failed:
     556           0 :         talloc_free(ndr);
     557           0 :         return ret;
     558             : }
     559             : 
     560             : /*
     561             :   a useful helper function for printing idl function calls to a string
     562             : */
     563       52440 : _PUBLIC_ char *ndr_print_function_string(TALLOC_CTX *mem_ctx,
     564             :                                 ndr_print_function_t fn, const char *name,
     565             :                                 ndr_flags_type flags, void *ptr)
     566             : {
     567        2990 :         struct ndr_print *ndr;
     568       52440 :         char *ret = NULL;
     569             : 
     570       52440 :         ndr = talloc_zero(mem_ctx, struct ndr_print);
     571       52440 :         if (!ndr) return NULL;
     572       52440 :         ndr->private_data = talloc_strdup(ndr, "");
     573       52440 :         if (!ndr->private_data) {
     574           0 :                 goto failed;
     575             :         }
     576       52440 :         ndr->print = ndr_print_string_helper;
     577       52440 :         ndr->depth = 1;
     578       52440 :         ndr->flags = 0;
     579       52440 :         fn(ndr, name, flags, ptr);
     580       52440 :         ret = talloc_steal(mem_ctx, (char *)ndr->private_data);
     581       52440 : failed:
     582       52440 :         talloc_free(ndr);
     583       52440 :         return ret;
     584             : }
     585             : 
     586   373235824 : _PUBLIC_ void ndr_set_flags(libndr_flags *pflags, libndr_flags new_flags)
     587             : {
     588             :         /* the big/little endian flags are inter-dependent */
     589   373235824 :         if (new_flags & LIBNDR_FLAG_LITTLE_ENDIAN) {
     590    17826143 :                 (*pflags) &= ~LIBNDR_FLAG_BIGENDIAN;
     591    17826143 :                 (*pflags) &= ~LIBNDR_FLAG_NDR64;
     592             :         }
     593   373235824 :         if (new_flags & LIBNDR_FLAG_BIGENDIAN) {
     594     2056304 :                 (*pflags) &= ~LIBNDR_FLAG_LITTLE_ENDIAN;
     595     2056304 :                 (*pflags) &= ~LIBNDR_FLAG_NDR64;
     596             :         }
     597   373235824 :         if (new_flags & LIBNDR_ALIGN_FLAGS) {
     598             :                 /* Ensure we only have the passed-in
     599             :                    align flag set in the new_flags,
     600             :                    remove any old align flag. */
     601    35558292 :                 (*pflags) &= ~LIBNDR_ALIGN_FLAGS;
     602             :         }
     603   373235824 :         if (new_flags & LIBNDR_FLAG_NO_RELATIVE_REVERSE) {
     604        2864 :                 (*pflags) &= ~LIBNDR_FLAG_RELATIVE_REVERSE;
     605             :         }
     606   373235824 :         (*pflags) |= new_flags;
     607   373235824 : }
     608             : 
     609             : /*
     610             :   return and possibly log an NDR error
     611             : */
     612         737 : _PUBLIC_ enum ndr_err_code _ndr_pull_error(struct ndr_pull *ndr,
     613             :                                            enum ndr_err_code ndr_err,
     614             :                                            const char *function,
     615             :                                            const char *location,
     616             :                                            const char *format, ...)
     617             : {
     618         737 :         char *s=NULL;
     619          54 :         va_list ap;
     620          54 :         int ret;
     621             : 
     622         737 :         if (ndr->flags & LIBNDR_FLAG_INCOMPLETE_BUFFER) {
     623           0 :                 switch (ndr_err) {
     624           0 :                 case NDR_ERR_BUFSIZE:
     625           0 :                         return NDR_ERR_INCOMPLETE_BUFFER;
     626           0 :                 default:
     627           0 :                         break;
     628             :                 }
     629             :         }
     630             : 
     631         737 :         va_start(ap, format);
     632         737 :         ret = vasprintf(&s, format, ap);
     633         737 :         va_end(ap);
     634             : 
     635         737 :         if (ret == -1) {
     636           0 :                 return NDR_ERR_ALLOC;
     637             :         }
     638             : 
     639         737 :         D_WARNING("%s: ndr_pull_error(%s): %s at %s\n",
     640             :                   function,
     641             :                   ndr_map_error2string(ndr_err),
     642             :                   s,
     643             :                   location);
     644             : 
     645         737 :         free(s);
     646             : 
     647         737 :         return ndr_err;
     648             : }
     649             : 
     650             : /*
     651             :   return and possibly log an NDR error
     652             : */
     653         376 : _PUBLIC_ enum ndr_err_code _ndr_push_error(struct ndr_push *ndr,
     654             :                                            enum ndr_err_code ndr_err,
     655             :                                            const char *function,
     656             :                                            const char *location,
     657             :                                            const char *format, ...)
     658             : {
     659         376 :         char *s=NULL;
     660          14 :         va_list ap;
     661          14 :         int ret;
     662             : 
     663         376 :         va_start(ap, format);
     664         376 :         ret = vasprintf(&s, format, ap);
     665         376 :         va_end(ap);
     666             : 
     667         376 :         if (ret == -1) {
     668           0 :                 return NDR_ERR_ALLOC;
     669             :         }
     670             : 
     671         376 :         D_WARNING("%s: ndr_push_error(%s): %s at %s\n",
     672             :                   function,
     673             :                   ndr_map_error2string(ndr_err),
     674             :                   s,
     675             :                   location);
     676             : 
     677         376 :         free(s);
     678             : 
     679         376 :         return ndr_err;
     680             : }
     681             : 
     682             : /*
     683             :   handle subcontext buffers, which in midl land are user-marshalled, but
     684             :   we use magic in pidl to make them easier to cope with
     685             : */
     686     5064975 : _PUBLIC_ enum ndr_err_code ndr_pull_subcontext_start(struct ndr_pull *ndr,
     687             :                                    struct ndr_pull **_subndr,
     688             :                                    size_t header_size,
     689             :                                    ssize_t size_is)
     690             : {
     691      120138 :         struct ndr_pull *subndr;
     692      120138 :         uint32_t r_content_size;
     693     5064975 :         bool force_le = false;
     694     5064975 :         bool force_be = false;
     695             : 
     696     5064975 :         switch (header_size) {
     697     4031499 :         case 0: {
     698     4031499 :                 uint32_t content_size = ndr->data_size - ndr->offset;
     699     4031499 :                 if (size_is >= 0) {
     700     3937337 :                         content_size = size_is;
     701             :                 }
     702     3951231 :                 r_content_size = content_size;
     703     3951231 :                 break;
     704             :         }
     705             : 
     706      763576 :         case 2: {
     707        3728 :                 uint16_t content_size;
     708      763576 :                 NDR_CHECK(ndr_pull_uint16(ndr, NDR_SCALARS, &content_size));
     709      763576 :                 if (size_is >= 0 && size_is != content_size) {
     710           0 :                         return ndr_pull_error(ndr, NDR_ERR_SUBCONTEXT, "Bad subcontext (PULL) size_is(%zd) (0x%04zx) mismatch content_size %"PRIu16" (0x%04"PRIx16")",
     711             :                                                 size_is, size_is,
     712             :                                                 content_size,
     713             :                                                 content_size);
     714             :                 }
     715      763576 :                 r_content_size = content_size;
     716      763576 :                 break;
     717             :         }
     718             : 
     719      130768 :         case 4: {
     720       33521 :                 uint32_t content_size;
     721      130768 :                 NDR_CHECK(ndr_pull_uint3264(ndr, NDR_SCALARS, &content_size));
     722      130768 :                 if (size_is >= 0 && size_is != content_size) {
     723           0 :                         return ndr_pull_error(ndr, NDR_ERR_SUBCONTEXT, "Bad subcontext (PULL) size_is(%zd) (0x%08zx) mismatch content_size %"PRIu32" (0x%08"PRIx32")",
     724             :                                                 size_is, size_is,
     725             :                                                 content_size,
     726             :                                                 content_size);
     727             :                 }
     728      130768 :                 r_content_size = content_size;
     729      130768 :                 break;
     730             :         }
     731      139132 :         case 0xFFFFFC01: {
     732             :                 /*
     733             :                  * Common Type Header for the Serialization Stream
     734             :                  * See [MS-RPCE] 2.2.6 Type Serialization Version 1
     735             :                  */
     736        2621 :                 uint8_t version;
     737        2621 :                 uint8_t drep;
     738        2621 :                 uint16_t hdrlen;
     739        2621 :                 uint32_t filler;
     740        2621 :                 uint32_t content_size;
     741        2621 :                 uint32_t reserved;
     742             : 
     743             :                 /* version */
     744      139132 :                 NDR_CHECK(ndr_pull_uint8(ndr, NDR_SCALARS, &version));
     745             : 
     746      139132 :                 if (version != 1) {
     747           0 :                         return ndr_pull_error(ndr, NDR_ERR_SUBCONTEXT,
     748             :                                               "Bad subcontext (PULL) Common Type Header version %"PRIu8" != 1",
     749             :                                               version);
     750             :                 }
     751             : 
     752             :                 /*
     753             :                  * 0x10 little endian
     754             :                  * 0x00 big endian
     755             :                  */
     756      139132 :                 NDR_CHECK(ndr_pull_uint8(ndr, NDR_SCALARS, &drep));
     757      139132 :                 if (drep == 0x10) {
     758      136511 :                         force_le = true;
     759           0 :                 } else if (drep == 0x00) {
     760           0 :                         force_be = true;
     761             :                 } else {
     762           0 :                         return ndr_pull_error(ndr, NDR_ERR_SUBCONTEXT,
     763             :                                               "Bad subcontext (PULL) Common Type Header invalid drep 0x%02"PRIX8,
     764             :                                               drep);
     765             :                 }
     766             : 
     767             :                 /* length of the "Private Header for Constructed Type" */
     768      139132 :                 NDR_CHECK(ndr_pull_uint16(ndr, NDR_SCALARS, &hdrlen));
     769      139132 :                 if (hdrlen != 8) {
     770           0 :                         return ndr_pull_error(ndr, NDR_ERR_SUBCONTEXT,
     771             :                                               "Bad subcontext (PULL) Common Type Header length %"PRIu16" != 8",
     772             :                                               hdrlen);
     773             :                 }
     774             : 
     775             :                 /* filler should be ignored */
     776      139132 :                 NDR_CHECK(ndr_pull_uint32(ndr, NDR_SCALARS, &filler));
     777             : 
     778             :                 /*
     779             :                  * Private Header for Constructed Type
     780             :                  */
     781             :                 /* length - will be updated later */
     782      139132 :                 NDR_CHECK(ndr_pull_uint32(ndr, NDR_SCALARS, &content_size));
     783      139132 :                 if (size_is >= 0 && size_is != content_size) {
     784           0 :                         return ndr_pull_error(ndr, NDR_ERR_SUBCONTEXT, "Bad subcontext (PULL) size_is(%zd) mismatch content_size %"PRIu32,
     785             :                                               size_is, content_size);
     786             :                 }
     787             :                 /* the content size must be a multiple of 8 */
     788      139132 :                 if ((content_size % 8) != 0) {
     789           0 :                         return ndr_pull_error(ndr, NDR_ERR_SUBCONTEXT,
     790             :                                               "Bad subcontext (PULL) size_is(%zd) not padded to 8 content_size %"PRIu32,
     791             :                                               size_is, content_size);
     792             :                 }
     793      139132 :                 r_content_size = content_size;
     794             : 
     795             :                 /* reserved */
     796      139132 :                 NDR_CHECK(ndr_pull_uint32(ndr, NDR_SCALARS, &reserved));
     797      139132 :                 break;
     798             :         }
     799           0 :         case 0xFFFFFFFF:
     800             :                 /*
     801             :                  * a shallow copy like subcontext
     802             :                  * useful for DCERPC pipe chunks.
     803             :                  */
     804           0 :                 subndr = talloc_zero(ndr, struct ndr_pull);
     805           0 :                 NDR_ERR_HAVE_NO_MEMORY(subndr);
     806             : 
     807           0 :                 subndr->flags                = ndr->flags;
     808           0 :                 subndr->current_mem_ctx      = ndr->current_mem_ctx;
     809           0 :                 subndr->data         = ndr->data;
     810           0 :                 subndr->offset               = ndr->offset;
     811           0 :                 subndr->data_size    = ndr->data_size;
     812             : 
     813           0 :                 *_subndr = subndr;
     814           0 :                 return NDR_ERR_SUCCESS;
     815             : 
     816           0 :         default:
     817           0 :                 return ndr_pull_error(ndr, NDR_ERR_SUBCONTEXT, "Bad subcontext (PULL) header_size %zu",
     818             :                                       header_size);
     819             :         }
     820             : 
     821     5064975 :         NDR_PULL_NEED_BYTES(ndr, r_content_size);
     822             : 
     823     5064963 :         subndr = talloc_zero(ndr, struct ndr_pull);
     824     5064963 :         NDR_ERR_HAVE_NO_MEMORY(subndr);
     825     5064963 :         subndr->flags                = ndr->flags & ~LIBNDR_FLAG_NDR64;
     826     5064963 :         subndr->current_mem_ctx      = ndr->current_mem_ctx;
     827             : 
     828     5064963 :         subndr->data = ndr->data + ndr->offset;
     829     5064963 :         subndr->offset = 0;
     830     5064963 :         subndr->data_size = r_content_size;
     831             : 
     832     5064963 :         if (force_le) {
     833      139132 :                 ndr_set_flags(&ndr->flags, LIBNDR_FLAG_LITTLE_ENDIAN);
     834     4925831 :         } else if (force_be) {
     835           0 :                 ndr_set_flags(&ndr->flags, LIBNDR_FLAG_BIGENDIAN);
     836             :         }
     837             : 
     838     5064963 :         *_subndr = subndr;
     839     5064963 :         return NDR_ERR_SUCCESS;
     840             : }
     841             : 
     842     5064950 : _PUBLIC_ enum ndr_err_code ndr_pull_subcontext_end(struct ndr_pull *ndr,
     843             :                                  struct ndr_pull *subndr,
     844             :                                  size_t header_size,
     845             :                                  ssize_t size_is)
     846             : {
     847      120133 :         uint32_t advance;
     848      120133 :         uint32_t highest_ofs;
     849             : 
     850     5064950 :         if (header_size == 0xFFFFFFFF) {
     851           0 :                 advance = subndr->offset - ndr->offset;
     852     5064950 :         } else if (size_is >= 0) {
     853     3943271 :                 advance = size_is;
     854     1121679 :         } else if (header_size > 0) {
     855     1027529 :                 advance = subndr->data_size;
     856             :         } else {
     857       94150 :                 advance = subndr->offset;
     858             :         }
     859             : 
     860     5064950 :         if (subndr->offset > ndr->relative_highest_offset) {
     861     2744890 :                 highest_ofs = subndr->offset;
     862             :         } else {
     863     2250828 :                 highest_ofs = subndr->relative_highest_offset;
     864             :         }
     865     5064950 :         if (!(subndr->flags & LIBNDR_FLAG_SUBCONTEXT_NO_UNREAD_BYTES)) {
     866             :                 /*
     867             :                  * avoid an error unless SUBCONTEXT_NO_UNREAD_BYTES is specified
     868             :                  */
     869     4882625 :                 highest_ofs = advance;
     870             :         }
     871     5064950 :         if (highest_ofs < advance) {
     872           0 :                 return ndr_pull_error(subndr, NDR_ERR_UNREAD_BYTES,
     873             :                                       "not all bytes consumed ofs[%"PRIu32"] advance[%"PRIu32"]",
     874             :                                       highest_ofs, advance);
     875             :         }
     876             : 
     877     5064950 :         NDR_CHECK(ndr_pull_advance(ndr, advance));
     878     4944817 :         return NDR_ERR_SUCCESS;
     879             : }
     880             : 
     881     2902993 : _PUBLIC_ enum ndr_err_code ndr_push_subcontext_start(struct ndr_push *ndr,
     882             :                                    struct ndr_push **_subndr,
     883             :                                    size_t header_size,
     884             :                                    ssize_t size_is)
     885             : {
     886       53040 :         struct ndr_push *subndr;
     887             : 
     888     2902993 :         subndr = ndr_push_init_ctx(ndr);
     889     2902993 :         NDR_ERR_HAVE_NO_MEMORY(subndr);
     890     2902993 :         subndr->flags        = ndr->flags & ~LIBNDR_FLAG_NDR64;
     891             : 
     892     2902993 :         if (size_is > 0) {
     893        9700 :                 enum ndr_err_code status;
     894             : 
     895     1354868 :                 status = ndr_push_zero(subndr, size_is);
     896     1354868 :                 if (!NDR_ERR_CODE_IS_SUCCESS(status)) {
     897           0 :                         talloc_free(subndr);
     898           0 :                         return status;
     899             :                 }
     900     1354868 :                 subndr->offset = 0;
     901     1354868 :                 subndr->relative_end_offset = size_is;
     902             :         }
     903             : 
     904     2902993 :         *_subndr = subndr;
     905     2902993 :         return NDR_ERR_SUCCESS;
     906             : }
     907             : 
     908             : /*
     909             :   push a subcontext header
     910             : */
     911     2902905 : _PUBLIC_ enum ndr_err_code ndr_push_subcontext_end(struct ndr_push *ndr,
     912             :                                  struct ndr_push *subndr,
     913             :                                  size_t header_size,
     914             :                                  ssize_t size_is)
     915             : {
     916       53040 :         ssize_t padding_len;
     917             : 
     918     2902905 :         if (size_is >= 0) {
     919     1476734 :                 padding_len = size_is - subndr->offset;
     920     1476734 :                 if (padding_len < 0) {
     921           0 :                         return ndr_push_error(ndr, NDR_ERR_SUBCONTEXT, "Bad subcontext (PUSH) content_size %"PRIu32" is larger than size_is(%zd)",
     922             :                                               subndr->offset, size_is);
     923             :                 }
     924     1476734 :                 subndr->offset = size_is;
     925             :         }
     926             : 
     927     2902905 :         switch (header_size) {
     928     1462185 :         case 0:
     929     1462185 :                 break;
     930             : 
     931     1172599 :         case 2:
     932     1172599 :                 NDR_CHECK(ndr_push_uint16(ndr, NDR_SCALARS, subndr->offset));
     933     1166412 :                 break;
     934             : 
     935      160051 :         case 4:
     936      160051 :                 NDR_CHECK(ndr_push_uint3264(ndr, NDR_SCALARS, subndr->offset));
     937      126153 :                 break;
     938             : 
     939       98065 :         case 0xFFFFFC01:
     940             :                 /*
     941             :                  * Common Type Header for the Serialization Stream
     942             :                  * See [MS-RPCE] 2.2.6 Type Serialization Version 1
     943             :                  */
     944       98065 :                 padding_len = NDR_ROUND(subndr->offset, 8) - subndr->offset;
     945       98065 :                 if (padding_len > 0) {
     946       68012 :                         NDR_CHECK(ndr_push_zero(subndr, padding_len));
     947             :                 }
     948             : 
     949             :                 /* version */
     950       98065 :                 NDR_CHECK(ndr_push_uint8(ndr, NDR_SCALARS, 1));
     951             : 
     952             :                 /*
     953             :                  * 0x10 little endian
     954             :                  * 0x00 big endian
     955             :                  */
     956      101015 :                 NDR_CHECK(ndr_push_uint8(ndr, NDR_SCALARS, NDR_BE(ndr)?0x00:0x10));
     957             : 
     958             :                 /* length of the "Private Header for Constructed Type" */
     959       98065 :                 NDR_CHECK(ndr_push_uint16(ndr, NDR_SCALARS, 8));
     960             : 
     961             :                 /* filler */
     962       98065 :                 NDR_CHECK(ndr_push_uint32(ndr, NDR_SCALARS, 0xCCCCCCCC));
     963             : 
     964             :                 /*
     965             :                  * Private Header for Constructed Type
     966             :                  */
     967             :                 /* length - will be updated later */
     968       98065 :                 NDR_CHECK(ndr_push_uint32(ndr, NDR_SCALARS, subndr->offset));
     969             : 
     970             :                 /* reserved */
     971       98065 :                 NDR_CHECK(ndr_push_uint32(ndr, NDR_SCALARS, 0));
     972       95115 :                 break;
     973             : 
     974           0 :         default:
     975           0 :                 return ndr_push_error(ndr, NDR_ERR_SUBCONTEXT, "Bad subcontext header size %zu",
     976             :                                       header_size);
     977             :         }
     978             : 
     979     2902905 :         NDR_CHECK(ndr_push_bytes(ndr, subndr->data, subndr->offset));
     980     2849865 :         return NDR_ERR_SUCCESS;
     981             : }
     982             : 
     983             : 
     984             : struct ndr_token {
     985             :         const void *key;
     986             :         uint32_t value;
     987             : };
     988             : 
     989             : /*
     990             :   store a token in the ndr context, for later retrieval
     991             : */
     992  1371087641 : _PUBLIC_ enum ndr_err_code ndr_token_store(TALLOC_CTX *mem_ctx,
     993             :                          struct ndr_token_list *list,
     994             :                          const void *key,
     995             :                          uint32_t value)
     996             : {
     997  1371087641 :         if (list->tokens == NULL) {
     998   110963140 :                 list->tokens = talloc_array(mem_ctx, struct ndr_token, 10);
     999   110963140 :                 if (list->tokens == NULL) {
    1000           0 :                         NDR_ERR_HAVE_NO_MEMORY(list->tokens);
    1001             :                 }
    1002             :         } else {
    1003  1260124501 :                 struct ndr_token *new_tokens = NULL;
    1004  1260124501 :                 uint32_t alloc_count = talloc_array_length(list->tokens);
    1005             : 
    1006             :                 /*
    1007             :                  * Check every time we have not allocated too many
    1008             :                  * tokens.  This ensures developer sanity when
    1009             :                  * debugging the boundary condition
    1010             :                  */
    1011  1260124501 :                 if (list->count >= NDR_TOKEN_MAX_LIST_SIZE) {
    1012           0 :                         return NDR_ERR_RANGE;
    1013             :                 }
    1014  1260124501 :                 if (list->count == alloc_count) {
    1015      456710 :                         uint32_t new_alloc;
    1016             :                         /*
    1017             :                          * Double the list, until we start in chunks
    1018             :                          * of 1000
    1019             :                          */
    1020    16623979 :                         uint32_t increment = MIN(list->count, 1000);
    1021    16623979 :                         new_alloc = alloc_count + increment;
    1022    16623979 :                         if (new_alloc < alloc_count) {
    1023           0 :                                 return NDR_ERR_RANGE;
    1024             :                         }
    1025    16623979 :                         new_tokens = talloc_realloc(mem_ctx, list->tokens,
    1026             :                                                     struct ndr_token, new_alloc);
    1027    16623979 :                         NDR_ERR_HAVE_NO_MEMORY(new_tokens);
    1028    16623979 :                         list->tokens = new_tokens;
    1029             :                 }
    1030             :         }
    1031  1371087641 :         list->tokens[list->count].key = key;
    1032  1371087641 :         list->tokens[list->count].value = value;
    1033  1371087641 :         list->count++;
    1034  1371087641 :         return NDR_ERR_SUCCESS;
    1035             : }
    1036             : 
    1037             : /*
    1038             :   retrieve a token from a ndr context, using cmp_fn to match the tokens
    1039             : */
    1040  1436666009 : _PUBLIC_ enum ndr_err_code ndr_token_retrieve_cmp_fn(struct ndr_token_list *list,
    1041             :                                                      const void *key, uint32_t *v,
    1042             :                                                      comparison_fn_t _cmp_fn,
    1043             :                                                      bool erase)
    1044             : {
    1045  1436666009 :         struct ndr_token *tokens = list->tokens;
    1046    19984171 :         unsigned i;
    1047  1436666009 :         if (_cmp_fn) {
    1048      724364 :                 for (i = list->count - 1; i < list->count; i--) {
    1049      598573 :                         if (_cmp_fn(tokens[i].key, key) == 0) {
    1050       33379 :                                 goto found;
    1051             :                         }
    1052             :                 }
    1053             :         } else {
    1054  2098275219 :                 for (i = list->count - 1; i < list->count; i--) {
    1055  2098207690 :                         if (tokens[i].key == key) {
    1056  1436439310 :                                 goto found;
    1057             :                         }
    1058             :                 }
    1059             :         }
    1060      192282 :         return NDR_ERR_TOKEN;
    1061  1436472689 : found:
    1062  1436472689 :         *v = tokens[i].value;
    1063  1436472689 :         if (erase) {
    1064   905499051 :                 if (i != list->count - 1) {
    1065   119770586 :                         tokens[i] = tokens[list->count - 1];
    1066             :                 }
    1067   905499051 :                 list->count--;
    1068             :         }
    1069  1416489556 :         return NDR_ERR_SUCCESS;
    1070             : }
    1071             : 
    1072             : /*
    1073             :   retrieve a token from a ndr context
    1074             : */
    1075   905499051 : _PUBLIC_ enum ndr_err_code ndr_token_retrieve(struct ndr_token_list *list,
    1076             :                                               const void *key, uint32_t *v)
    1077             : {
    1078   905499051 :         return ndr_token_retrieve_cmp_fn(list, key, v, NULL, true);
    1079             : }
    1080             : 
    1081             : /*
    1082             :   peek at but don't removed a token from a ndr context
    1083             : */
    1084   531007788 : _PUBLIC_ enum ndr_err_code ndr_token_peek(struct ndr_token_list *list,
    1085             :                                           const void *key, uint32_t *v)
    1086             : {
    1087   531007788 :         return ndr_token_retrieve_cmp_fn(list, key, v, NULL, false);
    1088             : }
    1089             : 
    1090             : /*
    1091             :   pull an array size field and add it to the array_size_list token list
    1092             : */
    1093   254559879 : _PUBLIC_ enum ndr_err_code ndr_pull_array_size(struct ndr_pull *ndr, const void *p)
    1094             : {
    1095      323158 :         enum ndr_err_code ret;
    1096      323158 :         uint32_t size;
    1097   254559879 :         NDR_CHECK(ndr_pull_uint3264(ndr, NDR_SCALARS, &size));
    1098   254559855 :         ret = ndr_token_store(ndr, &ndr->array_size_list, p, size);
    1099   254559855 :         if (ret == NDR_ERR_RANGE) {
    1100           0 :                 return ndr_pull_error(ndr, ret,
    1101             :                                       "More than %d NDR tokens stored for array_size",
    1102             :                                       NDR_TOKEN_MAX_LIST_SIZE);
    1103             :         }
    1104   254236697 :         return ret;
    1105             : }
    1106             : 
    1107             : /*
    1108             :   get the stored array size field
    1109             : */
    1110   527222215 : _PUBLIC_ enum ndr_err_code ndr_get_array_size(struct ndr_pull *ndr, const void *p, uint32_t *size)
    1111             : {
    1112   527222215 :         return ndr_token_peek(&ndr->array_size_list, p, size);
    1113             : }
    1114             : 
    1115             : /*
    1116             :   get and remove from the stored list the stored array size field
    1117             : */
    1118   109440686 : _PUBLIC_ enum ndr_err_code ndr_steal_array_size(struct ndr_pull *ndr, const void *p, uint32_t *size)
    1119             : {
    1120   109440686 :         return ndr_token_retrieve(&ndr->array_size_list, p, size);
    1121             : }
    1122             : 
    1123             : /*
    1124             :  * check the stored array size field and remove from the stored list
    1125             :  * (the array_size NDR token list).  We try to remove when possible to
    1126             :  * avoid the list growing towards the bounds check
    1127             :  */
    1128    99777641 : _PUBLIC_ enum ndr_err_code ndr_check_steal_array_size(struct ndr_pull *ndr, const void *p, uint32_t size)
    1129             : {
    1130      140533 :         uint32_t stored;
    1131    99777641 :         NDR_CHECK(ndr_steal_array_size(ndr, p, &stored));
    1132    99777641 :         if (stored != size) {
    1133           0 :                 return ndr_pull_error(ndr, NDR_ERR_ARRAY_SIZE,
    1134             :                                       "Bad array size - got %u expected %u\n",
    1135             :                                       stored, size);
    1136             :         }
    1137    99637108 :         return NDR_ERR_SUCCESS;
    1138             : }
    1139             : 
    1140             : /*
    1141             :  * check the stored array size field (leaving it on the array_size
    1142             :  * token list)
    1143             :  */
    1144   145119129 : _PUBLIC_ enum ndr_err_code ndr_check_array_size(struct ndr_pull *ndr, const void *p, uint32_t size)
    1145             : {
    1146       44031 :         uint32_t stored;
    1147   145119129 :         NDR_CHECK(ndr_get_array_size(ndr, p, &stored));
    1148   145119129 :         if (stored != size) {
    1149           0 :                 return ndr_pull_error(ndr, NDR_ERR_ARRAY_SIZE,
    1150             :                                       "Bad array size - got %"PRIu32" expected %"PRIu32"\n",
    1151             :                                       stored, size);
    1152             :         }
    1153   145075098 :         return NDR_ERR_SUCCESS;
    1154             : }
    1155             : 
    1156             : /*
    1157             :   pull an array length field and add it to the array_length_list token list
    1158             : */
    1159    13422933 : _PUBLIC_ enum ndr_err_code ndr_pull_array_length(struct ndr_pull *ndr, const void *p)
    1160             : {
    1161      196056 :         enum ndr_err_code ret;
    1162      196056 :         uint32_t length, offset;
    1163    13422933 :         NDR_CHECK(ndr_pull_uint3264(ndr, NDR_SCALARS, &offset));
    1164    13422933 :         if (offset != 0) {
    1165           0 :                 return ndr_pull_error(ndr, NDR_ERR_ARRAY_SIZE,
    1166             :                                       "non-zero array offset %"PRIu32"\n", offset);
    1167             :         }
    1168    13422933 :         NDR_CHECK(ndr_pull_uint3264(ndr, NDR_SCALARS, &length));
    1169    13422933 :         ret = ndr_token_store(ndr, &ndr->array_length_list, p, length);
    1170    13422933 :         if (ret == NDR_ERR_RANGE) {
    1171           0 :                 return ndr_pull_error(ndr, ret,
    1172             :                                       "More than %d NDR tokens stored for array_length_list",
    1173             :                                       NDR_TOKEN_MAX_LIST_SIZE);
    1174             :         }
    1175    13226877 :         return ret;
    1176             : }
    1177             : 
    1178             : /*
    1179             :   get the stored array length field
    1180             : */
    1181     3718044 : _PUBLIC_ enum ndr_err_code ndr_get_array_length(struct ndr_pull *ndr, const void *p, uint32_t *length)
    1182             : {
    1183     3718044 :         return ndr_token_peek(&ndr->array_length_list, p, length);
    1184             : }
    1185             : 
    1186             : /*
    1187             :  * check the stored array length field and remove from the stored list
    1188             :  * (the array_size NDR token list).  We try to remove when possible to
    1189             :  * avoid the list growing towards the bounds check
    1190             :  */
    1191    13422933 : _PUBLIC_ enum ndr_err_code ndr_steal_array_length(struct ndr_pull *ndr, const void *p, uint32_t *length)
    1192             : {
    1193    13422933 :         return ndr_token_retrieve(&ndr->array_length_list, p, length);
    1194             : }
    1195             : /*
    1196             :   check the stored array length field, removing it from the list
    1197             : */
    1198     3718044 : _PUBLIC_ enum ndr_err_code ndr_check_steal_array_length(struct ndr_pull *ndr, const void *p, uint32_t length)
    1199             : {
    1200       57462 :         uint32_t stored;
    1201     3718044 :         NDR_CHECK(ndr_steal_array_length(ndr, p, &stored));
    1202     3718044 :         if (stored != length) {
    1203           0 :                 return ndr_pull_error(ndr, NDR_ERR_ARRAY_SIZE,
    1204             :                                       "Bad array length: got %"PRIu32" expected %"PRIu32"\n",
    1205             :                                       stored, length);
    1206             :         }
    1207     3660582 :         return NDR_ERR_SUCCESS;
    1208             : }
    1209             : 
    1210           0 : _PUBLIC_ enum ndr_err_code ndr_push_pipe_chunk_trailer(struct ndr_push *ndr, ndr_flags_type ndr_flags, uint32_t count)
    1211             : {
    1212           0 :         if (ndr->flags & LIBNDR_FLAG_NDR64) {
    1213           0 :                 int64_t tmp = 0 - (int64_t)count;
    1214           0 :                 uint64_t ncount = tmp;
    1215             : 
    1216           0 :                 NDR_CHECK(ndr_push_hyper(ndr, ndr_flags, ncount));
    1217             :         }
    1218             : 
    1219           0 :         return NDR_ERR_SUCCESS;
    1220             : }
    1221             : 
    1222           0 : _PUBLIC_ enum ndr_err_code ndr_check_pipe_chunk_trailer(struct ndr_pull *ndr, ndr_flags_type ndr_flags, uint32_t count)
    1223             : {
    1224           0 :         if (ndr->flags & LIBNDR_FLAG_NDR64) {
    1225           0 :                 int64_t tmp = 0 - (int64_t)count;
    1226           0 :                 uint64_t ncount1 = tmp;
    1227           0 :                 uint64_t ncount2;
    1228             : 
    1229           0 :                 NDR_CHECK(ndr_pull_hyper(ndr, ndr_flags, &ncount2));
    1230           0 :                 if (ncount1 == ncount2) {
    1231           0 :                         return NDR_ERR_SUCCESS;
    1232             :                 }
    1233             : 
    1234           0 :                 return ndr_pull_error(ndr, NDR_ERR_ARRAY_SIZE,
    1235             :                         "Bad pipe trailer[%"PRIu64" should be %"PRIu64"] size was %"PRIu32"\"",
    1236             :                         ncount2,
    1237             :                         ncount1,
    1238             :                         count);
    1239             :         }
    1240             : 
    1241           0 :         return NDR_ERR_SUCCESS;
    1242             : }
    1243             : 
    1244             : /*
    1245             :   store a switch value
    1246             :  */
    1247   196912835 : _PUBLIC_ enum ndr_err_code ndr_push_set_switch_value(struct ndr_push *ndr, const void *p, uint32_t val)
    1248             : {
    1249     3502662 :         enum ndr_err_code ret =
    1250   196912835 :                 ndr_token_store(ndr, &ndr->switch_list, p, val);
    1251   196912835 :         if (ret == NDR_ERR_RANGE) {
    1252           0 :                 return ndr_push_error(ndr, ret,
    1253             :                                       "More than %d NDR tokens stored for switch_list",
    1254             :                                       NDR_TOKEN_MAX_LIST_SIZE);
    1255             :         }
    1256   193410173 :         return ret;
    1257             : }
    1258             : 
    1259   839993194 : _PUBLIC_ enum ndr_err_code ndr_pull_set_switch_value(struct ndr_pull *ndr, const void *p, uint32_t val)
    1260             : {
    1261             : 
    1262    20925091 :         enum ndr_err_code ret =
    1263   839993194 :                 ndr_token_store(ndr, &ndr->switch_list, p, val);
    1264   839993194 :         if (ret == NDR_ERR_RANGE) {
    1265           0 :                 return ndr_pull_error(ndr, ret,
    1266             :                                       "More than %d NDR tokens stored for switch_list",
    1267             :                                       NDR_TOKEN_MAX_LIST_SIZE);
    1268             :         }
    1269   819068103 :         return ret;
    1270             : }
    1271             : 
    1272       28284 : _PUBLIC_ enum ndr_err_code ndr_print_set_switch_value(struct ndr_print *ndr, const void *p, uint32_t val)
    1273             : {
    1274       28284 :         return ndr_token_store(ndr, &ndr->switch_list, p, val);
    1275             : }
    1276             : 
    1277             : /* retrieve a switch value (for push) and remove it from the list */
    1278   143015912 : _PUBLIC_ enum ndr_err_code ndr_push_steal_switch_value(struct ndr_push *ndr,
    1279             :                                                        const void *p,
    1280             :                                                        uint32_t *v)
    1281             : {
    1282   143015912 :         return ndr_token_retrieve(&ndr->switch_list, p, v);
    1283             : }
    1284             : 
    1285             : /* retrieve a switch value and remove it from the list */
    1286       28284 : _PUBLIC_ uint32_t ndr_print_steal_switch_value(struct ndr_print *ndr, const void *p)
    1287             : {
    1288        2822 :         enum ndr_err_code status;
    1289        2822 :         uint32_t v;
    1290             : 
    1291       28284 :         status = ndr_token_retrieve(&ndr->switch_list, p, &v);
    1292       28284 :         if (!NDR_ERR_CODE_IS_SUCCESS(status)) {
    1293           0 :                 return 0;
    1294             :         }
    1295             : 
    1296       28284 :         return v;
    1297             : }
    1298             : 
    1299             : /* retrieve a switch value and remove it from the list */
    1300   573806625 : _PUBLIC_ enum ndr_err_code ndr_pull_steal_switch_value(struct ndr_pull *ndr,
    1301             :                                                        const void *p,
    1302             :                                                        uint32_t *v)
    1303             : {
    1304   573806625 :         return ndr_token_retrieve(&ndr->switch_list, p, v);
    1305             : }
    1306             : 
    1307             : /*
    1308             :   pull a struct from a blob using NDR
    1309             : */
    1310    89397514 : _PUBLIC_ enum ndr_err_code ndr_pull_struct_blob(const DATA_BLOB *blob, TALLOC_CTX *mem_ctx, void *p,
    1311             :                               ndr_pull_flags_fn_t fn)
    1312             : {
    1313      667530 :         struct ndr_pull *ndr;
    1314    89397514 :         ndr = ndr_pull_init_blob(blob, mem_ctx);
    1315    89397514 :         NDR_ERR_HAVE_NO_MEMORY(ndr);
    1316    89397514 :         NDR_CHECK_FREE(fn(ndr, NDR_SCALARS|NDR_BUFFERS, p));
    1317    89397425 :         talloc_free(ndr);
    1318    89397425 :         return NDR_ERR_SUCCESS;
    1319             : }
    1320             : 
    1321             : /*
    1322             :   pull a struct from a blob using NDR - failing if all bytes are not consumed
    1323             : */
    1324     9960393 : _PUBLIC_ enum ndr_err_code ndr_pull_struct_blob_all(const DATA_BLOB *blob, TALLOC_CTX *mem_ctx,
    1325             :                                                     void *p, ndr_pull_flags_fn_t fn)
    1326             : {
    1327      335122 :         struct ndr_pull *ndr;
    1328      335122 :         uint32_t highest_ofs;
    1329     9960393 :         ndr = ndr_pull_init_blob(blob, mem_ctx);
    1330     9960393 :         NDR_ERR_HAVE_NO_MEMORY(ndr);
    1331     9960393 :         NDR_CHECK_FREE(fn(ndr, NDR_SCALARS|NDR_BUFFERS, p));
    1332     9960385 :         if (ndr->offset > ndr->relative_highest_offset) {
    1333     9075264 :                 highest_ofs = ndr->offset;
    1334             :         } else {
    1335      550000 :                 highest_ofs = ndr->relative_highest_offset;
    1336             :         }
    1337     9960385 :         if (highest_ofs < ndr->data_size) {
    1338          10 :                 enum ndr_err_code ret;
    1339         165 :                 ret = ndr_pull_error(ndr, NDR_ERR_UNREAD_BYTES,
    1340             :                                      "not all bytes consumed ofs[%"PRIu32"] size[%"PRIu32"]",
    1341             :                                      highest_ofs, ndr->data_size);
    1342         165 :                 talloc_free(ndr);
    1343         165 :                 return ret;
    1344             :         }
    1345     9960220 :         talloc_free(ndr);
    1346     9960220 :         return NDR_ERR_SUCCESS;
    1347             : }
    1348             : 
    1349             : /*
    1350             :  * pull a struct from a blob using NDR
    1351             :  *
    1352             :  * This only works for structures with NO allocated memory, like
    1353             :  * objectSID and GUID.  This helps because we parse these a lot.
    1354             :  */
    1355   254741123 : _PUBLIC_ enum ndr_err_code ndr_pull_struct_blob_noalloc(const uint8_t *buf,
    1356             :                                                         size_t buflen,
    1357             :                                                         void *p,
    1358             :                                                         ndr_pull_flags_fn_t fn,
    1359             :                                                         size_t *consumed)
    1360             : {
    1361             :         /*
    1362             :          * We init this structure on the stack here, to avoid a
    1363             :          * talloc() as otherwise this call to the fn() is assured not
    1364             :          * to be doing any allocation, eg SIDs and GUIDs.
    1365             :          *
    1366             :          * This allows us to keep the safety of the PIDL-generated
    1367             :          * code without the talloc() overhead.
    1368             :          */
    1369   254741123 :         struct ndr_pull ndr = {
    1370             :                 .data = discard_const_p(uint8_t, buf),
    1371             :                 .data_size = buflen,
    1372             :                 .current_mem_ctx = (void *)-1,
    1373             :         };
    1374             : 
    1375   254741123 :         NDR_CHECK(fn(&ndr, NDR_SCALARS|NDR_BUFFERS, p));
    1376   254740686 :         *consumed = MAX(ndr.offset, ndr.relative_highest_offset);
    1377             : 
    1378   254740686 :         return NDR_ERR_SUCCESS;
    1379             : }
    1380             : 
    1381             : /*
    1382             :   pull a struct from a blob using NDR - failing if all bytes are not consumed
    1383             : 
    1384             :   This only works for structures with NO allocated memory, like
    1385             :   objectSID and GUID.  This helps because we parse these a lot.
    1386             : */
    1387             : _PUBLIC_ enum ndr_err_code
    1388   254739674 : ndr_pull_struct_blob_all_noalloc(const DATA_BLOB *blob,
    1389             :                                  void *p,
    1390             :                                  ndr_pull_flags_fn_t fn)
    1391             : {
    1392     5682100 :         size_t consumed;
    1393     5682100 :         enum ndr_err_code ndr_err;
    1394             : 
    1395   260421774 :         ndr_err = ndr_pull_struct_blob_noalloc(blob->data,
    1396   254739674 :                                                blob->length,
    1397             :                                                p,
    1398             :                                                fn,
    1399             :                                                &consumed);
    1400   254739674 :         if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
    1401         434 :                 return ndr_err;
    1402             :         }
    1403             : 
    1404   254739237 :         if (consumed < blob->length) {
    1405           0 :                 D_WARNING("not all bytes consumed ofs[%zu] size[%zu]",
    1406             :                           consumed,
    1407             :                           blob->length);
    1408           0 :                 return NDR_ERR_UNREAD_BYTES;
    1409             :         }
    1410             : 
    1411   249057140 :         return NDR_ERR_SUCCESS;
    1412             : }
    1413             : 
    1414             : /*
    1415             :   pull a union from a blob using NDR, given the union discriminator
    1416             : */
    1417      409919 : _PUBLIC_ enum ndr_err_code ndr_pull_union_blob(const DATA_BLOB *blob, TALLOC_CTX *mem_ctx,
    1418             :                                                void *p,
    1419             :                              uint32_t level, ndr_pull_flags_fn_t fn)
    1420             : {
    1421        7389 :         struct ndr_pull *ndr;
    1422      409919 :         ndr = ndr_pull_init_blob(blob, mem_ctx);
    1423      409919 :         NDR_ERR_HAVE_NO_MEMORY(ndr);
    1424      409919 :         NDR_CHECK_FREE(ndr_pull_set_switch_value(ndr, p, level));
    1425      409919 :         NDR_CHECK_FREE(fn(ndr, NDR_SCALARS|NDR_BUFFERS, p));
    1426      409919 :         talloc_free(ndr);
    1427      409919 :         return NDR_ERR_SUCCESS;
    1428             : }
    1429             : 
    1430             : /*
    1431             :   pull a union from a blob using NDR, given the union discriminator,
    1432             :   failing if all bytes are not consumed
    1433             : */
    1434           3 : _PUBLIC_ enum ndr_err_code ndr_pull_union_blob_all(const DATA_BLOB *blob, TALLOC_CTX *mem_ctx,
    1435             :                                                    void *p,
    1436             :                              uint32_t level, ndr_pull_flags_fn_t fn)
    1437             : {
    1438           0 :         struct ndr_pull *ndr;
    1439           0 :         uint32_t highest_ofs;
    1440           3 :         ndr = ndr_pull_init_blob(blob, mem_ctx);
    1441           3 :         NDR_ERR_HAVE_NO_MEMORY(ndr);
    1442           3 :         NDR_CHECK_FREE(ndr_pull_set_switch_value(ndr, p, level));
    1443           3 :         NDR_CHECK_FREE(fn(ndr, NDR_SCALARS|NDR_BUFFERS, p));
    1444           3 :         if (ndr->offset > ndr->relative_highest_offset) {
    1445           3 :                 highest_ofs = ndr->offset;
    1446             :         } else {
    1447           0 :                 highest_ofs = ndr->relative_highest_offset;
    1448             :         }
    1449           3 :         if (highest_ofs < ndr->data_size) {
    1450           0 :                 enum ndr_err_code ret;
    1451           0 :                 ret = ndr_pull_error(ndr, NDR_ERR_UNREAD_BYTES,
    1452             :                                      "not all bytes consumed ofs[%"PRIu32"] size[%"PRIu32"]",
    1453             :                                      highest_ofs, ndr->data_size);
    1454           0 :                 talloc_free(ndr);
    1455           0 :                 return ret;
    1456             :         }
    1457           3 :         talloc_free(ndr);
    1458           3 :         return NDR_ERR_SUCCESS;
    1459             : }
    1460             : 
    1461             : /*
    1462             :   push a struct to a blob using NDR
    1463             : */
    1464    61949185 : _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)
    1465             : {
    1466      408741 :         struct ndr_push *ndr;
    1467    61949185 :         ndr = ndr_push_init_ctx(mem_ctx);
    1468    61949185 :         NDR_ERR_HAVE_NO_MEMORY(ndr);
    1469             : 
    1470    61949185 :         NDR_CHECK_FREE(fn(ndr, NDR_SCALARS|NDR_BUFFERS, p));
    1471             : 
    1472    61949173 :         *blob = ndr_push_blob(ndr);
    1473    61949173 :         talloc_steal(mem_ctx, blob->data);
    1474    61949173 :         talloc_free(ndr);
    1475             : 
    1476    61949173 :         return NDR_ERR_SUCCESS;
    1477             : }
    1478             : 
    1479             : /*
    1480             :   push a struct into a provided blob using NDR.
    1481             : 
    1482             :   We error because we want to have the performance issue (extra
    1483             :   talloc() calls) show up as an error, not just slower code.  This is
    1484             :   used for things like GUIDs, which we expect to be a fixed size, and
    1485             :   SIDs that we can pre-calculate the size for.
    1486             : */
    1487   151375034 : _PUBLIC_ enum ndr_err_code ndr_push_struct_into_fixed_blob(
    1488             :         DATA_BLOB *blob, const void *p, ndr_push_flags_fn_t fn)
    1489             : {
    1490   151375034 :         struct ndr_push ndr = {
    1491   151375034 :                 .data = blob->data,
    1492   151375034 :                 .alloc_size = blob->length,
    1493             :                 .fixed_buf_size = true
    1494             :         };
    1495             : 
    1496   151375034 :         NDR_CHECK(fn(&ndr, NDR_SCALARS|NDR_BUFFERS, p));
    1497             : 
    1498   151375032 :         if (ndr.offset != blob->length) {
    1499           2 :                 return ndr_push_error(&ndr, NDR_ERR_BUFSIZE,
    1500             :                                       "buffer was either too large or small "
    1501             :                                       "ofs[%"PRIu32"] size[%zu]",
    1502             :                                       ndr.offset, blob->length);
    1503             :         }
    1504             : 
    1505   149605868 :         return NDR_ERR_SUCCESS;
    1506             : }
    1507             : 
    1508             : /*
    1509             :   push a union to a blob using NDR
    1510             : */
    1511      274696 : _PUBLIC_ enum ndr_err_code ndr_push_union_blob(DATA_BLOB *blob, TALLOC_CTX *mem_ctx, void *p,
    1512             :                              uint32_t level, ndr_push_flags_fn_t fn)
    1513             : {
    1514        8888 :         struct ndr_push *ndr;
    1515      274696 :         ndr = ndr_push_init_ctx(mem_ctx);
    1516      274696 :         NDR_ERR_HAVE_NO_MEMORY(ndr);
    1517             : 
    1518      274696 :         NDR_CHECK_FREE(ndr_push_set_switch_value(ndr, p, level));
    1519      274696 :         NDR_CHECK_FREE(fn(ndr, NDR_SCALARS|NDR_BUFFERS, p));
    1520             : 
    1521      274696 :         *blob = ndr_push_blob(ndr);
    1522      274696 :         talloc_steal(mem_ctx, blob->data);
    1523      274696 :         talloc_free(ndr);
    1524             : 
    1525      274696 :         return NDR_ERR_SUCCESS;
    1526             : }
    1527             : 
    1528             : /*
    1529             :   generic ndr_size_*() handler for structures
    1530             : */
    1531    13588077 : _PUBLIC_ size_t ndr_size_struct(const void *p, libndr_flags flags, ndr_push_flags_fn_t push)
    1532             : {
    1533        4398 :         struct ndr_push *ndr;
    1534        4398 :         enum ndr_err_code status;
    1535        4398 :         size_t ret;
    1536             : 
    1537             :         /* avoid recursion */
    1538    13588077 :         if (flags & LIBNDR_FLAG_NO_NDR_SIZE) return 0;
    1539             : 
    1540             :         /* Avoid following a NULL pointer */
    1541     5754689 :         if (p == NULL) {
    1542           0 :                 return 0;
    1543             :         }
    1544             : 
    1545     5754687 :         ndr = ndr_push_init_ctx(NULL);
    1546     5754687 :         if (!ndr) return 0;
    1547     5754687 :         ndr->flags |= flags | LIBNDR_FLAG_NO_NDR_SIZE;
    1548     5754687 :         status = push(ndr, NDR_SCALARS|NDR_BUFFERS, discard_const(p));
    1549     5754687 :         if (!NDR_ERR_CODE_IS_SUCCESS(status)) {
    1550           0 :                 talloc_free(ndr);
    1551           0 :                 return 0;
    1552             :         }
    1553     5754687 :         ret = ndr->offset;
    1554     5754687 :         talloc_free(ndr);
    1555     5754687 :         return ret;
    1556             : }
    1557             : 
    1558             : /*
    1559             :   generic ndr_size_*() handler for unions
    1560             : */
    1561     2374898 : _PUBLIC_ size_t ndr_size_union(const void *p, libndr_flags flags, uint32_t level, ndr_push_flags_fn_t push)
    1562             : {
    1563        9673 :         struct ndr_push *ndr;
    1564        9673 :         enum ndr_err_code status;
    1565        9673 :         size_t ret;
    1566             : 
    1567             :         /* avoid recursion */
    1568     2374898 :         if (flags & LIBNDR_FLAG_NO_NDR_SIZE) return 0;
    1569             : 
    1570             :         /* Avoid following a NULL pointer */
    1571     2374898 :         if (p == NULL) {
    1572           0 :                 return 0;
    1573             :         }
    1574             : 
    1575     2374897 :         ndr = ndr_push_init_ctx(NULL);
    1576     2374897 :         if (!ndr) return 0;
    1577     2374897 :         ndr->flags |= flags | LIBNDR_FLAG_NO_NDR_SIZE;
    1578             : 
    1579     2374897 :         status = ndr_push_set_switch_value(ndr, p, level);
    1580     2374897 :         if (!NDR_ERR_CODE_IS_SUCCESS(status)) {
    1581           0 :                 talloc_free(ndr);
    1582           0 :                 return 0;
    1583             :         }
    1584     2374897 :         status = push(ndr, NDR_SCALARS|NDR_BUFFERS, p);
    1585     2374897 :         if (!NDR_ERR_CODE_IS_SUCCESS(status)) {
    1586         264 :                 talloc_free(ndr);
    1587         264 :                 return 0;
    1588             :         }
    1589     2374633 :         ret = ndr->offset;
    1590     2374633 :         talloc_free(ndr);
    1591     2374633 :         return ret;
    1592             : }
    1593             : 
    1594             : /*
    1595             :   get the current base for relative pointers for the push
    1596             : */
    1597      239717 : _PUBLIC_ uint32_t ndr_push_get_relative_base_offset(struct ndr_push *ndr)
    1598             : {
    1599      239717 :         return ndr->relative_base_offset;
    1600             : }
    1601             : 
    1602             : /*
    1603             :   restore the old base for relative pointers for the push
    1604             : */
    1605      239717 : _PUBLIC_ void ndr_push_restore_relative_base_offset(struct ndr_push *ndr, uint32_t offset)
    1606             : {
    1607      239717 :         ndr->relative_base_offset = offset;
    1608      239717 : }
    1609             : 
    1610             : /*
    1611             :   setup the current base for relative pointers for the push
    1612             :   called in the NDR_SCALAR stage
    1613             : */
    1614      126841 : _PUBLIC_ enum ndr_err_code ndr_push_setup_relative_base_offset1(struct ndr_push *ndr, const void *p, uint32_t offset)
    1615             : {
    1616          12 :         enum ndr_err_code ret;
    1617      126841 :         ndr->relative_base_offset = offset;
    1618      126841 :         ret = ndr_token_store(ndr, &ndr->relative_base_list, p, offset);
    1619      126841 :         if (ret == NDR_ERR_RANGE) {
    1620           0 :                 return ndr_push_error(ndr, ret,
    1621             :                                       "More than %d NDR tokens stored for relative_base_list",
    1622             :                                       NDR_TOKEN_MAX_LIST_SIZE);
    1623             :         }
    1624      126829 :         return ret;
    1625             : }
    1626             : 
    1627             : /*
    1628             :   setup the current base for relative pointers for the push
    1629             :   called in the NDR_BUFFERS stage
    1630             : */
    1631      126529 : _PUBLIC_ enum ndr_err_code ndr_push_setup_relative_base_offset2(struct ndr_push *ndr, const void *p)
    1632             : {
    1633      126529 :         return ndr_token_retrieve(&ndr->relative_base_list, p, &ndr->relative_base_offset);
    1634             : }
    1635             : 
    1636             : /*
    1637             :   push a relative object - stage1
    1638             :   this is called during SCALARS processing
    1639             : */
    1640    21442707 : _PUBLIC_ enum ndr_err_code ndr_push_relative_ptr1(struct ndr_push *ndr, const void *p)
    1641             : {
    1642      845230 :         enum ndr_err_code ret;
    1643    21442707 :         if (p == NULL) {
    1644     2359246 :                 NDR_CHECK(ndr_push_uint32(ndr, NDR_SCALARS, 0));
    1645     2359246 :                 return NDR_ERR_SUCCESS;
    1646             :         }
    1647    19083461 :         NDR_CHECK(ndr_push_align(ndr, 4));
    1648    19083461 :         ret = ndr_token_store(ndr, &ndr->relative_list, p, ndr->offset);
    1649    19083461 :         if (ret == NDR_ERR_RANGE) {
    1650           0 :                 return ndr_push_error(ndr, ret,
    1651             :                                       "More than %d NDR tokens stored for relative_list",
    1652             :                                       NDR_TOKEN_MAX_LIST_SIZE);
    1653             :         }
    1654    19083461 :         NDR_CHECK(ret);
    1655    19083461 :         return ndr_push_uint32(ndr, NDR_SCALARS, 0xFFFFFFFF);
    1656             : }
    1657             : 
    1658             : /*
    1659             :   push a short relative object - stage1
    1660             :   this is called during SCALARS processing
    1661             : */
    1662      194730 : _PUBLIC_ enum ndr_err_code ndr_push_short_relative_ptr1(struct ndr_push *ndr, const void *p)
    1663             : {
    1664        4770 :         enum ndr_err_code ret;
    1665      194730 :         if (p == NULL) {
    1666         102 :                 NDR_CHECK(ndr_push_uint16(ndr, NDR_SCALARS, 0));
    1667         102 :                 return NDR_ERR_SUCCESS;
    1668             :         }
    1669      194628 :         NDR_CHECK(ndr_push_align(ndr, 2));
    1670      194628 :         ret = ndr_token_store(ndr, &ndr->relative_list, p, ndr->offset);
    1671      194628 :         if (ret == NDR_ERR_RANGE) {
    1672           0 :                 return ndr_push_error(ndr, ret,
    1673             :                                       "More than %d NDR tokens stored for relative_list",
    1674             :                                       NDR_TOKEN_MAX_LIST_SIZE);
    1675             :         }
    1676      194628 :         NDR_CHECK(ret);
    1677      194628 :         return ndr_push_uint16(ndr, NDR_SCALARS, 0xFFFF);
    1678             : }
    1679             : /*
    1680             :   push a relative object - stage2
    1681             :   this is called during buffers processing
    1682             : */
    1683    18991895 : static enum ndr_err_code ndr_push_relative_ptr2(struct ndr_push *ndr, const void *p)
    1684             : {
    1685      727399 :         uint32_t save_offset;
    1686    18991895 :         uint32_t ptr_offset = 0xFFFFFFFF;
    1687    18991895 :         if (p == NULL) {
    1688           0 :                 return NDR_ERR_SUCCESS;
    1689             :         }
    1690    18991895 :         save_offset = ndr->offset;
    1691    18991895 :         NDR_CHECK(ndr_token_retrieve(&ndr->relative_list, p, &ptr_offset));
    1692    18991895 :         if (ptr_offset > ndr->offset) {
    1693           0 :                 return ndr_push_error(ndr, NDR_ERR_BUFSIZE,
    1694             :                                       "ndr_push_relative_ptr2 ptr_offset(%"PRIu32") > ndr->offset(%"PRIu32")",
    1695             :                                       ptr_offset, ndr->offset);
    1696             :         }
    1697    18991895 :         ndr->offset = ptr_offset;
    1698    18991895 :         if (save_offset < ndr->relative_base_offset) {
    1699           0 :                 return ndr_push_error(ndr, NDR_ERR_BUFSIZE,
    1700             :                                       "ndr_push_relative_ptr2 save_offset(%"PRIu32") < ndr->relative_base_offset(%"PRIu32")",
    1701             :                                       save_offset, ndr->relative_base_offset);
    1702             :         }
    1703    18991895 :         NDR_CHECK(ndr_push_uint32(ndr, NDR_SCALARS, save_offset - ndr->relative_base_offset));
    1704    18991895 :         ndr->offset = save_offset;
    1705    18991895 :         return NDR_ERR_SUCCESS;
    1706             : }
    1707             : /*
    1708             :   push a short relative object - stage2
    1709             :   this is called during buffers processing
    1710             : */
    1711      194628 : _PUBLIC_ enum ndr_err_code ndr_push_short_relative_ptr2(struct ndr_push *ndr, const void *p)
    1712             : {
    1713        4762 :         uint32_t save_offset;
    1714      194628 :         uint32_t ptr_offset = 0xFFFF;
    1715        4762 :         uint32_t relative_offset;
    1716        4762 :         size_t pad;
    1717      194628 :         size_t align = 1;
    1718             : 
    1719      194628 :         if (p == NULL) {
    1720           0 :                 return NDR_ERR_SUCCESS;
    1721             :         }
    1722             : 
    1723      194628 :         if (ndr->offset < ndr->relative_base_offset) {
    1724           0 :                 return ndr_push_error(ndr, NDR_ERR_BUFSIZE,
    1725             :                                       "ndr_push_relative_ptr2 ndr->offset(%"PRIu32") < ndr->relative_base_offset(%"PRIu32")",
    1726             :                                       ndr->offset, ndr->relative_base_offset);
    1727             :         }
    1728             : 
    1729      194628 :         relative_offset = ndr->offset - ndr->relative_base_offset;
    1730             : 
    1731      194628 :         if (ndr->flags & LIBNDR_FLAG_NOALIGN) {
    1732         152 :                 align = 1;
    1733      194460 :         } else if (ndr->flags & LIBNDR_FLAG_ALIGN2) {
    1734       30462 :                 align = 2;
    1735      163996 :         } else if (ndr->flags & LIBNDR_FLAG_ALIGN4) {
    1736           0 :                 align = 4;
    1737      163996 :         } else if (ndr->flags & LIBNDR_FLAG_ALIGN8) {
    1738      132807 :                 align = 8;
    1739             :         }
    1740             : 
    1741      194628 :         pad = ndr_align_size(relative_offset, align);
    1742      194628 :         if (pad != 0) {
    1743      124959 :                 NDR_CHECK(ndr_push_zero(ndr, pad));
    1744             :         }
    1745             : 
    1746      194628 :         relative_offset = ndr->offset - ndr->relative_base_offset;
    1747      194628 :         if (relative_offset > UINT16_MAX) {
    1748           0 :                 return ndr_push_error(ndr, NDR_ERR_BUFSIZE,
    1749             :                                       "ndr_push_relative_ptr2 relative_offset(%"PRIu32") > UINT16_MAX",
    1750             :                                       relative_offset);
    1751             :         }
    1752             : 
    1753      194628 :         save_offset = ndr->offset;
    1754      194628 :         NDR_CHECK(ndr_token_retrieve(&ndr->relative_list, p, &ptr_offset));
    1755      194628 :         if (ptr_offset > ndr->offset) {
    1756           0 :                 return ndr_push_error(ndr, NDR_ERR_BUFSIZE,
    1757             :                                       "ndr_push_short_relative_ptr2 ptr_offset(%"PRIu32") > ndr->offset(%"PRIu32")",
    1758             :                                       ptr_offset, ndr->offset);
    1759             :         }
    1760      194628 :         ndr->offset = ptr_offset;
    1761      194628 :         NDR_CHECK(ndr_push_uint16(ndr, NDR_SCALARS, relative_offset));
    1762      194628 :         ndr->offset = save_offset;
    1763      194628 :         return NDR_ERR_SUCCESS;
    1764             : }
    1765             : 
    1766             : /*
    1767             :   push a relative object - stage2 start
    1768             :   this is called during buffers processing
    1769             : */
    1770    19083461 : _PUBLIC_ enum ndr_err_code ndr_push_relative_ptr2_start(struct ndr_push *ndr, const void *p)
    1771             : {
    1772      727399 :         enum ndr_err_code ret;
    1773    19083461 :         if (p == NULL) {
    1774           0 :                 return NDR_ERR_SUCCESS;
    1775             :         }
    1776    19083461 :         if (!(ndr->flags & LIBNDR_FLAG_RELATIVE_REVERSE)) {
    1777      727399 :                 uint32_t relative_offset;
    1778      727399 :                 size_t pad;
    1779    18946387 :                 size_t align = 1;
    1780             : 
    1781    18946387 :                 if (ndr->offset < ndr->relative_base_offset) {
    1782           0 :                         return ndr_push_error(ndr, NDR_ERR_BUFSIZE,
    1783             :                                       "ndr_push_relative_ptr2_start ndr->offset(%"PRIu32") < ndr->relative_base_offset(%"PRIu32")",
    1784             :                                       ndr->offset, ndr->relative_base_offset);
    1785             :                 }
    1786             : 
    1787    18946387 :                 relative_offset = ndr->offset - ndr->relative_base_offset;
    1788             : 
    1789    18946387 :                 if (ndr->flags & LIBNDR_FLAG_NOALIGN) {
    1790           0 :                         align = 1;
    1791    18942547 :                 } else if (ndr->flags & LIBNDR_FLAG_ALIGN2) {
    1792        8820 :                         align = 2;
    1793    18928464 :                 } else if (ndr->flags & LIBNDR_FLAG_ALIGN4) {
    1794        6996 :                         align = 4;
    1795    18921468 :                 } else if (ndr->flags & LIBNDR_FLAG_ALIGN8) {
    1796      156892 :                         align = 8;
    1797             :                 }
    1798             : 
    1799    18946387 :                 pad = ndr_align_size(relative_offset, align);
    1800    18946387 :                 if (pad) {
    1801         680 :                         NDR_CHECK(ndr_push_zero(ndr, pad));
    1802             :                 }
    1803             : 
    1804    18946387 :                 return ndr_push_relative_ptr2(ndr, p);
    1805             :         }
    1806      137074 :         if (ndr->relative_end_offset == -1) {
    1807           0 :                 return ndr_push_error(ndr, NDR_ERR_RELATIVE,
    1808             :                               "ndr_push_relative_ptr2_start RELATIVE_REVERSE flag set and relative_end_offset %"PRIu32,
    1809             :                               ndr->relative_end_offset);
    1810             :         }
    1811      137074 :         ret = ndr_token_store(ndr,
    1812             :                               &ndr->relative_begin_list,
    1813             :                               p,
    1814             :                               ndr->offset);
    1815      137074 :         if (ret == NDR_ERR_RANGE) {
    1816           0 :                 return ndr_push_error(ndr, ret,
    1817             :                                       "More than %d NDR tokens stored for array_size",
    1818             :                                       NDR_TOKEN_MAX_LIST_SIZE);
    1819             :         }
    1820      137074 :         return ret;
    1821             : }
    1822             : 
    1823             : /*
    1824             :   push a relative object - stage2 end
    1825             :   this is called during buffers processing
    1826             : */
    1827    19083461 : _PUBLIC_ enum ndr_err_code ndr_push_relative_ptr2_end(struct ndr_push *ndr, const void *p)
    1828             : {
    1829    19083461 :         uint32_t begin_offset = 0xFFFFFFFF;
    1830      727399 :         ssize_t len;
    1831    19083461 :         uint32_t correct_offset = 0;
    1832    19083461 :         uint32_t align = 1;
    1833    19083461 :         uint32_t pad = 0;
    1834             : 
    1835    19083461 :         if (p == NULL) {
    1836           0 :                 return NDR_ERR_SUCCESS;
    1837             :         }
    1838             : 
    1839    19083461 :         if (!(ndr->flags & LIBNDR_FLAG_RELATIVE_REVERSE)) {
    1840    18218988 :                 return NDR_ERR_SUCCESS;
    1841             :         }
    1842             : 
    1843      137074 :         if (ndr->flags & LIBNDR_FLAG_NO_NDR_SIZE) {
    1844             :                 /* better say more than calculation a too small buffer */
    1845      363342 :                 NDR_PUSH_ALIGN(ndr, 8);
    1846       91566 :                 return NDR_ERR_SUCCESS;
    1847             :         }
    1848             : 
    1849       45508 :         if (ndr->relative_end_offset < ndr->offset) {
    1850           0 :                 return ndr_push_error(ndr, NDR_ERR_RELATIVE,
    1851             :                                       "ndr_push_relative_ptr2_end:"
    1852             :                                       "relative_end_offset %"PRIu32" < offset %"PRIu32,
    1853             :                                       ndr->relative_end_offset, ndr->offset);
    1854             :         }
    1855             : 
    1856       45508 :         NDR_CHECK(ndr_token_retrieve(&ndr->relative_begin_list, p, &begin_offset));
    1857             : 
    1858             :         /* we have marshalled a buffer, see how long it was */
    1859       45508 :         len = ndr->offset - begin_offset;
    1860             : 
    1861       45508 :         if (len < 0) {
    1862           0 :                 return ndr_push_error(ndr, NDR_ERR_RELATIVE,
    1863             :                                       "ndr_push_relative_ptr2_end:"
    1864             :                                       "offset %"PRIu32" - begin_offset %"PRIu32" < 0",
    1865             :                                       ndr->offset, begin_offset);
    1866             :         }
    1867             : 
    1868       45508 :         if (ndr->relative_end_offset < len) {
    1869           0 :                 return ndr_push_error(ndr, NDR_ERR_RELATIVE,
    1870             :                                       "ndr_push_relative_ptr2_end:"
    1871             :                                       "relative_end_offset %"PRIu32" < len %zd",
    1872             :                                       ndr->offset, len);
    1873             :         }
    1874             : 
    1875             :         /* the reversed offset is at the end of the main buffer */
    1876       45508 :         correct_offset = ndr->relative_end_offset - len;
    1877             : 
    1878       45508 :         if (ndr->flags & LIBNDR_FLAG_NOALIGN) {
    1879           0 :                 align = 1;
    1880       45508 :         } else if (ndr->flags & LIBNDR_FLAG_ALIGN2) {
    1881       36956 :                 align = 2;
    1882        8552 :         } else if (ndr->flags & LIBNDR_FLAG_ALIGN4) {
    1883        2140 :                 align = 4;
    1884        6412 :         } else if (ndr->flags & LIBNDR_FLAG_ALIGN8) {
    1885           0 :                 align = 8;
    1886             :         }
    1887             : 
    1888       45508 :         pad = ndr_align_size(correct_offset, align);
    1889       45508 :         if (pad) {
    1890        1076 :                 correct_offset += pad;
    1891        1076 :                 correct_offset -= align;
    1892             :         }
    1893             : 
    1894       45508 :         if (correct_offset < begin_offset) {
    1895           0 :                 return ndr_push_error(ndr, NDR_ERR_RELATIVE,
    1896             :                                       "ndr_push_relative_ptr2_end: "
    1897             :                                       "correct_offset %"PRIu32" < begin_offset %"PRIu32,
    1898             :                                       correct_offset, begin_offset);
    1899             :         }
    1900             : 
    1901       45508 :         if (len > 0) {
    1902       45508 :                 uint32_t clear_size = correct_offset - begin_offset;
    1903             : 
    1904       45508 :                 clear_size = MIN(clear_size, len);
    1905             : 
    1906             :                 /* now move the marshalled buffer to the end of the main buffer */
    1907       45508 :                 memmove(ndr->data + correct_offset, ndr->data + begin_offset, len);
    1908             : 
    1909       45508 :                 if (clear_size) {
    1910             :                         /* and wipe out old buffer within the main buffer */
    1911       43848 :                         memset(ndr->data + begin_offset, '\0', clear_size);
    1912             :                 }
    1913             :         }
    1914             : 
    1915             :         /* and set the end offset for the next buffer */
    1916       45508 :         ndr->relative_end_offset = correct_offset;
    1917             : 
    1918             :         /* finally write the offset to the main buffer */
    1919       45508 :         ndr->offset = correct_offset;
    1920       45508 :         NDR_CHECK(ndr_push_relative_ptr2(ndr, p));
    1921             : 
    1922             :         /* restore to where we were in the main buffer */
    1923       45508 :         ndr->offset = begin_offset;
    1924             : 
    1925       45508 :         return NDR_ERR_SUCCESS;
    1926             : }
    1927             : 
    1928             : /*
    1929             :   get the current base for relative pointers for the pull
    1930             : */
    1931       73387 : _PUBLIC_ uint32_t ndr_pull_get_relative_base_offset(struct ndr_pull *ndr)
    1932             : {
    1933       73387 :         return ndr->relative_base_offset;
    1934             : }
    1935             : 
    1936             : /*
    1937             :   restore the old base for relative pointers for the pull
    1938             : */
    1939       73387 : _PUBLIC_ void ndr_pull_restore_relative_base_offset(struct ndr_pull *ndr, uint32_t offset)
    1940             : {
    1941       73387 :         ndr->relative_base_offset = offset;
    1942       73387 : }
    1943             : 
    1944             : /*
    1945             :   setup the current base for relative pointers for the pull
    1946             :   called in the NDR_SCALAR stage
    1947             : */
    1948       38775 : _PUBLIC_ enum ndr_err_code ndr_pull_setup_relative_base_offset1(struct ndr_pull *ndr, const void *p, uint32_t offset)
    1949             : {
    1950          65 :         enum ndr_err_code ret;
    1951       38775 :         ndr->relative_base_offset = offset;
    1952       38775 :         ret = ndr_token_store(ndr, &ndr->relative_base_list, p, offset);
    1953       38775 :         if (ret == NDR_ERR_RANGE) {
    1954           0 :                 return ndr_pull_error(ndr, ret,
    1955             :                                       "More than %d NDR tokens stored for relative_base_list",
    1956             :                                       NDR_TOKEN_MAX_LIST_SIZE);
    1957             :         }
    1958       38710 :         return ret;
    1959             : }
    1960             : 
    1961             : /*
    1962             :   setup the current base for relative pointers for the pull
    1963             :   called in the NDR_BUFFERS stage
    1964             : */
    1965       38669 : _PUBLIC_ enum ndr_err_code ndr_pull_setup_relative_base_offset2(struct ndr_pull *ndr, const void *p)
    1966             : {
    1967       38669 :         return ndr_token_retrieve(&ndr->relative_base_list, p, &ndr->relative_base_offset);
    1968             : }
    1969             : 
    1970             : /*
    1971             :   pull a relative object - stage1
    1972             :   called during SCALARS processing
    1973             : */
    1974    46385510 : _PUBLIC_ enum ndr_err_code ndr_pull_relative_ptr1(struct ndr_pull *ndr, const void *p, uint32_t rel_offset)
    1975             : {
    1976     1962988 :         enum ndr_err_code ret;
    1977    46385510 :         rel_offset += ndr->relative_base_offset;
    1978    46385510 :         if (rel_offset > ndr->data_size) {
    1979           0 :                 return ndr_pull_error(ndr, NDR_ERR_BUFSIZE,
    1980             :                                       "ndr_pull_relative_ptr1 rel_offset(%"PRIu32") > ndr->data_size(%"PRIu32")",
    1981             :                                       rel_offset, ndr->data_size);
    1982             :         }
    1983    46385510 :         ret = ndr_token_store(ndr, &ndr->relative_list, p, rel_offset);
    1984    46385510 :         if (ret == NDR_ERR_RANGE) {
    1985           0 :                 return ndr_pull_error(ndr, ret,
    1986             :                                       "More than %d NDR tokens stored for relative_list",
    1987             :                                       NDR_TOKEN_MAX_LIST_SIZE);
    1988             :         }
    1989    44422522 :         return ret;
    1990             : }
    1991             : 
    1992             : /*
    1993             :   pull a relative object - stage2
    1994             :   called during BUFFERS processing
    1995             : */
    1996    46385510 : _PUBLIC_ enum ndr_err_code ndr_pull_relative_ptr2(struct ndr_pull *ndr, const void *p)
    1997             : {
    1998     1962988 :         uint32_t rel_offset;
    1999    46385510 :         NDR_CHECK(ndr_token_retrieve(&ndr->relative_list, p, &rel_offset));
    2000    46385510 :         return ndr_pull_set_offset(ndr, rel_offset);
    2001             : }
    2002             : 
    2003             : static const struct {
    2004             :         enum ndr_err_code err;
    2005             :         const char *string;
    2006             : } ndr_err_code_strings[] = {
    2007             :         { NDR_ERR_SUCCESS, "Success" },
    2008             :         { NDR_ERR_ARRAY_SIZE, "Bad Array Size" },
    2009             :         { NDR_ERR_BAD_SWITCH, "Bad Switch" },
    2010             :         { NDR_ERR_OFFSET, "Offset Error" },
    2011             :         { NDR_ERR_RELATIVE, "Relative Pointer Error" },
    2012             :         { NDR_ERR_CHARCNV, "Character Conversion Error" },
    2013             :         { NDR_ERR_LENGTH, "Length Error" },
    2014             :         { NDR_ERR_SUBCONTEXT, "Subcontext Error" },
    2015             :         { NDR_ERR_COMPRESSION, "Compression Error" },
    2016             :         { NDR_ERR_STRING, "String Error" },
    2017             :         { NDR_ERR_VALIDATE, "Validate Error" },
    2018             :         { NDR_ERR_BUFSIZE, "Buffer Size Error" },
    2019             :         { NDR_ERR_ALLOC, "Allocation Error" },
    2020             :         { NDR_ERR_RANGE, "Range Error" },
    2021             :         { NDR_ERR_TOKEN, "Token Error" },
    2022             :         { NDR_ERR_IPV4ADDRESS, "IPv4 Address Error" },
    2023             :         { NDR_ERR_INVALID_POINTER, "Invalid Pointer" },
    2024             :         { NDR_ERR_UNREAD_BYTES, "Unread Bytes" },
    2025             :         { NDR_ERR_NDR64, "NDR64 assertion error" },
    2026             :         { NDR_ERR_INCOMPLETE_BUFFER, "Incomplete Buffer" },
    2027             :         { NDR_ERR_MAX_RECURSION_EXCEEDED, "Maximum Recursion Exceeded" },
    2028             :         { NDR_ERR_UNDERFLOW, "Underflow" },
    2029             :         { 0, NULL }
    2030             : };
    2031             : 
    2032        1335 : _PUBLIC_ const char *ndr_map_error2string(enum ndr_err_code ndr_err)
    2033             : {
    2034         102 :         int i;
    2035       20526 :         for (i = 0; ndr_err_code_strings[i].string != NULL; i++) {
    2036       20262 :                 if (ndr_err_code_strings[i].err == ndr_err)
    2037        1071 :                         return ndr_err_code_strings[i].string;
    2038             :         }
    2039         264 :         return "Unknown error";
    2040             : }

Generated by: LCOV version 1.14