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