0becf38f7ba14a3bacb70131b9a94e1efe539c71
[nivanova/samba.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         return ndr_pull_udlong(ndr, ndr_flags, v);
256 }
257
258 /*
259   parse a pointer
260 */
261 _PUBLIC_ enum ndr_err_code ndr_pull_pointer(struct ndr_pull *ndr, int ndr_flags, void* *v)
262 {
263         uintptr_t h;
264         NDR_PULL_ALIGN(ndr, sizeof(h));
265         NDR_PULL_NEED_BYTES(ndr, sizeof(h));
266         memcpy(&h, ndr->data+ndr->offset, sizeof(h));
267         ndr->offset += sizeof(h);
268         *v = (void *)h;
269         return NDR_ERR_SUCCESS;
270 }
271
272 /*
273   pull a NTSTATUS
274 */
275 _PUBLIC_ enum ndr_err_code ndr_pull_NTSTATUS(struct ndr_pull *ndr, int ndr_flags, NTSTATUS *status)
276 {
277         uint32_t v;
278         NDR_CHECK(ndr_pull_uint32(ndr, NDR_SCALARS, &v));
279         *status = NT_STATUS(v);
280         return NDR_ERR_SUCCESS;
281 }
282
283 /*
284   push a NTSTATUS
285 */
286 _PUBLIC_ enum ndr_err_code ndr_push_NTSTATUS(struct ndr_push *ndr, int ndr_flags, NTSTATUS status)
287 {
288         return ndr_push_uint32(ndr, ndr_flags, NT_STATUS_V(status));
289 }
290
291 _PUBLIC_ void ndr_print_NTSTATUS(struct ndr_print *ndr, const char *name, NTSTATUS r)
292 {
293         ndr->print(ndr, "%-25s: %s", name, nt_errstr(r));
294 }
295
296 /*
297   pull a WERROR
298 */
299 _PUBLIC_ enum ndr_err_code ndr_pull_WERROR(struct ndr_pull *ndr, int ndr_flags, WERROR *status)
300 {
301         uint32_t v;
302         NDR_CHECK(ndr_pull_uint32(ndr, NDR_SCALARS, &v));
303         *status = W_ERROR(v);
304         return NDR_ERR_SUCCESS;
305 }
306
307
308 /*
309   parse a uint8_t enum
310 */
311 _PUBLIC_ enum ndr_err_code ndr_pull_enum_uint8(struct ndr_pull *ndr, int ndr_flags, uint8_t *v)
312 {
313         return ndr_pull_uint8(ndr, ndr_flags, v);
314 }
315
316 /*
317   parse a uint16_t enum
318 */
319 _PUBLIC_ enum ndr_err_code ndr_pull_enum_uint16(struct ndr_pull *ndr, int ndr_flags, uint16_t *v)
320 {
321         return ndr_pull_uint16(ndr, ndr_flags, v);
322 }
323
324 /*
325   parse a uint1632_t enum (uint32_t on NDR64)
326 */
327 _PUBLIC_ enum ndr_err_code ndr_pull_enum_uint1632(struct ndr_pull *ndr, int ndr_flags, uint16_t *v)
328 {
329         if (unlikely(ndr->flags & LIBNDR_FLAG_NDR64)) {
330                 uint32_t v32;
331                 NDR_CHECK(ndr_pull_uint32(ndr, ndr_flags, &v32));
332                 *v = v32;
333                 if (v32 != *v) {
334                         DEBUG(0,(__location__ ": non-zero upper 16 bits 0x%08x\n", (unsigned)v32));
335                         return NDR_ERR_NDR64;
336                 }
337                 return NDR_ERR_SUCCESS;
338         }
339         return ndr_pull_uint16(ndr, ndr_flags, v);
340 }
341
342 /*
343   parse a uint32_t enum
344 */
345 _PUBLIC_ enum ndr_err_code ndr_pull_enum_uint32(struct ndr_pull *ndr, int ndr_flags, uint32_t *v)
346 {
347         return ndr_pull_uint32(ndr, ndr_flags, v);
348 }
349
350 /*
351   push a uint8_t enum
352 */
353 _PUBLIC_ enum ndr_err_code ndr_push_enum_uint8(struct ndr_push *ndr, int ndr_flags, uint8_t v)
354 {
355         return ndr_push_uint8(ndr, ndr_flags, v);
356 }
357
358 /*
359   push a uint16_t enum
360 */
361 _PUBLIC_ enum ndr_err_code ndr_push_enum_uint16(struct ndr_push *ndr, int ndr_flags, uint16_t v)
362 {
363         return ndr_push_uint16(ndr, ndr_flags, v);
364 }
365
366 /*
367   push a uint32_t enum
368 */
369 _PUBLIC_ enum ndr_err_code ndr_push_enum_uint32(struct ndr_push *ndr, int ndr_flags, uint32_t v)
370 {
371         return ndr_push_uint32(ndr, ndr_flags, v);
372 }
373
374 /*
375   push a uint1632_t enum
376 */
377 _PUBLIC_ enum ndr_err_code ndr_push_enum_uint1632(struct ndr_push *ndr, int ndr_flags, uint16_t v)
378 {
379         if (unlikely(ndr->flags & LIBNDR_FLAG_NDR64)) {
380                 return ndr_push_uint32(ndr, ndr_flags, v);
381         }
382         return ndr_push_uint16(ndr, ndr_flags, v);
383 }
384
385 /*
386   push a WERROR
387 */
388 _PUBLIC_ enum ndr_err_code ndr_push_WERROR(struct ndr_push *ndr, int ndr_flags, WERROR status)
389 {
390         return ndr_push_uint32(ndr, NDR_SCALARS, W_ERROR_V(status));
391 }
392
393 _PUBLIC_ void ndr_print_WERROR(struct ndr_print *ndr, const char *name, WERROR r)
394 {
395         ndr->print(ndr, "%-25s: %s", name, win_errstr(r));
396 }
397
398 /*
399   parse a set of bytes
400 */
401 _PUBLIC_ enum ndr_err_code ndr_pull_bytes(struct ndr_pull *ndr, uint8_t *data, uint32_t n)
402 {
403         NDR_PULL_NEED_BYTES(ndr, n);
404         memcpy(data, ndr->data + ndr->offset, n);
405         ndr->offset += n;
406         return NDR_ERR_SUCCESS;
407 }
408
409 /*
410   pull an array of uint8
411 */
412 _PUBLIC_ enum ndr_err_code ndr_pull_array_uint8(struct ndr_pull *ndr, int ndr_flags, uint8_t *data, uint32_t n)
413 {
414         if (!(ndr_flags & NDR_SCALARS)) {
415                 return NDR_ERR_SUCCESS;
416         }
417         return ndr_pull_bytes(ndr, data, n);
418 }
419
420 /*
421   push a int8_t
422 */
423 _PUBLIC_ enum ndr_err_code ndr_push_int8(struct ndr_push *ndr, int ndr_flags, int8_t v)
424 {
425         NDR_PUSH_NEED_BYTES(ndr, 1);
426         SCVAL(ndr->data, ndr->offset, (uint8_t)v);
427         ndr->offset += 1;
428         return NDR_ERR_SUCCESS;
429 }
430
431 /*
432   push a uint8_t
433 */
434 _PUBLIC_ enum ndr_err_code ndr_push_uint8(struct ndr_push *ndr, int ndr_flags, uint8_t v)
435 {
436         NDR_PUSH_NEED_BYTES(ndr, 1);
437         SCVAL(ndr->data, ndr->offset, v);
438         ndr->offset += 1;
439         return NDR_ERR_SUCCESS;
440 }
441
442 /*
443   push a int16_t
444 */
445 _PUBLIC_ enum ndr_err_code ndr_push_int16(struct ndr_push *ndr, int ndr_flags, int16_t v)
446 {
447         NDR_PUSH_ALIGN(ndr, 2);
448         NDR_PUSH_NEED_BYTES(ndr, 2);
449         NDR_SSVAL(ndr, ndr->offset, (uint16_t)v);
450         ndr->offset += 2;
451         return NDR_ERR_SUCCESS;
452 }
453
454 /*
455   push a uint16_t
456 */
457 _PUBLIC_ enum ndr_err_code ndr_push_uint16(struct ndr_push *ndr, int ndr_flags, uint16_t v)
458 {
459         NDR_PUSH_ALIGN(ndr, 2);
460         NDR_PUSH_NEED_BYTES(ndr, 2);
461         NDR_SSVAL(ndr, ndr->offset, v);
462         ndr->offset += 2;
463         return NDR_ERR_SUCCESS;
464 }
465
466 /*
467   push a uint1632
468 */
469 _PUBLIC_ enum ndr_err_code ndr_push_uint1632(struct ndr_push *ndr, int ndr_flags, uint16_t v)
470 {
471         if (unlikely(ndr->flags & LIBNDR_FLAG_NDR64)) {
472                 return ndr_push_uint32(ndr, ndr_flags, v);
473         }
474         return ndr_push_uint16(ndr, ndr_flags, v);
475 }
476
477 /*
478   push a int32_t
479 */
480 _PUBLIC_ enum ndr_err_code ndr_push_int32(struct ndr_push *ndr, int ndr_flags, int32_t v)
481 {
482         NDR_PUSH_ALIGN(ndr, 4);
483         NDR_PUSH_NEED_BYTES(ndr, 4);
484         NDR_SIVALS(ndr, ndr->offset, v);
485         ndr->offset += 4;
486         return NDR_ERR_SUCCESS;
487 }
488
489 /*
490   push a uint32_t
491 */
492 _PUBLIC_ enum ndr_err_code ndr_push_uint32(struct ndr_push *ndr, int ndr_flags, uint32_t v)
493 {
494         NDR_PUSH_ALIGN(ndr, 4);
495         NDR_PUSH_NEED_BYTES(ndr, 4);
496         NDR_SIVAL(ndr, ndr->offset, v);
497         ndr->offset += 4;
498         return NDR_ERR_SUCCESS;
499 }
500
501 /*
502   push a uint3264
503 */
504 _PUBLIC_ enum ndr_err_code ndr_push_uint3264(struct ndr_push *ndr, int ndr_flags, uint32_t v)
505 {
506         if (unlikely(ndr->flags & LIBNDR_FLAG_NDR64)) {
507                 return ndr_push_hyper(ndr, ndr_flags, v);
508         }
509         return ndr_push_uint32(ndr, ndr_flags, v);
510 }
511
512 /*
513   push a udlong
514 */
515 _PUBLIC_ enum ndr_err_code ndr_push_udlong(struct ndr_push *ndr, int ndr_flags, uint64_t v)
516 {
517         NDR_PUSH_ALIGN(ndr, 4);
518         NDR_PUSH_NEED_BYTES(ndr, 8);
519         NDR_SIVAL(ndr, ndr->offset, (v & 0xFFFFFFFF));
520         NDR_SIVAL(ndr, ndr->offset+4, (v>>32));
521         ndr->offset += 8;
522         return NDR_ERR_SUCCESS;
523 }
524
525 /*
526   push a udlongr
527 */
528 _PUBLIC_ enum ndr_err_code ndr_push_udlongr(struct ndr_push *ndr, int ndr_flags, uint64_t v)
529 {
530         NDR_PUSH_ALIGN(ndr, 4);
531         NDR_PUSH_NEED_BYTES(ndr, 8);
532         NDR_SIVAL(ndr, ndr->offset, (v>>32));
533         NDR_SIVAL(ndr, ndr->offset+4, (v & 0xFFFFFFFF));
534         ndr->offset += 8;
535         return NDR_ERR_SUCCESS;
536 }
537
538 /*
539   push a dlong
540 */
541 _PUBLIC_ enum ndr_err_code ndr_push_dlong(struct ndr_push *ndr, int ndr_flags, int64_t v)
542 {
543         return ndr_push_udlong(ndr, NDR_SCALARS, (uint64_t)v);
544 }
545
546 /*
547   push a hyper
548 */
549 _PUBLIC_ enum ndr_err_code ndr_push_hyper(struct ndr_push *ndr, int ndr_flags, uint64_t v)
550 {
551         NDR_PUSH_ALIGN(ndr, 8);
552         return ndr_push_udlong(ndr, NDR_SCALARS, v);
553 }
554
555 /*
556   push a double
557 */
558 _PUBLIC_ enum ndr_err_code ndr_push_double(struct ndr_push *ndr, int ndr_flags, double v)
559 {
560         NDR_PUSH_ALIGN(ndr, 8);
561         NDR_PUSH_NEED_BYTES(ndr, 8);
562         memcpy(ndr->data+ndr->offset, &v, 8);
563         ndr->offset += 8;
564         return NDR_ERR_SUCCESS;
565 }
566
567 /*
568   push a pointer
569 */
570 _PUBLIC_ enum ndr_err_code ndr_push_pointer(struct ndr_push *ndr, int ndr_flags, void* v)
571 {
572         uintptr_t h = (intptr_t)v;
573         NDR_PUSH_ALIGN(ndr, sizeof(h));
574         NDR_PUSH_NEED_BYTES(ndr, sizeof(h));
575         memcpy(ndr->data+ndr->offset, &h, sizeof(h));
576         ndr->offset += sizeof(h);
577         return NDR_ERR_SUCCESS;
578 }
579
580 _PUBLIC_ enum ndr_err_code ndr_push_align(struct ndr_push *ndr, size_t size)
581 {
582         /* this is a nasty hack to make pidl work with NDR64 */
583         if (size == 5) {
584                 if (ndr->flags & LIBNDR_FLAG_NDR64) {
585                         size = 8;
586                 } else {
587                         size = 4;
588                 }
589         } else if (size == 3) {
590                 if (ndr->flags & LIBNDR_FLAG_NDR64) {
591                         size = 4;
592                 } else {
593                         size = 2;
594                 }
595         }
596         NDR_PUSH_ALIGN(ndr, size);
597         return NDR_ERR_SUCCESS;
598 }
599
600 _PUBLIC_ enum ndr_err_code ndr_pull_align(struct ndr_pull *ndr, size_t size)
601 {
602         /* this is a nasty hack to make pidl work with NDR64 */
603         if (size == 5) {
604                 if (ndr->flags & LIBNDR_FLAG_NDR64) {
605                         size = 8;
606                 } else {
607                         size = 4;
608                 }
609         } else if (size == 3) {
610                 if (ndr->flags & LIBNDR_FLAG_NDR64) {
611                         size = 4;
612                 } else {
613                         size = 2;
614                 }
615         }
616         NDR_PULL_ALIGN(ndr, size);
617         return NDR_ERR_SUCCESS;
618 }
619
620 _PUBLIC_ enum ndr_err_code ndr_push_union_align(struct ndr_push *ndr, size_t size)
621 {
622         /* MS-RPCE section 2.2.5.3.4.4 */
623         if (ndr->flags & LIBNDR_FLAG_NDR64) {
624                 return ndr_push_align(ndr, size);
625         }
626         return NDR_ERR_SUCCESS;
627 }
628
629 _PUBLIC_ enum ndr_err_code ndr_pull_union_align(struct ndr_pull *ndr, size_t size)
630 {
631         /* MS-RPCE section 2.2.5.3.4.4 */
632         if (ndr->flags & LIBNDR_FLAG_NDR64) {
633                 return ndr_pull_align(ndr, size);
634         }
635         return NDR_ERR_SUCCESS;
636 }
637
638 _PUBLIC_ enum ndr_err_code ndr_push_trailer_align(struct ndr_push *ndr, size_t size)
639 {
640         /* MS-RPCE section 2.2.5.3.4.1 */
641         if (ndr->flags & LIBNDR_FLAG_NDR64) {
642                 return ndr_push_align(ndr, size);
643         }
644         return NDR_ERR_SUCCESS;
645 }
646
647 _PUBLIC_ enum ndr_err_code ndr_pull_trailer_align(struct ndr_pull *ndr, size_t size)
648 {
649         /* MS-RPCE section 2.2.5.3.4.1 */
650         if (ndr->flags & LIBNDR_FLAG_NDR64) {
651                 return ndr_pull_align(ndr, size);
652         }
653         return NDR_ERR_SUCCESS;
654 }
655
656 /*
657   push some bytes
658 */
659 _PUBLIC_ enum ndr_err_code ndr_push_bytes(struct ndr_push *ndr, const uint8_t *data, uint32_t n)
660 {
661         NDR_PUSH_NEED_BYTES(ndr, n);
662         memcpy(ndr->data + ndr->offset, data, n);
663         ndr->offset += n;
664         return NDR_ERR_SUCCESS;
665 }
666
667 /*
668   push some zero bytes
669 */
670 _PUBLIC_ enum ndr_err_code ndr_push_zero(struct ndr_push *ndr, uint32_t n)
671 {
672         NDR_PUSH_NEED_BYTES(ndr, n);
673         memset(ndr->data + ndr->offset, 0, n);
674         ndr->offset += n;
675         return NDR_ERR_SUCCESS;
676 }
677
678 /*
679   push an array of uint8
680 */
681 _PUBLIC_ enum ndr_err_code ndr_push_array_uint8(struct ndr_push *ndr, int ndr_flags, const uint8_t *data, uint32_t n)
682 {
683         if (!(ndr_flags & NDR_SCALARS)) {
684                 return NDR_ERR_SUCCESS;
685         }
686         return ndr_push_bytes(ndr, data, n);
687 }
688
689 /*
690   push a unique non-zero value if a pointer is non-NULL, otherwise 0
691 */
692 _PUBLIC_ enum ndr_err_code ndr_push_unique_ptr(struct ndr_push *ndr, const void *p)
693 {
694         uint32_t ptr = 0;
695         if (p) {
696                 ptr = ndr->ptr_count * 4;
697                 ptr |= 0x00020000;
698                 ndr->ptr_count++;
699         }
700         return ndr_push_uint3264(ndr, NDR_SCALARS, ptr);
701 }
702
703 /*
704   push a 'simple' full non-zero value if a pointer is non-NULL, otherwise 0
705 */
706 _PUBLIC_ enum ndr_err_code ndr_push_full_ptr(struct ndr_push *ndr, const void *p)
707 {
708         uint32_t ptr = 0;
709         if (p) {
710                 /* Check if the pointer already exists and has an id */
711                 ptr = ndr_token_peek(&ndr->full_ptr_list, p);
712                 if (ptr == 0) {
713                         ndr->ptr_count++;
714                         ptr = ndr->ptr_count;
715                         ndr_token_store(ndr, &ndr->full_ptr_list, p, ptr);
716                 }
717         }
718         return ndr_push_uint3264(ndr, NDR_SCALARS, ptr);
719 }
720
721 /*
722   push always a 0, if a pointer is NULL it's a fatal error
723 */
724 _PUBLIC_ enum ndr_err_code ndr_push_ref_ptr(struct ndr_push *ndr)
725 {
726         return ndr_push_uint3264(ndr, NDR_SCALARS, 0xAEF1AEF1);
727 }
728
729
730 /*
731   push a NTTIME
732 */
733 _PUBLIC_ enum ndr_err_code ndr_push_NTTIME(struct ndr_push *ndr, int ndr_flags, NTTIME t)
734 {
735         NDR_CHECK(ndr_push_udlong(ndr, ndr_flags, t));
736         return NDR_ERR_SUCCESS;
737 }
738
739 /*
740   pull a NTTIME
741 */
742 _PUBLIC_ enum ndr_err_code ndr_pull_NTTIME(struct ndr_pull *ndr, int ndr_flags, NTTIME *t)
743 {
744         NDR_CHECK(ndr_pull_udlong(ndr, ndr_flags, t));
745         return NDR_ERR_SUCCESS;
746 }
747
748 /*
749   push a NTTIME_1sec
750 */
751 _PUBLIC_ enum ndr_err_code ndr_push_NTTIME_1sec(struct ndr_push *ndr, int ndr_flags, NTTIME t)
752 {
753         t /= 10000000;
754         NDR_CHECK(ndr_push_hyper(ndr, ndr_flags, t));
755         return NDR_ERR_SUCCESS;
756 }
757
758 /*
759   pull a NTTIME_1sec
760 */
761 _PUBLIC_ enum ndr_err_code ndr_pull_NTTIME_1sec(struct ndr_pull *ndr, int ndr_flags, NTTIME *t)
762 {
763         NDR_CHECK(ndr_pull_hyper(ndr, ndr_flags, t));
764         (*t) *= 10000000;
765         return NDR_ERR_SUCCESS;
766 }
767
768 /*
769   pull a NTTIME_hyper
770 */
771 _PUBLIC_ enum ndr_err_code ndr_pull_NTTIME_hyper(struct ndr_pull *ndr, int ndr_flags, NTTIME *t)
772 {
773         NDR_CHECK(ndr_pull_hyper(ndr, ndr_flags, t));
774         return NDR_ERR_SUCCESS;
775 }
776
777 /*
778   push a NTTIME_hyper
779 */
780 _PUBLIC_ enum ndr_err_code ndr_push_NTTIME_hyper(struct ndr_push *ndr, int ndr_flags, NTTIME t)
781 {
782         NDR_CHECK(ndr_push_hyper(ndr, ndr_flags, t));
783         return NDR_ERR_SUCCESS;
784 }
785
786 /*
787   push a time_t
788 */
789 _PUBLIC_ enum ndr_err_code ndr_push_time_t(struct ndr_push *ndr, int ndr_flags, time_t t)
790 {
791         return ndr_push_uint32(ndr, ndr_flags, t);
792 }
793
794 /*
795   pull a time_t
796 */
797 _PUBLIC_ enum ndr_err_code ndr_pull_time_t(struct ndr_pull *ndr, int ndr_flags, time_t *t)
798 {
799         uint32_t tt;
800         NDR_CHECK(ndr_pull_uint32(ndr, ndr_flags, &tt));
801         *t = tt;
802         return NDR_ERR_SUCCESS;
803 }
804
805
806 /*
807   pull a ipv4address
808 */
809 _PUBLIC_ enum ndr_err_code ndr_pull_ipv4address(struct ndr_pull *ndr, int ndr_flags, const char **address)
810 {
811         uint32_t addr;
812         struct in_addr in;
813         NDR_CHECK(ndr_pull_uint32(ndr, ndr_flags, &addr));
814         in.s_addr = htonl(addr);
815         *address = talloc_strdup(ndr->current_mem_ctx, inet_ntoa(in));
816         NDR_ERR_HAVE_NO_MEMORY(*address);
817         return NDR_ERR_SUCCESS;
818 }
819
820 /*
821   push a ipv4address
822 */
823 _PUBLIC_ enum ndr_err_code ndr_push_ipv4address(struct ndr_push *ndr, int ndr_flags, const char *address)
824 {
825         uint32_t addr;
826         if (!is_ipaddress(address)) {
827                 return ndr_push_error(ndr, NDR_ERR_IPV4ADDRESS,
828                                       "Invalid IPv4 address: '%s'", 
829                                       address);
830         }
831         addr = inet_addr(address);
832         NDR_CHECK(ndr_push_uint32(ndr, ndr_flags, htonl(addr)));
833         return NDR_ERR_SUCCESS;
834 }
835
836 /*
837   print a ipv4address
838 */
839 _PUBLIC_ void ndr_print_ipv4address(struct ndr_print *ndr, const char *name, 
840                            const char *address)
841 {
842         ndr->print(ndr, "%-25s: %s", name, address);
843 }
844
845
846 _PUBLIC_ void ndr_print_struct(struct ndr_print *ndr, const char *name, const char *type)
847 {
848         ndr->print(ndr, "%s: struct %s", name, type);
849 }
850
851 _PUBLIC_ void ndr_print_enum(struct ndr_print *ndr, const char *name, const char *type, 
852                     const char *val, uint32_t value)
853 {
854         if (ndr->flags & LIBNDR_PRINT_ARRAY_HEX) {
855                 ndr->print(ndr, "%-25s: %s (0x%X)", name, val?val:"UNKNOWN_ENUM_VALUE", value);
856         } else {
857                 ndr->print(ndr, "%-25s: %s (%d)", name, val?val:"UNKNOWN_ENUM_VALUE", value);
858         }
859 }
860
861 _PUBLIC_ void ndr_print_bitmap_flag(struct ndr_print *ndr, size_t size, const char *flag_name, uint32_t flag, uint32_t value)
862 {
863         /* this is an attempt to support multi-bit bitmap masks */
864         value &= flag;
865
866         while (!(flag & 1)) {
867                 flag >>= 1;
868                 value >>= 1;
869         }       
870         if (flag == 1) {
871                 ndr->print(ndr, "   %d: %-25s", value, flag_name);
872         } else {
873                 ndr->print(ndr, "0x%02x: %-25s (%d)", value, flag_name, value);
874         }
875 }
876
877 _PUBLIC_ void ndr_print_int8(struct ndr_print *ndr, const char *name, int8_t v)
878 {
879         ndr->print(ndr, "%-25s: %d", name, v);
880 }
881
882 _PUBLIC_ void ndr_print_uint8(struct ndr_print *ndr, const char *name, uint8_t v)
883 {
884         ndr->print(ndr, "%-25s: 0x%02x (%u)", name, v, v);
885 }
886
887 _PUBLIC_ void ndr_print_int16(struct ndr_print *ndr, const char *name, int16_t v)
888 {
889         ndr->print(ndr, "%-25s: %d", name, v);
890 }
891
892 _PUBLIC_ void ndr_print_uint16(struct ndr_print *ndr, const char *name, uint16_t v)
893 {
894         ndr->print(ndr, "%-25s: 0x%04x (%u)", name, v, v);
895 }
896
897 _PUBLIC_ void ndr_print_int32(struct ndr_print *ndr, const char *name, int32_t v)
898 {
899         ndr->print(ndr, "%-25s: %d", name, v);
900 }
901
902 _PUBLIC_ void ndr_print_uint32(struct ndr_print *ndr, const char *name, uint32_t v)
903 {
904         ndr->print(ndr, "%-25s: 0x%08x (%u)", name, v, v);
905 }
906
907 _PUBLIC_ void ndr_print_int3264(struct ndr_print *ndr, const char *name, int32_t v)
908 {
909         ndr->print(ndr, "%-25s: %d", name, v);
910 }
911
912 _PUBLIC_ void ndr_print_uint3264(struct ndr_print *ndr, const char *name, uint32_t v)
913 {
914         ndr->print(ndr, "%-25s: 0x%08x (%u)", name, v, v);
915 }
916
917 _PUBLIC_ void ndr_print_udlong(struct ndr_print *ndr, const char *name, uint64_t v)
918 {
919         ndr->print(ndr, "%-25s: 0x%016llx (%llu)", name, (unsigned long long)v, (unsigned long long)v);
920 }
921
922 _PUBLIC_ void ndr_print_udlongr(struct ndr_print *ndr, const char *name, uint64_t v)
923 {
924         ndr_print_udlong(ndr, name, v);
925 }
926
927 _PUBLIC_ void ndr_print_dlong(struct ndr_print *ndr, const char *name, int64_t v)
928 {
929         ndr->print(ndr, "%-25s: 0x%016llx (%lld)", name, (unsigned long long)v, (long long)v);
930 }
931
932 _PUBLIC_ void ndr_print_double(struct ndr_print *ndr, const char *name, double v)
933 {
934         ndr->print(ndr, "%-25s: %f", name, v);
935 }
936
937 _PUBLIC_ void ndr_print_hyper(struct ndr_print *ndr, const char *name, uint64_t v)
938 {
939         ndr_print_dlong(ndr, name, v);
940 }
941
942 _PUBLIC_ void ndr_print_pointer(struct ndr_print *ndr, const char *name, void *v)
943 {
944         ndr->print(ndr, "%-25s: %p", name, v);
945 }
946
947 _PUBLIC_ void ndr_print_ptr(struct ndr_print *ndr, const char *name, const void *p)
948 {
949         if (p) {
950                 ndr->print(ndr, "%-25s: *", name);
951         } else {
952                 ndr->print(ndr, "%-25s: NULL", name);
953         }
954 }
955
956 _PUBLIC_ void ndr_print_NTTIME(struct ndr_print *ndr, const char *name, NTTIME t)
957 {
958         ndr->print(ndr, "%-25s: %s", name, nt_time_string(ndr, t));
959 }
960
961 _PUBLIC_ void ndr_print_NTTIME_1sec(struct ndr_print *ndr, const char *name, NTTIME t)
962 {
963         /* this is a standard NTTIME here
964          * as it's already converted in the pull/push code
965          */
966         ndr_print_NTTIME(ndr, name, t);
967 }
968
969 _PUBLIC_ void ndr_print_NTTIME_hyper(struct ndr_print *ndr, const char *name, NTTIME t)
970 {
971         ndr_print_NTTIME(ndr, name, t);
972 }
973
974 _PUBLIC_ void ndr_print_time_t(struct ndr_print *ndr, const char *name, time_t t)
975 {
976         if (t == (time_t)-1 || t == 0) {
977                 ndr->print(ndr, "%-25s: (time_t)%d", name, (int)t);
978         } else {
979                 ndr->print(ndr, "%-25s: %s", name, timestring(ndr, t));
980         }
981 }
982
983 _PUBLIC_ void ndr_print_union(struct ndr_print *ndr, const char *name, int level, const char *type)
984 {
985         if (ndr->flags & LIBNDR_PRINT_ARRAY_HEX) {
986                 ndr->print(ndr, "%-25s: union %s(case 0x%X)", name, type, level);
987         } else {
988                 ndr->print(ndr, "%-25s: union %s(case %d)", name, type, level);
989         }
990 }
991
992 _PUBLIC_ void ndr_print_bad_level(struct ndr_print *ndr, const char *name, uint16_t level)
993 {
994         ndr->print(ndr, "UNKNOWN LEVEL %u", level);
995 }
996
997 _PUBLIC_ void ndr_print_array_uint8(struct ndr_print *ndr, const char *name, 
998                            const uint8_t *data, uint32_t count)
999 {
1000         int i;
1001
1002         if (count <= 600 && (ndr->flags & LIBNDR_PRINT_ARRAY_HEX)) {
1003                 char s[1202];
1004                 for (i=0;i<count;i++) {
1005                         snprintf(&s[i*2], 3, "%02x", data[i]);
1006                 }
1007                 s[i*2] = 0;
1008                 ndr->print(ndr, "%-25s: %s", name, s);
1009                 return;
1010         }
1011
1012         ndr->print(ndr, "%s: ARRAY(%d)", name, count);
1013         ndr->depth++;
1014         for (i=0;i<count;i++) {
1015                 char *idx=NULL;
1016                 if (asprintf(&idx, "[%d]", i) != -1) {
1017                         ndr_print_uint8(ndr, idx, data[i]);
1018                         free(idx);
1019                 }
1020         }
1021         ndr->depth--;   
1022 }
1023
1024 static void ndr_print_asc(struct ndr_print *ndr, const uint8_t *buf, int len)
1025 {
1026         int i;
1027         for (i=0;i<len;i++)
1028                 ndr->print(ndr, "%c", isprint(buf[i])?buf[i]:'.');
1029 }
1030
1031 /*
1032   ndr_print version of dump_data()
1033  */
1034 static void ndr_dump_data(struct ndr_print *ndr, const uint8_t *buf, int len)
1035 {
1036         int i=0;
1037
1038         ndr->no_newline = true;
1039
1040         for (i=0;i<len;) {
1041                 if (i%16 == 0 && i<len) {
1042                         ndr->print(ndr, "[%04X] ",i);
1043                 }
1044
1045                 ndr->print(ndr, "%02X ",(int)buf[i]);
1046                 i++;
1047                 if (i%8 == 0) ndr->print(ndr,"  ");
1048                 if (i%16 == 0) {
1049                         ndr_print_asc(ndr,&buf[i-16],8); ndr->print(ndr," ");
1050                         ndr_print_asc(ndr,&buf[i-8],8); ndr->print(ndr, "\n");
1051                 }
1052         }
1053
1054         if (i%16) {
1055                 int n;
1056                 n = 16 - (i%16);
1057                 ndr->print(ndr, " ");
1058                 if (n>8) ndr->print(ndr," ");
1059                 while (n--) ndr->print(ndr,"   ");
1060                 n = MIN(8,i%16);
1061                 ndr_print_asc(ndr,&buf[i-(i%16)],n); ndr->print(ndr, " ");
1062                 n = (i%16) - n;
1063                 if (n>0) ndr_print_asc(ndr,&buf[i-n],n);
1064                 ndr->print(ndr,"\n");
1065         }
1066
1067         ndr->no_newline = false;
1068 }
1069
1070
1071 _PUBLIC_ void ndr_print_DATA_BLOB(struct ndr_print *ndr, const char *name, DATA_BLOB r)
1072 {
1073         ndr->print(ndr, "%-25s: DATA_BLOB length=%u", name, (unsigned)r.length);
1074         if (r.length) {
1075                 ndr_dump_data(ndr, r.data, r.length);
1076         }
1077 }
1078
1079
1080 /*
1081   push a DATA_BLOB onto the wire. 
1082 */
1083 _PUBLIC_ enum ndr_err_code ndr_push_DATA_BLOB(struct ndr_push *ndr, int ndr_flags, DATA_BLOB blob)
1084 {
1085         if (ndr->flags & LIBNDR_ALIGN_FLAGS) {
1086                 if (ndr->flags & LIBNDR_FLAG_ALIGN2) {
1087                         blob.length = NDR_ALIGN(ndr, 2);
1088                 } else if (ndr->flags & LIBNDR_FLAG_ALIGN4) {
1089                         blob.length = NDR_ALIGN(ndr, 4);
1090                 } else if (ndr->flags & LIBNDR_FLAG_ALIGN8) {
1091                         blob.length = NDR_ALIGN(ndr, 8);
1092                 }
1093                 NDR_PUSH_ALLOC_SIZE(ndr, blob.data, blob.length);
1094                 data_blob_clear(&blob);
1095         } else if (!(ndr->flags & LIBNDR_FLAG_REMAINING)) {
1096                 NDR_CHECK(ndr_push_uint32(ndr, NDR_SCALARS, blob.length));
1097         }
1098         NDR_CHECK(ndr_push_bytes(ndr, blob.data, blob.length));
1099         return NDR_ERR_SUCCESS;
1100 }
1101
1102 /*
1103   pull a DATA_BLOB from the wire. 
1104 */
1105 _PUBLIC_ enum ndr_err_code ndr_pull_DATA_BLOB(struct ndr_pull *ndr, int ndr_flags, DATA_BLOB *blob)
1106 {
1107         uint32_t length = 0;
1108
1109         if (ndr->flags & LIBNDR_ALIGN_FLAGS) {
1110                 if (ndr->flags & LIBNDR_FLAG_ALIGN2) {
1111                         length = NDR_ALIGN(ndr, 2);
1112                 } else if (ndr->flags & LIBNDR_FLAG_ALIGN4) {
1113                         length = NDR_ALIGN(ndr, 4);
1114                 } else if (ndr->flags & LIBNDR_FLAG_ALIGN8) {
1115                         length = NDR_ALIGN(ndr, 8);
1116                 }
1117                 if (ndr->data_size - ndr->offset < length) {
1118                         length = ndr->data_size - ndr->offset;
1119                 }
1120         } else if (ndr->flags & LIBNDR_FLAG_REMAINING) {
1121                 length = ndr->data_size - ndr->offset;
1122         } else {
1123                 NDR_CHECK(ndr_pull_uint32(ndr, NDR_SCALARS, &length));
1124         }
1125         NDR_PULL_NEED_BYTES(ndr, length);
1126         *blob = data_blob_talloc(ndr->current_mem_ctx, ndr->data+ndr->offset, length);
1127         ndr->offset += length;
1128         return NDR_ERR_SUCCESS;
1129 }
1130
1131 _PUBLIC_ uint32_t ndr_size_DATA_BLOB(int ret, const DATA_BLOB *data, int flags)
1132 {
1133         if (!data) return ret;
1134         return ret + data->length;
1135 }