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