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