Merge branch 'v3-2-stable' into my_branch
[ira/wip.git] / source3 / 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
24 #define NDR_SVAL(ndr, ofs) (NDR_BE(ndr)?RSVAL(ndr->data,ofs):SVAL(ndr->data,ofs))
25 #define NDR_IVAL(ndr, ofs) (NDR_BE(ndr)?RIVAL(ndr->data,ofs):IVAL(ndr->data,ofs))
26 #define NDR_IVALS(ndr, ofs) (NDR_BE(ndr)?RIVALS(ndr->data,ofs):IVALS(ndr->data,ofs))
27 #define NDR_SSVAL(ndr, ofs, v) do { if (NDR_BE(ndr))  { RSSVAL(ndr->data,ofs,v); } else SSVAL(ndr->data,ofs,v); } while (0)
28 #define NDR_SIVAL(ndr, ofs, v) do { if (NDR_BE(ndr))  { RSIVAL(ndr->data,ofs,v); } else SIVAL(ndr->data,ofs,v); } while (0)
29 #define NDR_SIVALS(ndr, ofs, v) do { if (NDR_BE(ndr))  { RSIVALS(ndr->data,ofs,v); } else SIVALS(ndr->data,ofs,v); } while (0)
30
31
32 /*
33   check for data leaks from the server by looking for non-zero pad bytes
34   these could also indicate that real structure elements have been
35   mistaken for padding in the IDL
36 */
37 void ndr_check_padding(struct ndr_pull *ndr, size_t n)
38 {
39         size_t ofs2 = (ndr->offset + (n-1)) & ~(n-1);
40         int i;
41         for (i=ndr->offset;i<ofs2;i++) {
42                 if (ndr->data[i] != 0) {
43                         break;
44                 }
45         }
46         if (i<ofs2) {
47                 DEBUG(0,("WARNING: Non-zero padding to %d: ", (int)n));
48                 for (i=ndr->offset;i<ofs2;i++) {
49                         DEBUG(0,("%02x ", ndr->data[i]));
50                 }
51                 DEBUG(0,("\n"));
52         }
53
54 }
55
56 /*
57   parse a int8_t
58 */
59 NTSTATUS ndr_pull_int8(struct ndr_pull *ndr, int ndr_flags, int8_t *v)
60 {
61         NDR_PULL_NEED_BYTES(ndr, 1);
62         *v = (int8_t)CVAL(ndr->data, ndr->offset);
63         ndr->offset += 1;
64         return NT_STATUS_OK;
65 }
66
67 /*
68   parse a uint8_t
69 */
70 NTSTATUS ndr_pull_uint8(struct ndr_pull *ndr, int ndr_flags, uint8_t *v)
71 {
72         NDR_PULL_NEED_BYTES(ndr, 1);
73         *v = CVAL(ndr->data, ndr->offset);
74         ndr->offset += 1;
75         return NT_STATUS_OK;
76 }
77
78 /*
79   parse a int16_t
80 */
81 NTSTATUS ndr_pull_int16(struct ndr_pull *ndr, int ndr_flags, int16_t *v)
82 {
83         NDR_PULL_ALIGN(ndr, 2);
84         NDR_PULL_NEED_BYTES(ndr, 2);
85         *v = (uint16_t)NDR_SVAL(ndr, ndr->offset);
86         ndr->offset += 2;
87         return NT_STATUS_OK;
88 }
89
90 /*
91   parse a uint16_t
92 */
93 NTSTATUS ndr_pull_uint16(struct ndr_pull *ndr, int ndr_flags, uint16_t *v)
94 {
95         NDR_PULL_ALIGN(ndr, 2);
96         NDR_PULL_NEED_BYTES(ndr, 2);
97         *v = NDR_SVAL(ndr, ndr->offset);
98         ndr->offset += 2;
99         return NT_STATUS_OK;
100 }
101
102 /*
103   parse a int32_t
104 */
105 NTSTATUS ndr_pull_int32(struct ndr_pull *ndr, int ndr_flags, int32_t *v)
106 {
107         NDR_PULL_ALIGN(ndr, 4);
108         NDR_PULL_NEED_BYTES(ndr, 4);
109         *v = NDR_IVALS(ndr, ndr->offset);
110         ndr->offset += 4;
111         return NT_STATUS_OK;
112 }
113
114 /*
115   parse a uint32_t
116 */
117 NTSTATUS ndr_pull_uint32(struct ndr_pull *ndr, int ndr_flags, uint32_t *v)
118 {
119         NDR_PULL_ALIGN(ndr, 4);
120         NDR_PULL_NEED_BYTES(ndr, 4);
121         *v = NDR_IVAL(ndr, ndr->offset);
122         ndr->offset += 4;
123         return NT_STATUS_OK;
124 }
125
126 /*
127   parse a pointer referent identifier
128 */
129 NTSTATUS ndr_pull_generic_ptr(struct ndr_pull *ndr, uint32_t *v)
130 {
131         NTSTATUS status;
132         status = ndr_pull_uint32(ndr, NDR_SCALARS, v);
133         if (NT_STATUS_IS_OK(status) && *v != 0) {
134                 ndr->ptr_count++;
135         }
136         return status;
137 }
138
139 /*
140   parse a ref pointer referent identifier
141 */
142 NTSTATUS ndr_pull_ref_ptr(struct ndr_pull *ndr, uint32_t *v)
143 {
144         NDR_CHECK(ndr_pull_uint32(ndr, NDR_SCALARS, v));
145         /* ref pointers always point to data */
146         *v = 1;
147         return NT_STATUS_OK;
148 }
149
150 /*
151   parse a udlong
152 */
153 NTSTATUS ndr_pull_udlong(struct ndr_pull *ndr, int ndr_flags, uint64_t *v)
154 {
155         NDR_PULL_ALIGN(ndr, 4);
156         NDR_PULL_NEED_BYTES(ndr, 8);
157         *v = NDR_IVAL(ndr, ndr->offset);
158         *v |= (uint64_t)(NDR_IVAL(ndr, ndr->offset+4)) << 32;
159         ndr->offset += 8;
160         return NT_STATUS_OK;
161 }
162
163 /*
164   parse a udlongr
165 */
166 NTSTATUS ndr_pull_udlongr(struct ndr_pull *ndr, int ndr_flags, uint64_t *v)
167 {
168         NDR_PULL_ALIGN(ndr, 4);
169         NDR_PULL_NEED_BYTES(ndr, 8);
170         *v = ((uint64_t)NDR_IVAL(ndr, ndr->offset)) << 32;
171         *v |= NDR_IVAL(ndr, ndr->offset+4);
172         ndr->offset += 8;
173         return NT_STATUS_OK;
174 }
175
176 /*
177   parse a dlong
178 */
179 NTSTATUS ndr_pull_dlong(struct ndr_pull *ndr, int ndr_flags, int64_t *v)
180 {
181         return ndr_pull_udlong(ndr, ndr_flags, (uint64_t *)v);
182 }
183
184 /*
185   parse a hyper
186 */
187 NTSTATUS ndr_pull_hyper(struct ndr_pull *ndr, int ndr_flags, uint64_t *v)
188 {
189         NDR_PULL_ALIGN(ndr, 8);
190         return ndr_pull_udlong(ndr, ndr_flags, v);
191 }
192
193 /*
194   parse a pointer
195 */
196 NTSTATUS ndr_pull_pointer(struct ndr_pull *ndr, int ndr_flags, void* *v)
197 {
198         intptr_t h;
199         NDR_PULL_ALIGN(ndr, sizeof(h));
200         NDR_PULL_NEED_BYTES(ndr, sizeof(h));
201         memcpy(&h, ndr->data+ndr->offset, sizeof(h));
202         ndr->offset += sizeof(h);
203         *v = (void *)h;
204         return NT_STATUS_OK;    
205 }
206
207 /*
208   pull a NTSTATUS
209 */
210 NTSTATUS ndr_pull_NTSTATUS(struct ndr_pull *ndr, int ndr_flags, NTSTATUS *status)
211 {
212         uint32_t v;
213         NDR_CHECK(ndr_pull_uint32(ndr, NDR_SCALARS, &v));
214         *status = NT_STATUS(v);
215         return NT_STATUS_OK;
216 }
217
218 /*
219   push a NTSTATUS
220 */
221 NTSTATUS ndr_push_NTSTATUS(struct ndr_push *ndr, int ndr_flags, NTSTATUS status)
222 {
223         return ndr_push_uint32(ndr, ndr_flags, NT_STATUS_V(status));
224 }
225
226 void ndr_print_NTSTATUS(struct ndr_print *ndr, const char *name, NTSTATUS r)
227 {
228         ndr->print(ndr, "%-25s: %s", name, nt_errstr(r));
229 }
230
231 /*
232   pull a WERROR
233 */
234 NTSTATUS ndr_pull_WERROR(struct ndr_pull *ndr, int ndr_flags, WERROR *status)
235 {
236         uint32_t v;
237         NDR_CHECK(ndr_pull_uint32(ndr, NDR_SCALARS, &v));
238         *status = W_ERROR(v);
239         return NT_STATUS_OK;
240 }
241
242 /*
243   push a WERROR
244 */
245 NTSTATUS ndr_push_WERROR(struct ndr_push *ndr, int ndr_flags, WERROR status)
246 {
247         return ndr_push_uint32(ndr, NDR_SCALARS, W_ERROR_V(status));
248 }
249
250 void ndr_print_WERROR(struct ndr_print *ndr, const char *name, WERROR r)
251 {
252         ndr->print(ndr, "%-25s: %s", name, dos_errstr(r));
253 }
254
255 /*
256   parse a set of bytes
257 */
258 NTSTATUS ndr_pull_bytes(struct ndr_pull *ndr, uint8_t *data, uint32_t n)
259 {
260         NDR_PULL_NEED_BYTES(ndr, n);
261         memcpy(data, ndr->data + ndr->offset, n);
262         ndr->offset += n;
263         return NT_STATUS_OK;
264 }
265
266 /*
267   pull an array of uint8
268 */
269 NTSTATUS ndr_pull_array_uint8(struct ndr_pull *ndr, int ndr_flags, uint8_t *data, uint32_t n)
270 {
271         if (!(ndr_flags & NDR_SCALARS)) {
272                 return NT_STATUS_OK;
273         }
274         return ndr_pull_bytes(ndr, data, n);
275 }
276
277 /*
278   push a int8_t
279 */
280 NTSTATUS ndr_push_int8(struct ndr_push *ndr, int ndr_flags, int8_t v)
281 {
282         NDR_PUSH_NEED_BYTES(ndr, 1);
283         SCVAL(ndr->data, ndr->offset, (uint8_t)v);
284         ndr->offset += 1;
285         return NT_STATUS_OK;
286 }
287
288 /*
289   push a uint8_t
290 */
291 NTSTATUS ndr_push_uint8(struct ndr_push *ndr, int ndr_flags, uint8_t v)
292 {
293         NDR_PUSH_NEED_BYTES(ndr, 1);
294         SCVAL(ndr->data, ndr->offset, v);
295         ndr->offset += 1;
296         return NT_STATUS_OK;
297 }
298
299 /*
300   push a int16_t
301 */
302 NTSTATUS ndr_push_int16(struct ndr_push *ndr, int ndr_flags, int16_t v)
303 {
304         NDR_PUSH_ALIGN(ndr, 2);
305         NDR_PUSH_NEED_BYTES(ndr, 2);
306         NDR_SSVAL(ndr, ndr->offset, (uint16_t)v);
307         ndr->offset += 2;
308         return NT_STATUS_OK;
309 }
310
311 /*
312   push a uint16_t
313 */
314 NTSTATUS ndr_push_uint16(struct ndr_push *ndr, int ndr_flags, uint16_t v)
315 {
316         NDR_PUSH_ALIGN(ndr, 2);
317         NDR_PUSH_NEED_BYTES(ndr, 2);
318         NDR_SSVAL(ndr, ndr->offset, v);
319         ndr->offset += 2;
320         return NT_STATUS_OK;
321 }
322
323 /*
324   push a int32_t
325 */
326 NTSTATUS ndr_push_int32(struct ndr_push *ndr, int ndr_flags, int32_t v)
327 {
328         NDR_PUSH_ALIGN(ndr, 4);
329         NDR_PUSH_NEED_BYTES(ndr, 4);
330         NDR_SIVALS(ndr, ndr->offset, v);
331         ndr->offset += 4;
332         return NT_STATUS_OK;
333 }
334
335 /*
336   push a uint32_t
337 */
338 NTSTATUS ndr_push_uint32(struct ndr_push *ndr, int ndr_flags, uint32_t v)
339 {
340         NDR_PUSH_ALIGN(ndr, 4);
341         NDR_PUSH_NEED_BYTES(ndr, 4);
342         NDR_SIVAL(ndr, ndr->offset, v);
343         ndr->offset += 4;
344         return NT_STATUS_OK;
345 }
346
347 /*
348   push a udlong
349 */
350 NTSTATUS ndr_push_udlong(struct ndr_push *ndr, int ndr_flags, uint64_t v)
351 {
352         NDR_PUSH_ALIGN(ndr, 4);
353         NDR_PUSH_NEED_BYTES(ndr, 8);
354         NDR_SIVAL(ndr, ndr->offset, (v & 0xFFFFFFFF));
355         NDR_SIVAL(ndr, ndr->offset+4, (v>>32));
356         ndr->offset += 8;
357         return NT_STATUS_OK;
358 }
359
360 /*
361   push a udlongr
362 */
363 NTSTATUS ndr_push_udlongr(struct ndr_push *ndr, int ndr_flags, uint64_t v)
364 {
365         NDR_PUSH_ALIGN(ndr, 4);
366         NDR_PUSH_NEED_BYTES(ndr, 8);
367         NDR_SIVAL(ndr, ndr->offset, (v>>32));
368         NDR_SIVAL(ndr, ndr->offset+4, (v & 0xFFFFFFFF));
369         ndr->offset += 8;
370         return NT_STATUS_OK;
371 }
372
373 /*
374   push a dlong
375 */
376 NTSTATUS ndr_push_dlong(struct ndr_push *ndr, int ndr_flags, int64_t v)
377 {
378         return ndr_push_udlong(ndr, NDR_SCALARS, (uint64_t)v);
379 }
380
381 /*
382   push a hyper
383 */
384 NTSTATUS ndr_push_hyper(struct ndr_push *ndr, int ndr_flags, uint64_t v)
385 {
386         NDR_PUSH_ALIGN(ndr, 8);
387         return ndr_push_udlong(ndr, NDR_SCALARS, v);
388 }
389
390 /*
391   push a pointer
392 */
393 NTSTATUS ndr_push_pointer(struct ndr_push *ndr, int ndr_flags, void* v)
394 {
395         intptr_t h = (intptr_t)v;
396         NDR_PUSH_ALIGN(ndr, sizeof(h));
397         NDR_PUSH_NEED_BYTES(ndr, sizeof(h));
398         memcpy(ndr->data+ndr->offset, &h, sizeof(h));
399         ndr->offset += sizeof(h);
400         return NT_STATUS_OK;    
401 }
402
403 NTSTATUS ndr_push_align(struct ndr_push *ndr, size_t size)
404 {
405         NDR_PUSH_ALIGN(ndr, size);
406         return NT_STATUS_OK;
407 }
408
409 NTSTATUS ndr_pull_align(struct ndr_pull *ndr, size_t size)
410 {
411         NDR_PULL_ALIGN(ndr, size);
412         return NT_STATUS_OK;
413 }
414
415 /*
416   push some bytes
417 */
418 NTSTATUS ndr_push_bytes(struct ndr_push *ndr, const uint8_t *data, uint32_t n)
419 {
420         NDR_PUSH_NEED_BYTES(ndr, n);
421         memcpy(ndr->data + ndr->offset, data, n);
422         ndr->offset += n;
423         return NT_STATUS_OK;
424 }
425
426 /*
427   push some zero bytes
428 */
429 NTSTATUS ndr_push_zero(struct ndr_push *ndr, uint32_t n)
430 {
431         NDR_PUSH_NEED_BYTES(ndr, n);
432         memset(ndr->data + ndr->offset, 0, n);
433         ndr->offset += n;
434         return NT_STATUS_OK;
435 }
436
437 /*
438   push an array of uint8
439 */
440 NTSTATUS ndr_push_array_uint8(struct ndr_push *ndr, int ndr_flags, const uint8_t *data, uint32_t n)
441 {
442         if (!(ndr_flags & NDR_SCALARS)) {
443                 return NT_STATUS_OK;
444         }
445         return ndr_push_bytes(ndr, data, n);
446 }
447
448 /*
449   save the current position
450  */
451 void ndr_push_save(struct ndr_push *ndr, struct ndr_push_save *save)
452 {
453         save->offset = ndr->offset;
454 }
455
456 /*
457   restore the position
458  */
459 void ndr_push_restore(struct ndr_push *ndr, struct ndr_push_save *save)
460 {
461         ndr->offset = save->offset;
462 }
463
464 /*
465   push a unique non-zero value if a pointer is non-NULL, otherwise 0
466 */
467 NTSTATUS ndr_push_unique_ptr(struct ndr_push *ndr, const void *p)
468 {
469         uint32_t ptr = 0;
470         if (p) {
471                 ptr = ndr->ptr_count * 4;
472                 ptr |= 0x00020000;
473                 ndr->ptr_count++;
474         }
475         return ndr_push_uint32(ndr, NDR_SCALARS, ptr);
476 }
477
478 /*
479   push a 'simple' full non-zero value if a pointer is non-NULL, otherwise 0
480 */
481 NTSTATUS ndr_push_full_ptr(struct ndr_push *ndr, const void *p)
482 {
483         uint32_t ptr = 0;
484         if (p) {
485                 /* Check if the pointer already exists and has an id */
486                 ptr = ndr_token_peek(&ndr->full_ptr_list, p);
487                 if (ptr == 0) {
488                         ndr->ptr_count++;
489                         ptr = ndr->ptr_count;
490                         ndr_token_store(ndr, &ndr->full_ptr_list, p, ptr);
491                 }
492         }
493         return ndr_push_uint32(ndr, NDR_SCALARS, ptr);
494 }
495
496 /*
497   push always a 0, if a pointer is NULL it's a fatal error
498 */
499 NTSTATUS ndr_push_ref_ptr(struct ndr_push *ndr)
500 {
501         return ndr_push_uint32(ndr, NDR_SCALARS, 0xAEF1AEF1);
502 }
503
504 /*
505   push a NTTIME
506 */
507 NTSTATUS ndr_push_NTTIME(struct ndr_push *ndr, int ndr_flags, NTTIME t)
508 {
509         NDR_CHECK(ndr_push_udlong(ndr, ndr_flags, t));
510         return NT_STATUS_OK;
511 }
512
513 /*
514   pull a NTTIME
515 */
516 NTSTATUS ndr_pull_NTTIME(struct ndr_pull *ndr, int ndr_flags, NTTIME *t)
517 {
518         NDR_CHECK(ndr_pull_udlong(ndr, ndr_flags, t));
519         return NT_STATUS_OK;
520 }
521
522 /*
523   push a NTTIME
524 */
525 NTSTATUS ndr_push_NTTIME_1sec(struct ndr_push *ndr, int ndr_flags, NTTIME t)
526 {
527         t /= 10000000;
528         NDR_CHECK(ndr_push_hyper(ndr, ndr_flags, t));
529         return NT_STATUS_OK;
530 }
531
532 /*
533   pull a NTTIME_1sec
534 */
535 NTSTATUS ndr_pull_NTTIME_1sec(struct ndr_pull *ndr, int ndr_flags, NTTIME *t)
536 {
537         NDR_CHECK(ndr_pull_hyper(ndr, ndr_flags, t));
538         (*t) *= 10000000;
539         return NT_STATUS_OK;
540 }
541
542 /*
543   pull a NTTIME_hyper
544 */
545 NTSTATUS ndr_pull_NTTIME_hyper(struct ndr_pull *ndr, int ndr_flags, NTTIME *t)
546 {
547         NDR_CHECK(ndr_pull_hyper(ndr, ndr_flags, t));
548         return NT_STATUS_OK;
549 }
550
551 /*
552   push a NTTIME_hyper
553 */
554 NTSTATUS ndr_push_NTTIME_hyper(struct ndr_push *ndr, int ndr_flags, NTTIME t)
555 {
556         NDR_CHECK(ndr_push_hyper(ndr, ndr_flags, t));
557         return NT_STATUS_OK;
558 }
559
560 /*
561   push a time_t
562 */
563 NTSTATUS ndr_push_time_t(struct ndr_push *ndr, int ndr_flags, time_t t)
564 {
565         return ndr_push_uint32(ndr, ndr_flags, t);
566 }
567
568 /*
569   pull a time_t
570 */
571 NTSTATUS ndr_pull_time_t(struct ndr_pull *ndr, int ndr_flags, time_t *t)
572 {
573         uint32_t tt;
574         NDR_CHECK(ndr_pull_uint32(ndr, ndr_flags, &tt));
575         *t = tt;
576         return NT_STATUS_OK;
577 }
578
579 /*
580   pull a ipv4address
581 */
582 NTSTATUS ndr_pull_ipv4address(struct ndr_pull *ndr, int ndr_flags, const char **address)
583 {
584         struct in_addr in;
585         NDR_CHECK(ndr_pull_uint32(ndr, ndr_flags, &in.s_addr));
586         in.s_addr = htonl(in.s_addr);
587         *address = talloc_strdup(ndr->current_mem_ctx, inet_ntoa(in));
588         NT_STATUS_HAVE_NO_MEMORY(*address);
589         return NT_STATUS_OK;
590 }
591
592 /*
593   push a ipv4address
594 */
595 NTSTATUS ndr_push_ipv4address(struct ndr_push *ndr, int ndr_flags, const char *address)
596 {
597         uint32_t addr;
598         if (!is_ipaddress_v4(address)) {
599                 return ndr_push_error(ndr, NDR_ERR_IPV4ADDRESS,
600                                       "Invalid IPv4 address: '%s'", 
601                                       address);
602         }
603         addr = inet_addr(address);
604         NDR_CHECK(ndr_push_uint32(ndr, ndr_flags, htonl(addr)));
605         return NT_STATUS_OK;
606 }
607
608 /*
609   print a ipv4address
610 */
611 void ndr_print_ipv4address(struct ndr_print *ndr, const char *name, 
612                            const char *address)
613 {
614         ndr->print(ndr, "%-25s: %s", name, address);
615 }
616
617 void ndr_print_struct(struct ndr_print *ndr, const char *name, const char *type)
618 {
619         ndr->print(ndr, "%s: struct %s", name, type);
620 }
621
622 void ndr_print_enum(struct ndr_print *ndr, const char *name, const char *type, 
623                     const char *val, uint32_t value)
624 {
625         if (ndr->flags & LIBNDR_PRINT_ARRAY_HEX) {
626                 ndr->print(ndr, "%-25s: %s (0x%X)", name, val?val:"UNKNOWN_ENUM_VALUE", value);
627         } else {
628                 ndr->print(ndr, "%-25s: %s (%d)", name, val?val:"UNKNOWN_ENUM_VALUE", value);
629         }
630 }
631
632 void ndr_print_bitmap_flag(struct ndr_print *ndr, size_t size, const char *flag_name, uint32_t flag, uint32_t value)
633 {
634         /* this is an attempt to support multi-bit bitmap masks */
635         value &= flag;
636
637         while (!(flag & 1)) {
638                 flag >>= 1;
639                 value >>= 1;
640         }       
641         if (flag == 1) {
642                 ndr->print(ndr, "   %d: %-25s", value, flag_name);
643         } else {
644                 ndr->print(ndr, "0x%02x: %-25s (%d)", value, flag_name, value);
645         }
646 }
647
648 void ndr_print_int8(struct ndr_print *ndr, const char *name, int8_t v)
649 {
650         ndr->print(ndr, "%-25s: %d", name, v);
651 }
652
653 void ndr_print_uint8(struct ndr_print *ndr, const char *name, uint8_t v)
654 {
655         ndr->print(ndr, "%-25s: 0x%02x (%u)", name, v, v);
656 }
657
658 void ndr_print_int16(struct ndr_print *ndr, const char *name, int16_t v)
659 {
660         ndr->print(ndr, "%-25s: %d", name, v);
661 }
662
663 void ndr_print_uint16(struct ndr_print *ndr, const char *name, uint16_t v)
664 {
665         ndr->print(ndr, "%-25s: 0x%04x (%u)", name, v, v);
666 }
667
668 void ndr_print_int32(struct ndr_print *ndr, const char *name, int32_t v)
669 {
670         ndr->print(ndr, "%-25s: %d", name, v);
671 }
672
673 void ndr_print_uint32(struct ndr_print *ndr, const char *name, uint32_t v)
674 {
675         ndr->print(ndr, "%-25s: 0x%08x (%u)", name, v, v);
676 }
677
678 void ndr_print_udlong(struct ndr_print *ndr, const char *name, uint64_t v)
679 {
680         ndr->print(ndr, "%-25s: 0x%016llx (%llu)", name, v, v);
681 }
682
683 void ndr_print_udlongr(struct ndr_print *ndr, const char *name, uint64_t v)
684 {
685         ndr_print_udlong(ndr, name, v);
686 }
687
688 void ndr_print_dlong(struct ndr_print *ndr, const char *name, int64_t v)
689 {
690         ndr->print(ndr, "%-25s: 0x%016llx (%lld)", name, v, v);
691 }
692
693 void ndr_print_hyper(struct ndr_print *ndr, const char *name, uint64_t v)
694 {
695         ndr_print_dlong(ndr, name, v);
696 }
697
698 void ndr_print_pointer(struct ndr_print *ndr, const char *name, void *v)
699 {
700         ndr->print(ndr, "%-25s: %p", name, v);
701 }
702
703 void ndr_print_ptr(struct ndr_print *ndr, const char *name, const void *p)
704 {
705         if (p) {
706                 ndr->print(ndr, "%-25s: *", name);
707         } else {
708                 ndr->print(ndr, "%-25s: NULL", name);
709         }
710 }
711
712 void ndr_print_NTTIME(struct ndr_print *ndr, const char *name, NTTIME t)
713 {
714         ndr->print(ndr, "%-25s: %s", name, nt_time_string(ndr, t));
715 }
716
717 void ndr_print_NTTIME_1sec(struct ndr_print *ndr, const char *name, NTTIME t)
718 {
719         /* this is a standard NTTIME here
720          * as it's already converted in the pull/push code
721          */
722         ndr_print_NTTIME(ndr, name, t);
723 }
724
725 void ndr_print_NTTIME_hyper(struct ndr_print *ndr, const char *name, NTTIME t)
726 {
727         ndr_print_NTTIME(ndr, name, t);
728 }
729
730 void ndr_print_time_t(struct ndr_print *ndr, const char *name, time_t t)
731 {
732         if (t == (time_t)-1 || t == 0) {
733                 ndr->print(ndr, "%-25s: (time_t)%d", name, (int)t);
734         } else {
735                 ndr->print(ndr, "%-25s: %s", name, timestring(ndr, t));
736         }
737 }
738
739 void ndr_print_union(struct ndr_print *ndr, const char *name, int level, const char *type)
740 {
741         if (ndr->flags & LIBNDR_PRINT_ARRAY_HEX) {
742                 ndr->print(ndr, "%-25s: union %s(case 0x%X)", name, type, level);
743         } else {
744                 ndr->print(ndr, "%-25s: union %s(case %d)", name, type, level);
745         }
746 }
747
748 void ndr_print_bad_level(struct ndr_print *ndr, const char *name, uint16_t level)
749 {
750         ndr->print(ndr, "UNKNOWN LEVEL %u", level);
751 }
752
753 void ndr_print_array_uint8(struct ndr_print *ndr, const char *name, 
754                            const uint8_t *data, uint32_t count)
755 {
756         int i;
757
758         if (count <= 600 && (ndr->flags & LIBNDR_PRINT_ARRAY_HEX)) {
759                 char s[1202];
760                 for (i=0;i<count;i++) {
761                         snprintf(&s[i*2], 3, "%02x", data[i]);
762                 }
763                 s[i*2] = 0;
764                 ndr->print(ndr, "%-25s: %s", name, s);
765                 return;
766         }
767
768         ndr->print(ndr, "%s: ARRAY(%d)", name, count);
769         ndr->depth++;
770         for (i=0;i<count;i++) {
771                 char *idx=NULL;
772                 asprintf(&idx, "[%d]", i);
773                 if (idx) {
774                         ndr_print_uint8(ndr, idx, data[i]);
775                         free(idx);
776                 }
777         }
778         ndr->depth--;   
779 }
780
781 void ndr_print_DATA_BLOB(struct ndr_print *ndr, const char *name, DATA_BLOB r)
782 {
783         ndr->print(ndr, "%-25s: DATA_BLOB length=%u", name, r.length);
784         if (r.length) {
785                 dump_data(10, r.data, r.length);
786         }
787 }
788
789
790 /*
791   push a DATA_BLOB onto the wire. 
792 */
793 NTSTATUS ndr_push_DATA_BLOB(struct ndr_push *ndr, int ndr_flags, DATA_BLOB blob)
794 {
795         if (ndr->flags & LIBNDR_ALIGN_FLAGS) {
796                 if (ndr->flags & LIBNDR_FLAG_ALIGN2) {
797                         blob.length = NDR_ALIGN(ndr, 2);
798                 } else if (ndr->flags & LIBNDR_FLAG_ALIGN4) {
799                         blob.length = NDR_ALIGN(ndr, 4);
800                 } else if (ndr->flags & LIBNDR_FLAG_ALIGN8) {
801                         blob.length = NDR_ALIGN(ndr, 8);
802                 }
803                 NDR_PUSH_ALLOC_SIZE(ndr, blob.data, blob.length);
804                 data_blob_clear(&blob);
805         } else if (!(ndr->flags & LIBNDR_FLAG_REMAINING)) {
806                 NDR_CHECK(ndr_push_uint32(ndr, NDR_SCALARS, blob.length));
807         }
808         NDR_CHECK(ndr_push_bytes(ndr, blob.data, blob.length));
809         return NT_STATUS_OK;
810 }
811
812 /*
813   pull a DATA_BLOB from the wire. 
814 */
815 NTSTATUS ndr_pull_DATA_BLOB(struct ndr_pull *ndr, int ndr_flags, DATA_BLOB *blob)
816 {
817         uint32_t length = 0;
818
819         if (ndr->flags & LIBNDR_ALIGN_FLAGS) {
820                 if (ndr->flags & LIBNDR_FLAG_ALIGN2) {
821                         length = NDR_ALIGN(ndr, 2);
822                 } else if (ndr->flags & LIBNDR_FLAG_ALIGN4) {
823                         length = NDR_ALIGN(ndr, 4);
824                 } else if (ndr->flags & LIBNDR_FLAG_ALIGN8) {
825                         length = NDR_ALIGN(ndr, 8);
826                 }
827                 if (ndr->data_size - ndr->offset < length) {
828                         length = ndr->data_size - ndr->offset;
829                 }
830         } else if (ndr->flags & LIBNDR_FLAG_REMAINING) {
831                 length = ndr->data_size - ndr->offset;
832         } else {
833                 NDR_CHECK(ndr_pull_uint32(ndr, NDR_SCALARS, &length));
834         }
835         NDR_PULL_NEED_BYTES(ndr, length);
836         *blob = data_blob_talloc(ndr->current_mem_ctx, ndr->data+ndr->offset, length);
837         ndr->offset += length;
838         return NT_STATUS_OK;
839 }
840
841 uint32_t ndr_size_DATA_BLOB(int ret, const DATA_BLOB *data, int flags)
842 {
843         if (!data) return ret;
844         return ret + data->length;
845 }