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