librpc/ndr: handle NOALIGN flag for relative pointers and alignment DATA_BLOBs
[garming/samba-autobuild/.git] / librpc / ndr / ndr_basic.c
1 /* 
2    Unix SMB/CIFS implementation.
3
4    routines for marshalling/unmarshalling basic types
5
6    Copyright (C) Andrew Tridgell 2003
7    
8    This program is free software; you can redistribute it and/or modify
9    it under the terms of the GNU General Public License as published by
10    the Free Software Foundation; either version 3 of the License, or
11    (at your option) any later version.
12    
13    This program is distributed in the hope that it will be useful,
14    but WITHOUT ANY WARRANTY; without even the implied warranty of
15    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
16    GNU General Public License for more details.
17    
18    You should have received a copy of the GNU General Public License
19    along with this program.  If not, see <http://www.gnu.org/licenses/>.
20 */
21
22 #include "includes.h"
23 #include "system/network.h"
24 #include "librpc/ndr/libndr.h"
25 #include "lib/util/util_net.h"
26
27 #define NDR_SVAL(ndr, ofs) (NDR_BE(ndr)?RSVAL(ndr->data,ofs):SVAL(ndr->data,ofs))
28 #define NDR_IVAL(ndr, ofs) (NDR_BE(ndr)?RIVAL(ndr->data,ofs):IVAL(ndr->data,ofs))
29 #define NDR_IVALS(ndr, ofs) (NDR_BE(ndr)?RIVALS(ndr->data,ofs):IVALS(ndr->data,ofs))
30 #define NDR_SSVAL(ndr, ofs, v) do { if (NDR_BE(ndr))  { RSSVAL(ndr->data,ofs,v); } else SSVAL(ndr->data,ofs,v); } while (0)
31 #define NDR_SIVAL(ndr, ofs, v) do { if (NDR_BE(ndr))  { RSIVAL(ndr->data,ofs,v); } else SIVAL(ndr->data,ofs,v); } while (0)
32 #define NDR_SIVALS(ndr, ofs, v) do { if (NDR_BE(ndr))  { RSIVALS(ndr->data,ofs,v); } else SIVALS(ndr->data,ofs,v); } while (0)
33
34
35 /*
36   check for data leaks from the server by looking for non-zero pad bytes
37   these could also indicate that real structure elements have been
38   mistaken for padding in the IDL
39 */
40 _PUBLIC_ void ndr_check_padding(struct ndr_pull *ndr, size_t n)
41 {
42         size_t ofs2 = (ndr->offset + (n-1)) & ~(n-1);
43         int i;
44         for (i=ndr->offset;i<ofs2;i++) {
45                 if (ndr->data[i] != 0) {
46                         break;
47                 }
48         }
49         if (i<ofs2) {
50                 DEBUG(0,("WARNING: Non-zero padding to %d: ", (int)n));
51                 for (i=ndr->offset;i<ofs2;i++) {
52                         DEBUG(0,("%02x ", ndr->data[i]));
53                 }
54                 DEBUG(0,("\n"));
55         }
56
57 }
58
59 /*
60   parse a int8_t
61 */
62 _PUBLIC_ enum ndr_err_code ndr_pull_int8(struct ndr_pull *ndr, int ndr_flags, int8_t *v)
63 {
64         NDR_PULL_NEED_BYTES(ndr, 1);
65         *v = (int8_t)CVAL(ndr->data, ndr->offset);
66         ndr->offset += 1;
67         return NDR_ERR_SUCCESS;
68 }
69
70 /*
71   parse a uint8_t
72 */
73 _PUBLIC_ enum ndr_err_code ndr_pull_uint8(struct ndr_pull *ndr, int ndr_flags, uint8_t *v)
74 {
75         NDR_PULL_NEED_BYTES(ndr, 1);
76         *v = CVAL(ndr->data, ndr->offset);
77         ndr->offset += 1;
78         return NDR_ERR_SUCCESS;
79 }
80
81 /*
82   parse a int16_t
83 */
84 _PUBLIC_ enum ndr_err_code ndr_pull_int16(struct ndr_pull *ndr, int ndr_flags, int16_t *v)
85 {
86         NDR_PULL_ALIGN(ndr, 2);
87         NDR_PULL_NEED_BYTES(ndr, 2);
88         *v = (uint16_t)NDR_SVAL(ndr, ndr->offset);
89         ndr->offset += 2;
90         return NDR_ERR_SUCCESS;
91 }
92
93 /*
94   parse a uint16_t
95 */
96 _PUBLIC_ enum ndr_err_code ndr_pull_uint16(struct ndr_pull *ndr, int ndr_flags, uint16_t *v)
97 {
98         NDR_PULL_ALIGN(ndr, 2);
99         NDR_PULL_NEED_BYTES(ndr, 2);
100         *v = NDR_SVAL(ndr, ndr->offset);
101         ndr->offset += 2;
102         return NDR_ERR_SUCCESS;
103 }
104
105 /*
106   parse a uint1632_t
107 */
108 _PUBLIC_ enum ndr_err_code ndr_pull_uint1632(struct ndr_pull *ndr, int ndr_flags, uint16_t *v)
109 {
110         if (unlikely(ndr->flags & LIBNDR_FLAG_NDR64)) {
111                 uint32_t v32 = 0;
112                 enum ndr_err_code err = ndr_pull_uint32(ndr, ndr_flags, &v32);
113                 *v = v32;
114                 if (unlikely(v32 != *v)) {
115                         DEBUG(0,(__location__ ": non-zero upper 16 bits 0x%08x\n", (unsigned)v32));
116                         return NDR_ERR_NDR64;
117                 }
118                 return err;
119         }
120         return ndr_pull_uint16(ndr, ndr_flags, v);
121 }
122
123 /*
124   parse a int32_t
125 */
126 _PUBLIC_ enum ndr_err_code ndr_pull_int32(struct ndr_pull *ndr, int ndr_flags, int32_t *v)
127 {
128         NDR_PULL_ALIGN(ndr, 4);
129         NDR_PULL_NEED_BYTES(ndr, 4);
130         *v = NDR_IVALS(ndr, ndr->offset);
131         ndr->offset += 4;
132         return NDR_ERR_SUCCESS;
133 }
134
135 /*
136   parse a uint32_t
137 */
138 _PUBLIC_ enum ndr_err_code ndr_pull_uint32(struct ndr_pull *ndr, int ndr_flags, uint32_t *v)
139 {
140         NDR_PULL_ALIGN(ndr, 4);
141         NDR_PULL_NEED_BYTES(ndr, 4);
142         *v = NDR_IVAL(ndr, ndr->offset);
143         ndr->offset += 4;
144         return NDR_ERR_SUCCESS;
145 }
146
147 /*
148   parse a arch dependent uint32/uint64
149 */
150 _PUBLIC_ enum ndr_err_code ndr_pull_uint3264(struct ndr_pull *ndr, int ndr_flags, uint32_t *v)
151 {
152         uint64_t v64;
153         enum ndr_err_code err;
154         if (likely(!(ndr->flags & LIBNDR_FLAG_NDR64))) {
155                 return ndr_pull_uint32(ndr, ndr_flags, v);
156         }
157         err = ndr_pull_hyper(ndr, ndr_flags, &v64);
158         *v = (uint32_t)v64;
159         if (unlikely(v64 != *v)) {
160                 DEBUG(0,(__location__ ": non-zero upper 32 bits 0x%016llx\n",
161                          (unsigned long long)v64));
162                 return NDR_ERR_NDR64;
163         }
164         return err;
165 }
166
167 /*
168   parse a double
169 */
170 _PUBLIC_ enum ndr_err_code ndr_pull_double(struct ndr_pull *ndr, int ndr_flags, double *v)
171 {
172         NDR_PULL_ALIGN(ndr, 8);
173         NDR_PULL_NEED_BYTES(ndr, 8);
174         memcpy(v, ndr->data+ndr->offset, 8);
175         ndr->offset += 8;
176         return NDR_ERR_SUCCESS;
177 }
178
179 /*
180   parse a pointer referent identifier stored in 2 bytes
181 */
182 _PUBLIC_ enum ndr_err_code ndr_pull_relative_ptr_short(struct ndr_pull *ndr, uint16_t *v)
183 {
184         NDR_CHECK(ndr_pull_uint16(ndr, NDR_SCALARS, v));
185         if (*v != 0) {
186                 ndr->ptr_count++;
187         }
188         *(v) -= ndr->relative_rap_convert;
189         return NDR_ERR_SUCCESS;
190 }
191
192 /*
193   parse a pointer referent identifier
194 */
195 _PUBLIC_ enum ndr_err_code ndr_pull_generic_ptr(struct ndr_pull *ndr, uint32_t *v)
196 {
197         NDR_CHECK(ndr_pull_uint3264(ndr, NDR_SCALARS, v));
198         if (*v != 0) {
199                 ndr->ptr_count++;
200         }
201         return NDR_ERR_SUCCESS;
202 }
203
204 /*
205   parse a ref pointer referent identifier
206 */
207 _PUBLIC_ enum ndr_err_code ndr_pull_ref_ptr(struct ndr_pull *ndr, uint32_t *v)
208 {
209         NDR_CHECK(ndr_pull_uint3264(ndr, NDR_SCALARS, v));
210         /* ref pointers always point to data */
211         *v = 1;
212         return NDR_ERR_SUCCESS;
213 }
214
215 /*
216   parse a udlong
217 */
218 _PUBLIC_ enum ndr_err_code ndr_pull_udlong(struct ndr_pull *ndr, int ndr_flags, uint64_t *v)
219 {
220         NDR_PULL_ALIGN(ndr, 4);
221         NDR_PULL_NEED_BYTES(ndr, 8);
222         *v = NDR_IVAL(ndr, ndr->offset);
223         *v |= (uint64_t)(NDR_IVAL(ndr, ndr->offset+4)) << 32;
224         ndr->offset += 8;
225         return NDR_ERR_SUCCESS;
226 }
227
228 /*
229   parse a udlongr
230 */
231 _PUBLIC_ enum ndr_err_code ndr_pull_udlongr(struct ndr_pull *ndr, int ndr_flags, uint64_t *v)
232 {
233         NDR_PULL_ALIGN(ndr, 4);
234         NDR_PULL_NEED_BYTES(ndr, 8);
235         *v = ((uint64_t)NDR_IVAL(ndr, ndr->offset)) << 32;
236         *v |= NDR_IVAL(ndr, ndr->offset+4);
237         ndr->offset += 8;
238         return NDR_ERR_SUCCESS;
239 }
240
241 /*
242   parse a dlong
243 */
244 _PUBLIC_ enum ndr_err_code ndr_pull_dlong(struct ndr_pull *ndr, int ndr_flags, int64_t *v)
245 {
246         return ndr_pull_udlong(ndr, ndr_flags, (uint64_t *)v);
247 }
248
249 /*
250   parse a hyper
251 */
252 _PUBLIC_ enum ndr_err_code ndr_pull_hyper(struct ndr_pull *ndr, int ndr_flags, uint64_t *v)
253 {
254         NDR_PULL_ALIGN(ndr, 8);
255         if (NDR_BE(ndr)) {
256                 return ndr_pull_udlongr(ndr, ndr_flags, v);
257         }
258         return ndr_pull_udlong(ndr, ndr_flags, v);
259 }
260
261 /*
262   parse a pointer
263 */
264 _PUBLIC_ enum ndr_err_code ndr_pull_pointer(struct ndr_pull *ndr, int ndr_flags, void* *v)
265 {
266         uintptr_t h;
267         NDR_PULL_ALIGN(ndr, sizeof(h));
268         NDR_PULL_NEED_BYTES(ndr, sizeof(h));
269         memcpy(&h, ndr->data+ndr->offset, sizeof(h));
270         ndr->offset += sizeof(h);
271         *v = (void *)h;
272         return NDR_ERR_SUCCESS;
273 }
274
275 /*
276   pull a NTSTATUS
277 */
278 _PUBLIC_ enum ndr_err_code ndr_pull_NTSTATUS(struct ndr_pull *ndr, int ndr_flags, NTSTATUS *status)
279 {
280         uint32_t v;
281         NDR_CHECK(ndr_pull_uint32(ndr, NDR_SCALARS, &v));
282         *status = NT_STATUS(v);
283         return NDR_ERR_SUCCESS;
284 }
285
286 /*
287   push a NTSTATUS
288 */
289 _PUBLIC_ enum ndr_err_code ndr_push_NTSTATUS(struct ndr_push *ndr, int ndr_flags, NTSTATUS status)
290 {
291         return ndr_push_uint32(ndr, ndr_flags, NT_STATUS_V(status));
292 }
293
294 _PUBLIC_ void ndr_print_NTSTATUS(struct ndr_print *ndr, const char *name, NTSTATUS r)
295 {
296         ndr->print(ndr, "%-25s: %s", name, nt_errstr(r));
297 }
298
299 /*
300   pull a WERROR
301 */
302 _PUBLIC_ enum ndr_err_code ndr_pull_WERROR(struct ndr_pull *ndr, int ndr_flags, WERROR *status)
303 {
304         uint32_t v;
305         NDR_CHECK(ndr_pull_uint32(ndr, NDR_SCALARS, &v));
306         *status = W_ERROR(v);
307         return NDR_ERR_SUCCESS;
308 }
309
310
311 /*
312   parse a uint8_t enum
313 */
314 _PUBLIC_ enum ndr_err_code ndr_pull_enum_uint8(struct ndr_pull *ndr, int ndr_flags, uint8_t *v)
315 {
316         return ndr_pull_uint8(ndr, ndr_flags, v);
317 }
318
319 /*
320   parse a uint16_t enum
321 */
322 _PUBLIC_ enum ndr_err_code ndr_pull_enum_uint16(struct ndr_pull *ndr, int ndr_flags, uint16_t *v)
323 {
324         return ndr_pull_uint16(ndr, ndr_flags, v);
325 }
326
327 /*
328   parse a uint1632_t enum (uint32_t on NDR64)
329 */
330 _PUBLIC_ enum ndr_err_code ndr_pull_enum_uint1632(struct ndr_pull *ndr, int ndr_flags, uint16_t *v)
331 {
332         if (unlikely(ndr->flags & LIBNDR_FLAG_NDR64)) {
333                 uint32_t v32;
334                 NDR_CHECK(ndr_pull_uint32(ndr, ndr_flags, &v32));
335                 *v = v32;
336                 if (v32 != *v) {
337                         DEBUG(0,(__location__ ": non-zero upper 16 bits 0x%08x\n", (unsigned)v32));
338                         return NDR_ERR_NDR64;
339                 }
340                 return NDR_ERR_SUCCESS;
341         }
342         return ndr_pull_uint16(ndr, ndr_flags, v);
343 }
344
345 /*
346   parse a uint32_t enum
347 */
348 _PUBLIC_ enum ndr_err_code ndr_pull_enum_uint32(struct ndr_pull *ndr, int ndr_flags, uint32_t *v)
349 {
350         return ndr_pull_uint32(ndr, ndr_flags, v);
351 }
352
353 /*
354   push a uint8_t enum
355 */
356 _PUBLIC_ enum ndr_err_code ndr_push_enum_uint8(struct ndr_push *ndr, int ndr_flags, uint8_t v)
357 {
358         return ndr_push_uint8(ndr, ndr_flags, v);
359 }
360
361 /*
362   push a uint16_t enum
363 */
364 _PUBLIC_ enum ndr_err_code ndr_push_enum_uint16(struct ndr_push *ndr, int ndr_flags, uint16_t v)
365 {
366         return ndr_push_uint16(ndr, ndr_flags, v);
367 }
368
369 /*
370   push a uint32_t enum
371 */
372 _PUBLIC_ enum ndr_err_code ndr_push_enum_uint32(struct ndr_push *ndr, int ndr_flags, uint32_t v)
373 {
374         return ndr_push_uint32(ndr, ndr_flags, v);
375 }
376
377 /*
378   push a uint1632_t enum
379 */
380 _PUBLIC_ enum ndr_err_code ndr_push_enum_uint1632(struct ndr_push *ndr, int ndr_flags, uint16_t v)
381 {
382         if (unlikely(ndr->flags & LIBNDR_FLAG_NDR64)) {
383                 return ndr_push_uint32(ndr, ndr_flags, v);
384         }
385         return ndr_push_uint16(ndr, ndr_flags, v);
386 }
387
388 /*
389   push a WERROR
390 */
391 _PUBLIC_ enum ndr_err_code ndr_push_WERROR(struct ndr_push *ndr, int ndr_flags, WERROR status)
392 {
393         return ndr_push_uint32(ndr, NDR_SCALARS, W_ERROR_V(status));
394 }
395
396 _PUBLIC_ void ndr_print_WERROR(struct ndr_print *ndr, const char *name, WERROR r)
397 {
398         ndr->print(ndr, "%-25s: %s", name, win_errstr(r));
399 }
400
401 /*
402   parse a set of bytes
403 */
404 _PUBLIC_ enum ndr_err_code ndr_pull_bytes(struct ndr_pull *ndr, uint8_t *data, uint32_t n)
405 {
406         NDR_PULL_NEED_BYTES(ndr, n);
407         memcpy(data, ndr->data + ndr->offset, n);
408         ndr->offset += n;
409         return NDR_ERR_SUCCESS;
410 }
411
412 /*
413   pull an array of uint8
414 */
415 _PUBLIC_ enum ndr_err_code ndr_pull_array_uint8(struct ndr_pull *ndr, int ndr_flags, uint8_t *data, uint32_t n)
416 {
417         if (!(ndr_flags & NDR_SCALARS)) {
418                 return NDR_ERR_SUCCESS;
419         }
420         return ndr_pull_bytes(ndr, data, n);
421 }
422
423 /*
424   push a int8_t
425 */
426 _PUBLIC_ enum ndr_err_code ndr_push_int8(struct ndr_push *ndr, int ndr_flags, int8_t v)
427 {
428         NDR_PUSH_NEED_BYTES(ndr, 1);
429         SCVAL(ndr->data, ndr->offset, (uint8_t)v);
430         ndr->offset += 1;
431         return NDR_ERR_SUCCESS;
432 }
433
434 /*
435   push a uint8_t
436 */
437 _PUBLIC_ enum ndr_err_code ndr_push_uint8(struct ndr_push *ndr, int ndr_flags, uint8_t v)
438 {
439         NDR_PUSH_NEED_BYTES(ndr, 1);
440         SCVAL(ndr->data, ndr->offset, v);
441         ndr->offset += 1;
442         return NDR_ERR_SUCCESS;
443 }
444
445 /*
446   push a int16_t
447 */
448 _PUBLIC_ enum ndr_err_code ndr_push_int16(struct ndr_push *ndr, int ndr_flags, int16_t v)
449 {
450         NDR_PUSH_ALIGN(ndr, 2);
451         NDR_PUSH_NEED_BYTES(ndr, 2);
452         NDR_SSVAL(ndr, ndr->offset, (uint16_t)v);
453         ndr->offset += 2;
454         return NDR_ERR_SUCCESS;
455 }
456
457 /*
458   push a uint16_t
459 */
460 _PUBLIC_ enum ndr_err_code ndr_push_uint16(struct ndr_push *ndr, int ndr_flags, uint16_t v)
461 {
462         NDR_PUSH_ALIGN(ndr, 2);
463         NDR_PUSH_NEED_BYTES(ndr, 2);
464         NDR_SSVAL(ndr, ndr->offset, v);
465         ndr->offset += 2;
466         return NDR_ERR_SUCCESS;
467 }
468
469 /*
470   push a uint1632
471 */
472 _PUBLIC_ enum ndr_err_code ndr_push_uint1632(struct ndr_push *ndr, int ndr_flags, uint16_t v)
473 {
474         if (unlikely(ndr->flags & LIBNDR_FLAG_NDR64)) {
475                 return ndr_push_uint32(ndr, ndr_flags, v);
476         }
477         return ndr_push_uint16(ndr, ndr_flags, v);
478 }
479
480 /*
481   push a int32_t
482 */
483 _PUBLIC_ enum ndr_err_code ndr_push_int32(struct ndr_push *ndr, int ndr_flags, int32_t v)
484 {
485         NDR_PUSH_ALIGN(ndr, 4);
486         NDR_PUSH_NEED_BYTES(ndr, 4);
487         NDR_SIVALS(ndr, ndr->offset, v);
488         ndr->offset += 4;
489         return NDR_ERR_SUCCESS;
490 }
491
492 /*
493   push a uint32_t
494 */
495 _PUBLIC_ enum ndr_err_code ndr_push_uint32(struct ndr_push *ndr, int ndr_flags, uint32_t v)
496 {
497         NDR_PUSH_ALIGN(ndr, 4);
498         NDR_PUSH_NEED_BYTES(ndr, 4);
499         NDR_SIVAL(ndr, ndr->offset, v);
500         ndr->offset += 4;
501         return NDR_ERR_SUCCESS;
502 }
503
504 /*
505   push a uint3264
506 */
507 _PUBLIC_ enum ndr_err_code ndr_push_uint3264(struct ndr_push *ndr, int ndr_flags, uint32_t v)
508 {
509         if (unlikely(ndr->flags & LIBNDR_FLAG_NDR64)) {
510                 return ndr_push_hyper(ndr, ndr_flags, v);
511         }
512         return ndr_push_uint32(ndr, ndr_flags, v);
513 }
514
515 /*
516   push a udlong
517 */
518 _PUBLIC_ enum ndr_err_code ndr_push_udlong(struct ndr_push *ndr, int ndr_flags, uint64_t v)
519 {
520         NDR_PUSH_ALIGN(ndr, 4);
521         NDR_PUSH_NEED_BYTES(ndr, 8);
522         NDR_SIVAL(ndr, ndr->offset, (v & 0xFFFFFFFF));
523         NDR_SIVAL(ndr, ndr->offset+4, (v>>32));
524         ndr->offset += 8;
525         return NDR_ERR_SUCCESS;
526 }
527
528 /*
529   push a udlongr
530 */
531 _PUBLIC_ enum ndr_err_code ndr_push_udlongr(struct ndr_push *ndr, int ndr_flags, uint64_t v)
532 {
533         NDR_PUSH_ALIGN(ndr, 4);
534         NDR_PUSH_NEED_BYTES(ndr, 8);
535         NDR_SIVAL(ndr, ndr->offset, (v>>32));
536         NDR_SIVAL(ndr, ndr->offset+4, (v & 0xFFFFFFFF));
537         ndr->offset += 8;
538         return NDR_ERR_SUCCESS;
539 }
540
541 /*
542   push a dlong
543 */
544 _PUBLIC_ enum ndr_err_code ndr_push_dlong(struct ndr_push *ndr, int ndr_flags, int64_t v)
545 {
546         return ndr_push_udlong(ndr, NDR_SCALARS, (uint64_t)v);
547 }
548
549 /*
550   push a hyper
551 */
552 _PUBLIC_ enum ndr_err_code ndr_push_hyper(struct ndr_push *ndr, int ndr_flags, uint64_t v)
553 {
554         NDR_PUSH_ALIGN(ndr, 8);
555         if (NDR_BE(ndr)) {
556                 return ndr_push_udlongr(ndr, NDR_SCALARS, v);
557         }
558         return ndr_push_udlong(ndr, NDR_SCALARS, v);
559 }
560
561 /*
562   push a double
563 */
564 _PUBLIC_ enum ndr_err_code ndr_push_double(struct ndr_push *ndr, int ndr_flags, double v)
565 {
566         NDR_PUSH_ALIGN(ndr, 8);
567         NDR_PUSH_NEED_BYTES(ndr, 8);
568         memcpy(ndr->data+ndr->offset, &v, 8);
569         ndr->offset += 8;
570         return NDR_ERR_SUCCESS;
571 }
572
573 /*
574   push a pointer
575 */
576 _PUBLIC_ enum ndr_err_code ndr_push_pointer(struct ndr_push *ndr, int ndr_flags, void* v)
577 {
578         uintptr_t h = (intptr_t)v;
579         NDR_PUSH_ALIGN(ndr, sizeof(h));
580         NDR_PUSH_NEED_BYTES(ndr, sizeof(h));
581         memcpy(ndr->data+ndr->offset, &h, sizeof(h));
582         ndr->offset += sizeof(h);
583         return NDR_ERR_SUCCESS;
584 }
585
586 _PUBLIC_ enum ndr_err_code ndr_push_align(struct ndr_push *ndr, size_t size)
587 {
588         /* this is a nasty hack to make pidl work with NDR64 */
589         if (size == 5) {
590                 if (ndr->flags & LIBNDR_FLAG_NDR64) {
591                         size = 8;
592                 } else {
593                         size = 4;
594                 }
595         } else if (size == 3) {
596                 if (ndr->flags & LIBNDR_FLAG_NDR64) {
597                         size = 4;
598                 } else {
599                         size = 2;
600                 }
601         }
602         NDR_PUSH_ALIGN(ndr, size);
603         return NDR_ERR_SUCCESS;
604 }
605
606 _PUBLIC_ enum ndr_err_code ndr_pull_align(struct ndr_pull *ndr, size_t size)
607 {
608         /* this is a nasty hack to make pidl work with NDR64 */
609         if (size == 5) {
610                 if (ndr->flags & LIBNDR_FLAG_NDR64) {
611                         size = 8;
612                 } else {
613                         size = 4;
614                 }
615         } else if (size == 3) {
616                 if (ndr->flags & LIBNDR_FLAG_NDR64) {
617                         size = 4;
618                 } else {
619                         size = 2;
620                 }
621         }
622         NDR_PULL_ALIGN(ndr, size);
623         return NDR_ERR_SUCCESS;
624 }
625
626 _PUBLIC_ enum ndr_err_code ndr_push_union_align(struct ndr_push *ndr, size_t size)
627 {
628         /* MS-RPCE section 2.2.5.3.4.4 */
629         if (ndr->flags & LIBNDR_FLAG_NDR64) {
630                 return ndr_push_align(ndr, size);
631         }
632         return NDR_ERR_SUCCESS;
633 }
634
635 _PUBLIC_ enum ndr_err_code ndr_pull_union_align(struct ndr_pull *ndr, size_t size)
636 {
637         /* MS-RPCE section 2.2.5.3.4.4 */
638         if (ndr->flags & LIBNDR_FLAG_NDR64) {
639                 return ndr_pull_align(ndr, size);
640         }
641         return NDR_ERR_SUCCESS;
642 }
643
644 _PUBLIC_ enum ndr_err_code ndr_push_trailer_align(struct ndr_push *ndr, size_t size)
645 {
646         /* MS-RPCE section 2.2.5.3.4.1 */
647         if (ndr->flags & LIBNDR_FLAG_NDR64) {
648                 return ndr_push_align(ndr, size);
649         }
650         return NDR_ERR_SUCCESS;
651 }
652
653 _PUBLIC_ enum ndr_err_code ndr_pull_trailer_align(struct ndr_pull *ndr, size_t size)
654 {
655         /* MS-RPCE section 2.2.5.3.4.1 */
656         if (ndr->flags & LIBNDR_FLAG_NDR64) {
657                 return ndr_pull_align(ndr, size);
658         }
659         return NDR_ERR_SUCCESS;
660 }
661
662 /*
663   push some bytes
664 */
665 _PUBLIC_ enum ndr_err_code ndr_push_bytes(struct ndr_push *ndr, const uint8_t *data, uint32_t n)
666 {
667         NDR_PUSH_NEED_BYTES(ndr, n);
668         memcpy(ndr->data + ndr->offset, data, n);
669         ndr->offset += n;
670         return NDR_ERR_SUCCESS;
671 }
672
673 /*
674   push some zero bytes
675 */
676 _PUBLIC_ enum ndr_err_code ndr_push_zero(struct ndr_push *ndr, uint32_t n)
677 {
678         NDR_PUSH_NEED_BYTES(ndr, n);
679         memset(ndr->data + ndr->offset, 0, n);
680         ndr->offset += n;
681         return NDR_ERR_SUCCESS;
682 }
683
684 /*
685   push an array of uint8
686 */
687 _PUBLIC_ enum ndr_err_code ndr_push_array_uint8(struct ndr_push *ndr, int ndr_flags, const uint8_t *data, uint32_t n)
688 {
689         if (!(ndr_flags & NDR_SCALARS)) {
690                 return NDR_ERR_SUCCESS;
691         }
692         return ndr_push_bytes(ndr, data, n);
693 }
694
695 /*
696   push a unique non-zero value if a pointer is non-NULL, otherwise 0
697 */
698 _PUBLIC_ enum ndr_err_code ndr_push_unique_ptr(struct ndr_push *ndr, const void *p)
699 {
700         uint32_t ptr = 0;
701         if (p) {
702                 ptr = ndr->ptr_count * 4;
703                 ptr |= 0x00020000;
704                 ndr->ptr_count++;
705         }
706         return ndr_push_uint3264(ndr, NDR_SCALARS, ptr);
707 }
708
709 /*
710   push a 'simple' full non-zero value if a pointer is non-NULL, otherwise 0
711 */
712 _PUBLIC_ enum ndr_err_code ndr_push_full_ptr(struct ndr_push *ndr, const void *p)
713 {
714         uint32_t ptr = 0;
715         if (p) {
716                 /* Check if the pointer already exists and has an id */
717                 ptr = ndr_token_peek(&ndr->full_ptr_list, p);
718                 if (ptr == 0) {
719                         ndr->ptr_count++;
720                         ptr = ndr->ptr_count;
721                         ndr_token_store(ndr, &ndr->full_ptr_list, p, ptr);
722                 }
723         }
724         return ndr_push_uint3264(ndr, NDR_SCALARS, ptr);
725 }
726
727 /*
728   push always a 0, if a pointer is NULL it's a fatal error
729 */
730 _PUBLIC_ enum ndr_err_code ndr_push_ref_ptr(struct ndr_push *ndr)
731 {
732         return ndr_push_uint3264(ndr, NDR_SCALARS, 0xAEF1AEF1);
733 }
734
735
736 /*
737   push a NTTIME
738 */
739 _PUBLIC_ enum ndr_err_code ndr_push_NTTIME(struct ndr_push *ndr, int ndr_flags, NTTIME t)
740 {
741         NDR_CHECK(ndr_push_udlong(ndr, ndr_flags, t));
742         return NDR_ERR_SUCCESS;
743 }
744
745 /*
746   pull a NTTIME
747 */
748 _PUBLIC_ enum ndr_err_code ndr_pull_NTTIME(struct ndr_pull *ndr, int ndr_flags, NTTIME *t)
749 {
750         NDR_CHECK(ndr_pull_udlong(ndr, ndr_flags, t));
751         return NDR_ERR_SUCCESS;
752 }
753
754 /*
755   push a NTTIME_1sec
756 */
757 _PUBLIC_ enum ndr_err_code ndr_push_NTTIME_1sec(struct ndr_push *ndr, int ndr_flags, NTTIME t)
758 {
759         t /= 10000000;
760         NDR_CHECK(ndr_push_hyper(ndr, ndr_flags, t));
761         return NDR_ERR_SUCCESS;
762 }
763
764 /*
765   pull a NTTIME_1sec
766 */
767 _PUBLIC_ enum ndr_err_code ndr_pull_NTTIME_1sec(struct ndr_pull *ndr, int ndr_flags, NTTIME *t)
768 {
769         NDR_CHECK(ndr_pull_hyper(ndr, ndr_flags, t));
770         (*t) *= 10000000;
771         return NDR_ERR_SUCCESS;
772 }
773
774 /*
775   pull a NTTIME_hyper
776 */
777 _PUBLIC_ enum ndr_err_code ndr_pull_NTTIME_hyper(struct ndr_pull *ndr, int ndr_flags, NTTIME *t)
778 {
779         NDR_CHECK(ndr_pull_hyper(ndr, ndr_flags, t));
780         return NDR_ERR_SUCCESS;
781 }
782
783 /*
784   push a NTTIME_hyper
785 */
786 _PUBLIC_ enum ndr_err_code ndr_push_NTTIME_hyper(struct ndr_push *ndr, int ndr_flags, NTTIME t)
787 {
788         NDR_CHECK(ndr_push_hyper(ndr, ndr_flags, t));
789         return NDR_ERR_SUCCESS;
790 }
791
792 /*
793   push a time_t
794 */
795 _PUBLIC_ enum ndr_err_code ndr_push_time_t(struct ndr_push *ndr, int ndr_flags, time_t t)
796 {
797         return ndr_push_uint32(ndr, ndr_flags, t);
798 }
799
800 /*
801   pull a time_t
802 */
803 _PUBLIC_ enum ndr_err_code ndr_pull_time_t(struct ndr_pull *ndr, int ndr_flags, time_t *t)
804 {
805         uint32_t tt;
806         NDR_CHECK(ndr_pull_uint32(ndr, ndr_flags, &tt));
807         *t = tt;
808         return NDR_ERR_SUCCESS;
809 }
810
811
812 /*
813   push a uid_t
814 */
815 _PUBLIC_ enum ndr_err_code ndr_push_uid_t(struct ndr_push *ndr, int ndr_flags, uid_t u)
816 {
817         return ndr_push_udlong(ndr, NDR_SCALARS, (uint64_t)u);
818 }
819
820 /*
821   pull a uid_t
822 */
823 _PUBLIC_ enum ndr_err_code ndr_pull_uid_t(struct ndr_pull *ndr, int ndr_flags, uid_t *u)
824 {
825         uint64_t uu;
826         NDR_CHECK(ndr_pull_udlong(ndr, ndr_flags, &uu));
827         *u = (uid_t)uu;
828         if (unlikely(uu != *u)) {
829                 DEBUG(0,(__location__ ": uid_t pull doesn't fit 0x%016llx\n",
830                          (unsigned long long)uu));
831                 return NDR_ERR_NDR64;
832         }
833         return NDR_ERR_SUCCESS;
834 }
835
836
837 /*
838   push a gid_t
839 */
840 _PUBLIC_ enum ndr_err_code ndr_push_gid_t(struct ndr_push *ndr, int ndr_flags, gid_t g)
841 {
842         return ndr_push_udlong(ndr, NDR_SCALARS, (uint64_t)g);
843 }
844
845 /*
846   pull a gid_t
847 */
848 _PUBLIC_ enum ndr_err_code ndr_pull_gid_t(struct ndr_pull *ndr, int ndr_flags, gid_t *g)
849 {
850         uint64_t gg;
851         NDR_CHECK(ndr_pull_udlong(ndr, ndr_flags, &gg));
852         *g = (gid_t)gg;
853         if (unlikely(gg != *g)) {
854                 DEBUG(0,(__location__ ": gid_t pull doesn't fit 0x%016llx\n",
855                          (unsigned long long)gg));
856                 return NDR_ERR_NDR64;
857         }
858         return NDR_ERR_SUCCESS;
859 }
860
861
862 /*
863   pull a ipv4address
864 */
865 _PUBLIC_ enum ndr_err_code ndr_pull_ipv4address(struct ndr_pull *ndr, int ndr_flags, const char **address)
866 {
867         uint32_t addr;
868         struct in_addr in;
869         NDR_CHECK(ndr_pull_uint32(ndr, ndr_flags, &addr));
870         in.s_addr = htonl(addr);
871         *address = talloc_strdup(ndr->current_mem_ctx, inet_ntoa(in));
872         NDR_ERR_HAVE_NO_MEMORY(*address);
873         return NDR_ERR_SUCCESS;
874 }
875
876 /*
877   push a ipv4address
878 */
879 _PUBLIC_ enum ndr_err_code ndr_push_ipv4address(struct ndr_push *ndr, int ndr_flags, const char *address)
880 {
881         uint32_t addr;
882         if (!is_ipaddress(address)) {
883                 return ndr_push_error(ndr, NDR_ERR_IPV4ADDRESS,
884                                       "Invalid IPv4 address: '%s'",
885                                       address);
886         }
887         addr = inet_addr(address);
888         NDR_CHECK(ndr_push_uint32(ndr, ndr_flags, htonl(addr)));
889         return NDR_ERR_SUCCESS;
890 }
891
892 /*
893   print a ipv4address
894 */
895 _PUBLIC_ void ndr_print_ipv4address(struct ndr_print *ndr, const char *name,
896                            const char *address)
897 {
898         ndr->print(ndr, "%-25s: %s", name, address);
899 }
900
901 /*
902   pull a ipv6address
903 */
904 #define IPV6_BYTES 16
905 #define IPV6_ADDR_STR_LEN 39
906 _PUBLIC_ enum ndr_err_code ndr_pull_ipv6address(struct ndr_pull *ndr, int ndr_flags, const char **address)
907 {
908         uint8_t addr[IPV6_BYTES];
909         char *addr_str = talloc_strdup(ndr->current_mem_ctx, "");
910         int i;
911         NDR_CHECK(ndr_pull_array_uint8(ndr, ndr_flags, addr, IPV6_BYTES));
912         for (i = 0; i < IPV6_BYTES; ++i) {
913                 addr_str = talloc_asprintf_append(addr_str, "%02x", addr[i]);
914                 /* We need a ':' every second byte but the last one */
915                 if (i%2 == 1 && i != (IPV6_BYTES - 1)) {
916                         addr_str = talloc_strdup_append(addr_str, ":");
917                 }
918         }
919         *address = addr_str;
920         NDR_ERR_HAVE_NO_MEMORY(*address);
921         return NDR_ERR_SUCCESS;
922 }
923
924 /*
925   push a ipv6address
926 */
927 _PUBLIC_ enum ndr_err_code ndr_push_ipv6address(struct ndr_push *ndr, int ndr_flags, const char *address)
928 {
929 #ifdef AF_INET6
930         uint8_t addr[IPV6_BYTES];
931         int ret;
932
933         if (!is_ipaddress(address)) {
934                 return ndr_push_error(ndr, NDR_ERR_IPV6ADDRESS,
935                                       "Invalid IPv6 address: '%s'",
936                                       address);
937         }
938         ret = inet_pton(AF_INET6, address, addr);
939         if (ret <= 0) {
940                 return NDR_ERR_IPV6ADDRESS;
941         }
942
943         NDR_CHECK(ndr_push_array_uint8(ndr, ndr_flags, addr, IPV6_BYTES));
944
945         return NDR_ERR_SUCCESS;
946 #else
947         return NDR_ERR_IPV6ADDRESS;
948 #endif
949 }
950
951 /*
952   print a ipv6address
953 */
954 _PUBLIC_ void ndr_print_ipv6address(struct ndr_print *ndr, const char *name,
955                            const char *address)
956 {
957         ndr->print(ndr, "%-25s: %s", name, address);
958 }
959 #undef IPV6_BYTES
960
961 _PUBLIC_ void ndr_print_struct(struct ndr_print *ndr, const char *name, const char *type)
962 {
963         ndr->print(ndr, "%s: struct %s", name, type);
964 }
965
966 _PUBLIC_ void ndr_print_null(struct ndr_print *ndr)
967 {
968         ndr->print(ndr, "UNEXPECTED NULL POINTER");
969 }
970
971 _PUBLIC_ void ndr_print_enum(struct ndr_print *ndr, const char *name, const char *type, 
972                     const char *val, uint32_t value)
973 {
974         if (ndr->flags & LIBNDR_PRINT_ARRAY_HEX) {
975                 ndr->print(ndr, "%-25s: %s (0x%X)", name, val?val:"UNKNOWN_ENUM_VALUE", value);
976         } else {
977                 ndr->print(ndr, "%-25s: %s (%d)", name, val?val:"UNKNOWN_ENUM_VALUE", value);
978         }
979 }
980
981 _PUBLIC_ void ndr_print_bitmap_flag(struct ndr_print *ndr, size_t size, const char *flag_name, uint32_t flag, uint32_t value)
982 {
983         /* this is an attempt to support multi-bit bitmap masks */
984         value &= flag;
985
986         while (!(flag & 1)) {
987                 flag >>= 1;
988                 value >>= 1;
989         }       
990         if (flag == 1) {
991                 ndr->print(ndr, "   %d: %-25s", value, flag_name);
992         } else {
993                 ndr->print(ndr, "0x%02x: %-25s (%d)", value, flag_name, value);
994         }
995 }
996
997 _PUBLIC_ void ndr_print_int8(struct ndr_print *ndr, const char *name, int8_t v)
998 {
999         ndr->print(ndr, "%-25s: %d", name, v);
1000 }
1001
1002 _PUBLIC_ void ndr_print_uint8(struct ndr_print *ndr, const char *name, uint8_t v)
1003 {
1004         ndr->print(ndr, "%-25s: 0x%02x (%u)", name, v, v);
1005 }
1006
1007 _PUBLIC_ void ndr_print_int16(struct ndr_print *ndr, const char *name, int16_t v)
1008 {
1009         ndr->print(ndr, "%-25s: %d", name, v);
1010 }
1011
1012 _PUBLIC_ void ndr_print_uint16(struct ndr_print *ndr, const char *name, uint16_t v)
1013 {
1014         ndr->print(ndr, "%-25s: 0x%04x (%u)", name, v, v);
1015 }
1016
1017 _PUBLIC_ void ndr_print_int32(struct ndr_print *ndr, const char *name, int32_t v)
1018 {
1019         ndr->print(ndr, "%-25s: %d", name, v);
1020 }
1021
1022 _PUBLIC_ void ndr_print_uint32(struct ndr_print *ndr, const char *name, uint32_t v)
1023 {
1024         ndr->print(ndr, "%-25s: 0x%08x (%u)", name, v, v);
1025 }
1026
1027 _PUBLIC_ void ndr_print_int3264(struct ndr_print *ndr, const char *name, int32_t v)
1028 {
1029         ndr->print(ndr, "%-25s: %d", name, v);
1030 }
1031
1032 _PUBLIC_ void ndr_print_uint3264(struct ndr_print *ndr, const char *name, uint32_t v)
1033 {
1034         ndr->print(ndr, "%-25s: 0x%08x (%u)", name, v, v);
1035 }
1036
1037 _PUBLIC_ void ndr_print_udlong(struct ndr_print *ndr, const char *name, uint64_t v)
1038 {
1039         ndr->print(ndr, "%-25s: 0x%016llx (%llu)", name, (unsigned long long)v, (unsigned long long)v);
1040 }
1041
1042 _PUBLIC_ void ndr_print_udlongr(struct ndr_print *ndr, const char *name, uint64_t v)
1043 {
1044         ndr_print_udlong(ndr, name, v);
1045 }
1046
1047 _PUBLIC_ void ndr_print_dlong(struct ndr_print *ndr, const char *name, int64_t v)
1048 {
1049         ndr->print(ndr, "%-25s: 0x%016llx (%lld)", name, (unsigned long long)v, (long long)v);
1050 }
1051
1052 _PUBLIC_ void ndr_print_double(struct ndr_print *ndr, const char *name, double v)
1053 {
1054         ndr->print(ndr, "%-25s: %f", name, v);
1055 }
1056
1057 _PUBLIC_ void ndr_print_hyper(struct ndr_print *ndr, const char *name, uint64_t v)
1058 {
1059         ndr_print_dlong(ndr, name, v);
1060 }
1061
1062 _PUBLIC_ void ndr_print_pointer(struct ndr_print *ndr, const char *name, void *v)
1063 {
1064         ndr->print(ndr, "%-25s: %p", name, v);
1065 }
1066
1067 _PUBLIC_ void ndr_print_ptr(struct ndr_print *ndr, const char *name, const void *p)
1068 {
1069         if (p) {
1070                 ndr->print(ndr, "%-25s: *", name);
1071         } else {
1072                 ndr->print(ndr, "%-25s: NULL", name);
1073         }
1074 }
1075
1076 _PUBLIC_ void ndr_print_NTTIME(struct ndr_print *ndr, const char *name, NTTIME t)
1077 {
1078         ndr->print(ndr, "%-25s: %s", name, nt_time_string(ndr, t));
1079 }
1080
1081 _PUBLIC_ void ndr_print_NTTIME_1sec(struct ndr_print *ndr, const char *name, NTTIME t)
1082 {
1083         /* this is a standard NTTIME here
1084          * as it's already converted in the pull/push code
1085          */
1086         ndr_print_NTTIME(ndr, name, t);
1087 }
1088
1089 _PUBLIC_ void ndr_print_NTTIME_hyper(struct ndr_print *ndr, const char *name, NTTIME t)
1090 {
1091         ndr_print_NTTIME(ndr, name, t);
1092 }
1093
1094 _PUBLIC_ void ndr_print_time_t(struct ndr_print *ndr, const char *name, time_t t)
1095 {
1096         if (t == (time_t)-1 || t == 0) {
1097                 ndr->print(ndr, "%-25s: (time_t)%d", name, (int)t);
1098         } else {
1099                 ndr->print(ndr, "%-25s: %s", name, timestring(ndr, t));
1100         }
1101 }
1102
1103 _PUBLIC_ void ndr_print_uid_t(struct ndr_print *ndr, const char *name, uid_t u)
1104 {
1105         ndr_print_dlong(ndr, name, u);
1106 }
1107
1108 _PUBLIC_ void ndr_print_gid_t(struct ndr_print *ndr, const char *name, gid_t g)
1109 {
1110         ndr_print_dlong(ndr, name, g);
1111 }
1112
1113 _PUBLIC_ void ndr_print_union(struct ndr_print *ndr, const char *name, int level, const char *type)
1114 {
1115         if (ndr->flags & LIBNDR_PRINT_ARRAY_HEX) {
1116                 ndr->print(ndr, "%-25s: union %s(case 0x%X)", name, type, level);
1117         } else {
1118                 ndr->print(ndr, "%-25s: union %s(case %d)", name, type, level);
1119         }
1120 }
1121
1122 _PUBLIC_ void ndr_print_bad_level(struct ndr_print *ndr, const char *name, uint16_t level)
1123 {
1124         ndr->print(ndr, "UNKNOWN LEVEL %u", level);
1125 }
1126
1127 _PUBLIC_ void ndr_print_array_uint8(struct ndr_print *ndr, const char *name, 
1128                            const uint8_t *data, uint32_t count)
1129 {
1130         int i;
1131
1132         if (data == NULL) {
1133                 ndr->print(ndr, "%s: ARRAY(%d) : NULL", name, count);
1134                 return;
1135         }
1136
1137         if (count <= 600 && (ndr->flags & LIBNDR_PRINT_ARRAY_HEX)) {
1138                 char s[1202];
1139                 for (i=0;i<count;i++) {
1140                         snprintf(&s[i*2], 3, "%02x", data[i]);
1141                 }
1142                 s[i*2] = 0;
1143                 ndr->print(ndr, "%-25s: %s", name, s);
1144                 return;
1145         }
1146
1147         ndr->print(ndr, "%s: ARRAY(%d)", name, count);
1148         ndr->depth++;
1149         for (i=0;i<count;i++) {
1150                 char *idx=NULL;
1151                 if (asprintf(&idx, "[%d]", i) != -1) {
1152                         ndr_print_uint8(ndr, idx, data[i]);
1153                         free(idx);
1154                 }
1155         }
1156         ndr->depth--;   
1157 }
1158
1159 static void ndr_print_asc(struct ndr_print *ndr, const uint8_t *buf, int len)
1160 {
1161         int i;
1162         for (i=0;i<len;i++)
1163                 ndr->print(ndr, "%c", isprint(buf[i])?buf[i]:'.');
1164 }
1165
1166 /*
1167   ndr_print version of dump_data()
1168  */
1169 static void ndr_dump_data(struct ndr_print *ndr, const uint8_t *buf, int len)
1170 {
1171         int i=0;
1172
1173         ndr->no_newline = true;
1174
1175         for (i=0;i<len;) {
1176                 if (i%16 == 0 && i<len) {
1177                         ndr->print(ndr, "[%04X] ",i);
1178                 }
1179
1180                 ndr->print(ndr, "%02X ",(int)buf[i]);
1181                 i++;
1182                 if (i%8 == 0) ndr->print(ndr,"  ");
1183                 if (i%16 == 0) {
1184                         ndr_print_asc(ndr,&buf[i-16],8); ndr->print(ndr," ");
1185                         ndr_print_asc(ndr,&buf[i-8],8); ndr->print(ndr, "\n");
1186                 }
1187         }
1188
1189         if (i%16) {
1190                 int n;
1191                 n = 16 - (i%16);
1192                 ndr->print(ndr, " ");
1193                 if (n>8) ndr->print(ndr," ");
1194                 while (n--) ndr->print(ndr,"   ");
1195                 n = MIN(8,i%16);
1196                 ndr_print_asc(ndr,&buf[i-(i%16)],n); ndr->print(ndr, " ");
1197                 n = (i%16) - n;
1198                 if (n>0) ndr_print_asc(ndr,&buf[i-n],n);
1199                 ndr->print(ndr,"\n");
1200         }
1201
1202         ndr->no_newline = false;
1203 }
1204
1205
1206 _PUBLIC_ void ndr_print_DATA_BLOB(struct ndr_print *ndr, const char *name, DATA_BLOB r)
1207 {
1208         ndr->print(ndr, "%-25s: DATA_BLOB length=%u", name, (unsigned)r.length);
1209         if (r.length) {
1210                 ndr_dump_data(ndr, r.data, r.length);
1211         }
1212 }
1213
1214
1215 /*
1216   push a DATA_BLOB onto the wire. 
1217 */
1218 _PUBLIC_ enum ndr_err_code ndr_push_DATA_BLOB(struct ndr_push *ndr, int ndr_flags, DATA_BLOB blob)
1219 {
1220         if (ndr->flags & LIBNDR_FLAG_REMAINING) {
1221                 /* nothing to do */
1222         } else if (ndr->flags & LIBNDR_ALIGN_FLAGS) {
1223                 if (ndr->flags & LIBNDR_FLAG_NOALIGN) {
1224                         blob.length = 0;
1225                 } else if (ndr->flags & LIBNDR_FLAG_ALIGN2) {
1226                         blob.length = NDR_ALIGN(ndr, 2);
1227                 } else if (ndr->flags & LIBNDR_FLAG_ALIGN4) {
1228                         blob.length = NDR_ALIGN(ndr, 4);
1229                 } else if (ndr->flags & LIBNDR_FLAG_ALIGN8) {
1230                         blob.length = NDR_ALIGN(ndr, 8);
1231                 }
1232                 NDR_PUSH_ALLOC_SIZE(ndr, blob.data, blob.length);
1233                 data_blob_clear(&blob);
1234         } else {
1235                 NDR_CHECK(ndr_push_uint32(ndr, NDR_SCALARS, blob.length));
1236         }
1237         NDR_CHECK(ndr_push_bytes(ndr, blob.data, blob.length));
1238         return NDR_ERR_SUCCESS;
1239 }
1240
1241 /*
1242   pull a DATA_BLOB from the wire. 
1243 */
1244 _PUBLIC_ enum ndr_err_code ndr_pull_DATA_BLOB(struct ndr_pull *ndr, int ndr_flags, DATA_BLOB *blob)
1245 {
1246         uint32_t length = 0;
1247
1248         if (ndr->flags & LIBNDR_FLAG_REMAINING) {
1249                 length = ndr->data_size - ndr->offset;
1250         } else if (ndr->flags & LIBNDR_ALIGN_FLAGS) {
1251                 if (ndr->flags & LIBNDR_FLAG_NOALIGN) {
1252                         length = 0;
1253                 } else if (ndr->flags & LIBNDR_FLAG_ALIGN2) {
1254                         length = NDR_ALIGN(ndr, 2);
1255                 } else if (ndr->flags & LIBNDR_FLAG_ALIGN4) {
1256                         length = NDR_ALIGN(ndr, 4);
1257                 } else if (ndr->flags & LIBNDR_FLAG_ALIGN8) {
1258                         length = NDR_ALIGN(ndr, 8);
1259                 }
1260                 if (ndr->data_size - ndr->offset < length) {
1261                         length = ndr->data_size - ndr->offset;
1262                 }
1263         } else {
1264                 NDR_CHECK(ndr_pull_uint32(ndr, NDR_SCALARS, &length));
1265         }
1266         NDR_PULL_NEED_BYTES(ndr, length);
1267         *blob = data_blob_talloc(ndr->current_mem_ctx, ndr->data+ndr->offset, length);
1268         ndr->offset += length;
1269         return NDR_ERR_SUCCESS;
1270 }
1271
1272 _PUBLIC_ uint32_t ndr_size_DATA_BLOB(int ret, const DATA_BLOB *data, int flags)
1273 {
1274         if (!data) return ret;
1275         return ret + data->length;
1276 }
1277
1278 _PUBLIC_ void ndr_print_bool(struct ndr_print *ndr, const char *name, const bool b)
1279 {
1280         ndr->print(ndr, "%-25s: %s", name, b?"true":"false");
1281 }
1282
1283 _PUBLIC_ NTSTATUS ndr_map_error2ntstatus(enum ndr_err_code ndr_err)
1284 {
1285         switch (ndr_err) {
1286         case NDR_ERR_SUCCESS:
1287                 return NT_STATUS_OK;
1288         case NDR_ERR_BUFSIZE:
1289                 return NT_STATUS_BUFFER_TOO_SMALL;
1290         case NDR_ERR_TOKEN:
1291                 return NT_STATUS_INTERNAL_ERROR;
1292         case NDR_ERR_ALLOC:
1293                 return NT_STATUS_NO_MEMORY;
1294         case NDR_ERR_ARRAY_SIZE:
1295                 return NT_STATUS_ARRAY_BOUNDS_EXCEEDED;
1296         case NDR_ERR_INVALID_POINTER:
1297                 return NT_STATUS_INVALID_PARAMETER_MIX;
1298         case NDR_ERR_UNREAD_BYTES:
1299                 return NT_STATUS_PORT_MESSAGE_TOO_LONG;
1300         default:
1301                 break;
1302         }
1303
1304         /* we should map all error codes to different status codes */
1305         return NT_STATUS_INVALID_PARAMETER;
1306 }