5eecb1d60bb05499c3d0e50d6d97053fca15a261
[samba.git] / source4 / 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 2 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 #include "system/network.h"
25
26 #define NDR_BE(ndr) (((ndr)->flags & (LIBNDR_FLAG_BIGENDIAN|LIBNDR_FLAG_LITTLE_ENDIAN)) == LIBNDR_FLAG_BIGENDIAN)
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 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: ", 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 uint8
61 */
62 NTSTATUS ndr_pull_uint8(struct ndr_pull *ndr, int ndr_flags, uint8_t *v)
63 {
64         NDR_PULL_NEED_BYTES(ndr, 1);
65         *v = CVAL(ndr->data, ndr->offset);
66         ndr->offset += 1;
67         return NT_STATUS_OK;
68 }
69
70
71 /*
72   parse a uint16
73 */
74 NTSTATUS ndr_pull_uint16(struct ndr_pull *ndr, int ndr_flags, uint16_t *v)
75 {
76         NDR_PULL_ALIGN(ndr, 2);
77         NDR_PULL_NEED_BYTES(ndr, 2);
78         *v = NDR_SVAL(ndr, ndr->offset);
79         ndr->offset += 2;
80         return NT_STATUS_OK;
81 }
82
83
84 /*
85   parse a uint32_t
86 */
87 NTSTATUS ndr_pull_uint32(struct ndr_pull *ndr, int ndr_flags, uint32_t *v)
88 {
89         NDR_PULL_ALIGN(ndr, 4);
90         NDR_PULL_NEED_BYTES(ndr, 4);
91         *v = NDR_IVAL(ndr, ndr->offset);
92         ndr->offset += 4;
93         return NT_STATUS_OK;
94 }
95
96 /*
97   parse a int32_t
98 */
99 NTSTATUS ndr_pull_int32(struct ndr_pull *ndr, int ndr_flags, int32_t *v)
100 {
101         NDR_PULL_ALIGN(ndr, 4);
102         NDR_PULL_NEED_BYTES(ndr, 4);
103         *v = NDR_IVALS(ndr, ndr->offset);
104         ndr->offset += 4;
105         return NT_STATUS_OK;
106 }
107
108 /*
109   parse a pointer referent identifier
110 */
111 NTSTATUS ndr_pull_unique_ptr(struct ndr_pull *ndr, uint32_t *v)
112 {
113         NTSTATUS status;
114         status = ndr_pull_uint32(ndr, NDR_SCALARS, v);
115         if (*v != 0) {
116                 ndr->ptr_count++;
117         }
118         return status;
119 }
120
121 /*
122   parse a udlong
123 */
124 NTSTATUS ndr_pull_udlong(struct ndr_pull *ndr, int ndr_flags, uint64_t *v)
125 {
126         NDR_PULL_ALIGN(ndr, 4);
127         NDR_PULL_NEED_BYTES(ndr, 8);
128         *v = NDR_IVAL(ndr, ndr->offset);
129         *v |= (uint64_t)(NDR_IVAL(ndr, ndr->offset+4)) << 32;
130         ndr->offset += 8;
131         return NT_STATUS_OK;
132 }
133
134 /*
135   parse a dlong
136 */
137 NTSTATUS ndr_pull_dlong(struct ndr_pull *ndr, int ndr_flags, int64_t *v)
138 {
139         return ndr_pull_udlong(ndr, ndr_flags, (uint64_t *)v);
140 }
141
142 /*
143   parse a hyper
144 */
145 NTSTATUS ndr_pull_hyper(struct ndr_pull *ndr, int ndr_flags, uint64_t *v)
146 {
147         NDR_PULL_ALIGN(ndr, 8);
148         return ndr_pull_udlong(ndr, ndr_flags, v);
149 }
150
151 /*
152   pull a NTSTATUS
153 */
154 NTSTATUS ndr_pull_NTSTATUS(struct ndr_pull *ndr, int ndr_flags, NTSTATUS *status)
155 {
156         uint32_t v;
157         NDR_CHECK(ndr_pull_uint32(ndr, NDR_SCALARS, &v));
158         *status = NT_STATUS(v);
159         return NT_STATUS_OK;
160 }
161
162 /*
163   push a NTSTATUS
164 */
165 NTSTATUS ndr_push_NTSTATUS(struct ndr_push *ndr, int ndr_flags, NTSTATUS status)
166 {
167         return ndr_push_uint32(ndr, ndr_flags, NT_STATUS_V(status));
168 }
169
170 void ndr_print_NTSTATUS(struct ndr_print *ndr, const char *name, NTSTATUS *r)
171 {
172         ndr->print(ndr, "%-25s: %s", name, nt_errstr(*r));
173 }
174
175 /*
176   pull a WERROR
177 */
178 NTSTATUS ndr_pull_WERROR(struct ndr_pull *ndr, int ndr_flags, WERROR *status)
179 {
180         uint32_t v;
181         NDR_CHECK(ndr_pull_uint32(ndr, NDR_SCALARS, &v));
182         *status = W_ERROR(v);
183         return NT_STATUS_OK;
184 }
185
186 /*
187   push a WERROR
188 */
189 NTSTATUS ndr_push_WERROR(struct ndr_push *ndr, int ndr_flags, WERROR status)
190 {
191         return ndr_push_uint32(ndr, NDR_SCALARS, W_ERROR_V(status));
192 }
193
194 void ndr_print_WERROR(struct ndr_print *ndr, const char *name, WERROR r)
195 {
196         ndr->print(ndr, "%-25s: %s", name, win_errstr(r));
197 }
198
199 /*
200   parse a set of bytes
201 */
202 NTSTATUS ndr_pull_bytes(struct ndr_pull *ndr, uint8_t *data, uint32_t n)
203 {
204         NDR_PULL_NEED_BYTES(ndr, n);
205         memcpy(data, ndr->data + ndr->offset, n);
206         ndr->offset += n;
207         return NT_STATUS_OK;
208 }
209
210 /*
211   pull an array of uint8
212 */
213 NTSTATUS ndr_pull_array_uint8(struct ndr_pull *ndr, int ndr_flags, uint8_t *data, uint32_t n)
214 {
215         if (!(ndr_flags & NDR_SCALARS)) {
216                 return NT_STATUS_OK;
217         }
218         return ndr_pull_bytes(ndr, data, n);
219 }
220
221
222 /*
223   pull an array of uint16
224 */
225 NTSTATUS ndr_pull_array_uint16(struct ndr_pull *ndr, int ndr_flags, uint16_t *data, uint32_t n)
226 {
227         uint32_t i;
228         if (!(ndr_flags & NDR_SCALARS)) {
229                 return NT_STATUS_OK;
230         }
231         for (i=0;i<n;i++) {
232                 NDR_CHECK(ndr_pull_uint16(ndr, NDR_SCALARS, &data[i]));
233         }
234         return NT_STATUS_OK;
235 }
236
237 /*
238   pull a const array of uint32_t
239 */
240 NTSTATUS ndr_pull_array_uint32(struct ndr_pull *ndr, int ndr_flags, uint32_t *data, uint32_t n)
241 {
242         uint32_t i;
243         if (!(ndr_flags & NDR_SCALARS)) {
244                 return NT_STATUS_OK;
245         }
246         for (i=0;i<n;i++) {
247                 NDR_CHECK(ndr_pull_uint32(ndr, NDR_SCALARS, &data[i]));
248         }
249         return NT_STATUS_OK;
250 }
251
252 /*
253   pull a const array of hyper
254 */
255 NTSTATUS ndr_pull_array_hyper(struct ndr_pull *ndr, int ndr_flags, uint64_t *data, uint32_t n)
256 {
257         uint32_t i;
258         if (!(ndr_flags & NDR_SCALARS)) {
259                 return NT_STATUS_OK;
260         }
261         for (i=0;i<n;i++) {
262                 NDR_CHECK(ndr_pull_hyper(ndr, NDR_SCALARS, &data[i]));
263         }
264         return NT_STATUS_OK;
265 }
266
267 /*
268   pull a const array of WERROR
269 */
270 NTSTATUS ndr_pull_array_WERROR(struct ndr_pull *ndr, int ndr_flags, WERROR *data, uint32_t n)
271 {
272         uint32_t i;
273         if (!(ndr_flags & NDR_SCALARS)) {
274                 return NT_STATUS_OK;
275         }
276         for (i=0;i<n;i++) {
277                 NDR_CHECK(ndr_pull_WERROR(ndr, NDR_SCALARS, &data[i]));
278         }
279         return NT_STATUS_OK;
280 }
281
282
283
284 /*
285   push a uint8
286 */
287 NTSTATUS ndr_push_uint8(struct ndr_push *ndr, int ndr_flags, uint8_t v)
288 {
289         NDR_PUSH_NEED_BYTES(ndr, 1);
290         SCVAL(ndr->data, ndr->offset, v);
291         ndr->offset += 1;
292         return NT_STATUS_OK;
293 }
294
295 /*
296   push a uint16
297 */
298 NTSTATUS ndr_push_uint16(struct ndr_push *ndr, int ndr_flags, uint16_t v)
299 {
300         NDR_PUSH_ALIGN(ndr, 2);
301         NDR_PUSH_NEED_BYTES(ndr, 2);
302         NDR_SSVAL(ndr, ndr->offset, v);
303         ndr->offset += 2;
304         return NT_STATUS_OK;
305 }
306
307 /*
308   push a uint32_t
309 */
310 NTSTATUS ndr_push_uint32(struct ndr_push *ndr, int ndr_flags, uint32_t v)
311 {
312         NDR_PUSH_ALIGN(ndr, 4);
313         NDR_PUSH_NEED_BYTES(ndr, 4);
314         NDR_SIVAL(ndr, ndr->offset, v);
315         ndr->offset += 4;
316         return NT_STATUS_OK;
317 }
318
319 /*
320   push a int32_t
321 */
322 NTSTATUS ndr_push_int32(struct ndr_push *ndr, int ndr_flags, int32_t v)
323 {
324         NDR_PUSH_ALIGN(ndr, 4);
325         NDR_PUSH_NEED_BYTES(ndr, 4);
326         NDR_SIVALS(ndr, ndr->offset, v);
327         ndr->offset += 4;
328         return NT_STATUS_OK;
329 }
330
331 /*
332   push a uint64
333 */
334 NTSTATUS ndr_push_udlong(struct ndr_push *ndr, int ndr_flags, uint64_t v)
335 {
336         NDR_PUSH_ALIGN(ndr, 4);
337         NDR_PUSH_NEED_BYTES(ndr, 8);
338         NDR_SIVAL(ndr, ndr->offset, (v & 0xFFFFFFFF));
339         NDR_SIVAL(ndr, ndr->offset+4, (v>>32));
340         ndr->offset += 8;
341         return NT_STATUS_OK;
342 }
343
344 /*
345   push a int64
346 */
347 NTSTATUS ndr_push_dlong(struct ndr_push *ndr, int ndr_flags, int64_t v)
348 {
349         return ndr_push_udlong(ndr, NDR_SCALARS, (uint64_t)v);
350 }
351
352 /*
353   push a hyper
354 */
355 NTSTATUS ndr_push_hyper(struct ndr_push *ndr, int ndr_flags, uint64_t v)
356 {
357         NDR_PUSH_ALIGN(ndr, 8);
358         return ndr_push_udlong(ndr, NDR_SCALARS, v);
359 }
360
361 NTSTATUS ndr_push_align(struct ndr_push *ndr, size_t size)
362 {
363         NDR_PUSH_ALIGN(ndr, size);
364         return NT_STATUS_OK;
365 }
366
367 NTSTATUS ndr_pull_align(struct ndr_pull *ndr, size_t size)
368 {
369         NDR_PULL_ALIGN(ndr, size);
370         return NT_STATUS_OK;
371 }
372
373 /*
374   push some bytes
375 */
376 NTSTATUS ndr_push_bytes(struct ndr_push *ndr, const uint8_t *data, uint32_t n)
377 {
378         NDR_PUSH_NEED_BYTES(ndr, n);
379         memcpy(ndr->data + ndr->offset, data, n);
380         ndr->offset += n;
381         return NT_STATUS_OK;
382 }
383
384 /*
385   push some zero bytes
386 */
387 NTSTATUS ndr_push_zero(struct ndr_push *ndr, uint32_t n)
388 {
389         NDR_PUSH_NEED_BYTES(ndr, n);
390         memset(ndr->data + ndr->offset, 0, n);
391         ndr->offset += n;
392         return NT_STATUS_OK;
393 }
394
395 /*
396   push an array of uint8
397 */
398 NTSTATUS ndr_push_array_uint8(struct ndr_push *ndr, int ndr_flags, const uint8_t *data, uint32_t n)
399 {
400         if (!(ndr_flags & NDR_SCALARS)) {
401                 return NT_STATUS_OK;
402         }
403         return ndr_push_bytes(ndr, data, n);
404 }
405
406 /*
407   push an array of uint16
408 */
409 NTSTATUS ndr_push_array_uint16(struct ndr_push *ndr, int ndr_flags, const uint16_t *data, uint32_t n)
410 {
411         int i;
412         if (!(ndr_flags & NDR_SCALARS)) {
413                 return NT_STATUS_OK;
414         }
415         for (i=0;i<n;i++) {
416                 NDR_CHECK(ndr_push_uint16(ndr, NDR_SCALARS, data[i]));
417         }
418         return NT_STATUS_OK;
419 }
420
421 /*
422   push an array of uint32_t
423 */
424 NTSTATUS ndr_push_array_uint32(struct ndr_push *ndr, int ndr_flags, const uint32_t *data, uint32_t n)
425 {
426         int i;
427         if (!(ndr_flags & NDR_SCALARS)) {
428                 return NT_STATUS_OK;
429         }
430         for (i=0;i<n;i++) {
431                 NDR_CHECK(ndr_push_uint32(ndr, NDR_SCALARS, data[i]));
432         }
433         return NT_STATUS_OK;
434 }
435
436 /*
437   push an array of hyper
438 */
439 NTSTATUS ndr_push_array_hyper(struct ndr_push *ndr, int ndr_flags, const uint64_t *data, uint32_t n)
440 {
441         int i;
442         if (!(ndr_flags & NDR_SCALARS)) {
443                 return NT_STATUS_OK;
444         }
445         for (i=0;i<n;i++) {
446                 NDR_CHECK(ndr_push_hyper(ndr, NDR_SCALARS, data[i]));
447         }
448         return NT_STATUS_OK;
449 }
450
451 /*
452   push an array of hyper
453 */
454 NTSTATUS ndr_push_array_WERROR(struct ndr_push *ndr, int ndr_flags, const WERROR *data, uint32_t n)
455 {
456         int i;
457         if (!(ndr_flags & NDR_SCALARS)) {
458                 return NT_STATUS_OK;
459         }
460         for (i=0;i<n;i++) {
461                 NDR_CHECK(ndr_push_WERROR(ndr, NDR_SCALARS, data[i]));
462         }
463         return NT_STATUS_OK;
464 }
465
466 /*
467   save the current position
468  */
469 void ndr_push_save(struct ndr_push *ndr, struct ndr_push_save *save)
470 {
471         save->offset = ndr->offset;
472 }
473
474 /*
475   restore the position
476  */
477 void ndr_push_restore(struct ndr_push *ndr, struct ndr_push_save *save)
478 {
479         ndr->offset = save->offset;
480 }
481
482 /*
483   push a 1 if a pointer is non-NULL, otherwise 0
484 */
485 NTSTATUS ndr_push_unique_ptr(struct ndr_push *ndr, const void *p)
486 {
487         uint32_t ptr = 0;
488         if (p) {
489                 ndr->ptr_count++;
490                 ptr = ndr->ptr_count;
491         }
492         return ndr_push_uint32(ndr, NDR_SCALARS, ptr);
493 }
494
495
496 /*
497   pull a general string from the wire
498 */
499 NTSTATUS ndr_pull_string(struct ndr_pull *ndr, int ndr_flags, const char **s)
500 {
501         char *as=NULL;
502         uint32_t len1, ofs, len2;
503         uint16_t len3;
504         int ret;
505         int chset = CH_UTF16;
506         unsigned byte_mul = 2;
507         unsigned flags = ndr->flags;
508         unsigned c_len_term = 0;
509
510         if (!(ndr_flags & NDR_SCALARS)) {
511                 return NT_STATUS_OK;
512         }
513
514         if (NDR_BE(ndr)) {
515                 chset = CH_UTF16BE;
516         }
517
518         if (flags & LIBNDR_FLAG_STR_ASCII) {
519                 chset = CH_DOS;
520                 byte_mul = 1;
521                 flags &= ~LIBNDR_FLAG_STR_ASCII;
522         }
523
524         if (flags & LIBNDR_FLAG_STR_UTF8) {
525                 chset = CH_UTF8;
526                 byte_mul = 1;
527                 flags &= ~LIBNDR_FLAG_STR_UTF8;
528         }
529
530         flags &= ~LIBNDR_FLAG_STR_CONFORMANT;
531         if (flags & LIBNDR_FLAG_STR_CHARLEN) {
532                 c_len_term = 1;
533                 flags &= ~LIBNDR_FLAG_STR_CHARLEN;
534         }
535
536         switch (flags & LIBNDR_STRING_FLAGS) {
537         case LIBNDR_FLAG_STR_LEN4|LIBNDR_FLAG_STR_SIZE4:
538         case LIBNDR_FLAG_STR_LEN4|LIBNDR_FLAG_STR_SIZE4|LIBNDR_FLAG_STR_NOTERM:
539                 NDR_CHECK(ndr_pull_uint32(ndr, NDR_SCALARS, &len1));
540                 NDR_CHECK(ndr_pull_uint32(ndr, NDR_SCALARS, &ofs));
541                 if (ofs != 0) {
542                         return ndr_pull_error(ndr, NDR_ERR_STRING, "non-zero array offset with string flags 0x%x\n",
543                                               ndr->flags & LIBNDR_STRING_FLAGS);
544                 }
545                 NDR_CHECK(ndr_pull_uint32(ndr, NDR_SCALARS, &len2));
546                 if (len2 > len1) {
547                         return ndr_pull_error(ndr, NDR_ERR_STRING, 
548                                               "Bad string lengths len1=%u ofs=%u len2=%u\n", 
549                                               len1, ofs, len2);
550                 }
551                 if (len2 == 0) {
552                         *s = talloc_strdup(ndr, "");
553                         break;
554                 }
555                 NDR_PULL_NEED_BYTES(ndr, (len2 + c_len_term)*byte_mul);
556                 ret = convert_string_talloc(ndr, chset, CH_UNIX, 
557                                             ndr->data+ndr->offset, 
558                                             (len2 + c_len_term)*byte_mul,
559                                             (void **)&as);
560                 if (ret == -1) {
561                         return ndr_pull_error(ndr, NDR_ERR_CHARCNV, 
562                                               "Bad character conversion");
563                 }
564                 NDR_CHECK(ndr_pull_advance(ndr, (len2 + c_len_term)*byte_mul));
565
566                 /* this is a way of detecting if a string is sent with the wrong
567                    termination */
568                 if (ndr->flags & LIBNDR_FLAG_STR_NOTERM) {
569                         if (strlen(as) < (len2 + c_len_term)) {
570                                 DEBUG(6,("short string '%s'\n", as));
571                         }
572                 } else {
573                         if (strlen(as) == (len2 + c_len_term)) {
574                                 DEBUG(6,("long string '%s'\n", as));
575                         }
576                 }
577                 *s = as;
578                 break;
579
580         case LIBNDR_FLAG_STR_SIZE4:
581         case LIBNDR_FLAG_STR_SIZE4|LIBNDR_FLAG_STR_NOTERM:
582                 NDR_CHECK(ndr_pull_uint32(ndr, NDR_SCALARS, &len1));
583                 NDR_PULL_NEED_BYTES(ndr, (len1 + c_len_term)*byte_mul);
584                 if (len1 == 0) {
585                         *s = talloc_strdup(ndr, "");
586                         break;
587                 }
588                 ret = convert_string_talloc(ndr, chset, CH_UNIX, 
589                                             ndr->data+ndr->offset, 
590                                             (len1 + c_len_term)*byte_mul,
591                                             (void **)&as);
592                 if (ret == -1) {
593                         return ndr_pull_error(ndr, NDR_ERR_CHARCNV, 
594                                               "Bad character conversion");
595                 }
596                 NDR_CHECK(ndr_pull_advance(ndr, (len1 + c_len_term)*byte_mul));
597
598                 /* this is a way of detecting if a string is sent with the wrong
599                    termination */
600                 if (ndr->flags & LIBNDR_FLAG_STR_NOTERM) {
601                         if (strlen(as) < (len1 + c_len_term)) {
602                                 DEBUG(6,("short string '%s'\n", as));
603                         }
604                 } else {
605                         if (strlen(as) == (len1 + c_len_term)) {
606                                 DEBUG(6,("long string '%s'\n", as));
607                         }
608                 }
609                 *s = as;
610                 break;
611
612         case LIBNDR_FLAG_STR_LEN4:
613         case LIBNDR_FLAG_STR_LEN4|LIBNDR_FLAG_STR_NOTERM:
614                 NDR_CHECK(ndr_pull_uint32(ndr, NDR_SCALARS, &ofs));
615                 if (ofs != 0) {
616                         return ndr_pull_error(ndr, NDR_ERR_STRING, "non-zero array offset with string flags 0x%x\n",
617                                               ndr->flags & LIBNDR_STRING_FLAGS);
618                 }
619                 NDR_CHECK(ndr_pull_uint32(ndr, NDR_SCALARS, &len1));
620                 NDR_PULL_NEED_BYTES(ndr, (len1 + c_len_term)*byte_mul);
621                 if (len1 == 0) {
622                         *s = talloc_strdup(ndr, "");
623                         break;
624                 }
625                 ret = convert_string_talloc(ndr, chset, CH_UNIX, 
626                                             ndr->data+ndr->offset, 
627                                             (len1 + c_len_term)*byte_mul,
628                                             (void **)&as);
629                 if (ret == -1) {
630                         return ndr_pull_error(ndr, NDR_ERR_CHARCNV, 
631                                               "Bad character conversion");
632                 }
633                 NDR_CHECK(ndr_pull_advance(ndr, (len1 + c_len_term)*byte_mul));
634
635                 /* this is a way of detecting if a string is sent with the wrong
636                    termination */
637                 if (ndr->flags & LIBNDR_FLAG_STR_NOTERM) {
638                         if (strlen(as) < (len1 + c_len_term)) {
639                                 DEBUG(6,("short string '%s'\n", as));
640                         }
641                 } else {
642                         if (strlen(as) == (len1 + c_len_term)) {
643                                 DEBUG(6,("long string '%s'\n", as));
644                         }
645                 }
646                 *s = as;
647                 break;
648
649
650         case LIBNDR_FLAG_STR_SIZE2:
651         case LIBNDR_FLAG_STR_SIZE2|LIBNDR_FLAG_STR_NOTERM:
652                 NDR_CHECK(ndr_pull_uint16(ndr, NDR_SCALARS, &len3));
653                 NDR_PULL_NEED_BYTES(ndr, (len3 + c_len_term)*byte_mul);
654                 if (len3 == 0) {
655                         *s = talloc_strdup(ndr, "");
656                         break;
657                 }
658                 ret = convert_string_talloc(ndr, chset, CH_UNIX, 
659                                             ndr->data+ndr->offset, 
660                                             (len3 + c_len_term)*byte_mul,
661                                             (void **)&as);
662                 if (ret == -1) {
663                         return ndr_pull_error(ndr, NDR_ERR_CHARCNV, 
664                                               "Bad character conversion");
665                 }
666                 NDR_CHECK(ndr_pull_advance(ndr, (len3 + c_len_term)*byte_mul));
667
668                 /* this is a way of detecting if a string is sent with the wrong
669                    termination */
670                 if (ndr->flags & LIBNDR_FLAG_STR_NOTERM) {
671                         if (strlen(as) < (len3 + c_len_term)) {
672                                 DEBUG(6,("short string '%s'\n", as));
673                         }
674                 } else {
675                         if (strlen(as) == (len3 + c_len_term)) {
676                                 DEBUG(6,("long string '%s'\n", as));
677                         }
678                 }
679                 *s = as;
680                 break;
681
682         case LIBNDR_FLAG_STR_SIZE2|LIBNDR_FLAG_STR_NOTERM|LIBNDR_FLAG_STR_BYTESIZE:
683                 NDR_CHECK(ndr_pull_uint16(ndr, NDR_SCALARS, &len3));
684                 NDR_PULL_NEED_BYTES(ndr, len3);
685                 if (len3 == 0) {
686                         *s = talloc_strdup(ndr, "");
687                         break;
688                 }
689                 ret = convert_string_talloc(ndr, chset, CH_UNIX, 
690                                             ndr->data+ndr->offset, 
691                                             len3,
692                                             (void **)&as);
693                 if (ret == -1) {
694                         return ndr_pull_error(ndr, NDR_ERR_CHARCNV, 
695                                               "Bad character conversion");
696                 }
697                 NDR_CHECK(ndr_pull_advance(ndr, len3));
698                 *s = as;
699                 break;
700
701         case LIBNDR_FLAG_STR_NULLTERM:
702                 if (byte_mul == 1) {
703                         len1 = ascii_len_n((const char *)(ndr->data+ndr->offset), ndr->data_size - ndr->offset);
704                 } else {
705                         len1 = utf16_len_n(ndr->data+ndr->offset, ndr->data_size - ndr->offset);
706                 }
707                 ret = convert_string_talloc(ndr, chset, CH_UNIX, 
708                                             ndr->data+ndr->offset, 
709                                             len1,
710                                             (void **)&as);
711                 if (ret == -1) {
712                         return ndr_pull_error(ndr, NDR_ERR_CHARCNV, 
713                                               "Bad character conversion");
714                 }
715                 NDR_CHECK(ndr_pull_advance(ndr, len1));
716                 *s = as;
717                 break;
718
719         case LIBNDR_FLAG_STR_FIXLEN15:
720         case LIBNDR_FLAG_STR_FIXLEN32:
721                 len1 = (flags & LIBNDR_FLAG_STR_FIXLEN32)?32:15;
722                 NDR_PULL_NEED_BYTES(ndr, len1*byte_mul);
723                 ret = convert_string_talloc(ndr, chset, CH_UNIX, 
724                                             ndr->data+ndr->offset, 
725                                             len1*byte_mul,
726                                             (void **)&as);
727                 if (ret == -1) {
728                         return ndr_pull_error(ndr, NDR_ERR_CHARCNV, 
729                                               "Bad character conversion");
730                 }
731                 NDR_CHECK(ndr_pull_advance(ndr, len1*byte_mul));
732                 *s = as;
733                 break;
734
735         default:
736                 return ndr_pull_error(ndr, NDR_ERR_STRING, "Bad string flags 0x%x\n",
737                                       ndr->flags & LIBNDR_STRING_FLAGS);
738         }
739
740         return NT_STATUS_OK;
741 }
742
743
744 /*
745   push a general string onto the wire
746 */
747 NTSTATUS ndr_push_string(struct ndr_push *ndr, int ndr_flags, const char *s)
748 {
749         ssize_t s_len, c_len, d_len;
750         int ret;
751         int chset = CH_UTF16;
752         unsigned flags = ndr->flags;
753         unsigned byte_mul = 2;
754         unsigned c_len_term = 1;
755
756         if (!(ndr_flags & NDR_SCALARS)) {
757                 return NT_STATUS_OK;
758         }
759
760         if (NDR_BE(ndr)) {
761                 chset = CH_UTF16BE;
762         }
763         
764         s_len = s?strlen(s):0;
765         c_len = s?strlen_m(s):0;
766
767         if (flags & LIBNDR_FLAG_STR_ASCII) {
768                 chset = CH_DOS;
769                 byte_mul = 1;
770                 flags &= ~LIBNDR_FLAG_STR_ASCII;
771         }
772
773         if (flags & LIBNDR_FLAG_STR_UTF8) {
774                 chset = CH_UTF8;
775                 byte_mul = 1;
776                 flags &= ~LIBNDR_FLAG_STR_UTF8;
777         }
778
779         flags &= ~LIBNDR_FLAG_STR_CONFORMANT;
780
781         if (flags & LIBNDR_FLAG_STR_CHARLEN) {
782                 c_len_term = 0;
783                 flags &= ~LIBNDR_FLAG_STR_CHARLEN;
784         }
785
786         switch (flags & LIBNDR_STRING_FLAGS) {
787         case LIBNDR_FLAG_STR_LEN4|LIBNDR_FLAG_STR_SIZE4:
788                 NDR_CHECK(ndr_push_uint32(ndr, NDR_SCALARS, c_len+c_len_term));
789                 NDR_CHECK(ndr_push_uint32(ndr, NDR_SCALARS, 0));
790                 NDR_CHECK(ndr_push_uint32(ndr, NDR_SCALARS, c_len+c_len_term));
791                 NDR_PUSH_NEED_BYTES(ndr, byte_mul*(c_len+1));
792                 ret = convert_string(CH_UNIX, chset, 
793                                      s, s_len+1,
794                                      ndr->data+ndr->offset, 
795                                      byte_mul*(c_len+1));
796                 if (ret == -1) {
797                         return ndr_push_error(ndr, NDR_ERR_CHARCNV, 
798                                               "Bad character conversion");
799                 }
800                 ndr->offset += byte_mul*(c_len+1);
801                 break;
802
803         case LIBNDR_FLAG_STR_LEN4|LIBNDR_FLAG_STR_SIZE4|LIBNDR_FLAG_STR_NOTERM:
804                 NDR_CHECK(ndr_push_uint32(ndr, NDR_SCALARS, c_len));
805                 NDR_CHECK(ndr_push_uint32(ndr, NDR_SCALARS, 0));
806                 NDR_CHECK(ndr_push_uint32(ndr, NDR_SCALARS, c_len));
807                 NDR_PUSH_NEED_BYTES(ndr, c_len*byte_mul);
808                 ret = convert_string(CH_UNIX, chset, 
809                                      s, s_len,
810                                      ndr->data+ndr->offset, c_len*byte_mul);
811                 if (ret == -1) {
812                         return ndr_push_error(ndr, NDR_ERR_CHARCNV, 
813                                               "Bad character conversion");
814                 }
815                 ndr->offset += c_len*byte_mul;
816                 break;
817
818         case LIBNDR_FLAG_STR_LEN4:
819                 NDR_CHECK(ndr_push_uint32(ndr, NDR_SCALARS, 0));
820                 NDR_CHECK(ndr_push_uint32(ndr, NDR_SCALARS, c_len + c_len_term));
821                 NDR_PUSH_NEED_BYTES(ndr, byte_mul*(c_len+1));
822                 ret = convert_string(CH_UNIX, chset, 
823                                      s, s_len + 1,
824                                      ndr->data+ndr->offset, byte_mul*(c_len+1));
825                 if (ret == -1) {
826                         return ndr_push_error(ndr, NDR_ERR_CHARCNV, 
827                                               "Bad character conversion");
828                 }
829                 ndr->offset += byte_mul*(c_len+1);
830                 break;
831
832         case LIBNDR_FLAG_STR_SIZE4:
833                 NDR_CHECK(ndr_push_uint32(ndr, NDR_SCALARS, c_len + c_len_term));
834                 NDR_PUSH_NEED_BYTES(ndr, byte_mul*(c_len+1));
835                 ret = convert_string(CH_UNIX, chset, 
836                                      s, s_len + 1,
837                                      ndr->data+ndr->offset, byte_mul*(c_len+1));
838                 if (ret == -1) {
839                         return ndr_push_error(ndr, NDR_ERR_CHARCNV, 
840                                               "Bad character conversion");
841                 }
842                 ndr->offset += byte_mul*(c_len+1);
843                 break;
844
845         case LIBNDR_FLAG_STR_SIZE2:
846                 NDR_CHECK(ndr_push_uint16(ndr, NDR_SCALARS, c_len + c_len_term));
847                 NDR_PUSH_NEED_BYTES(ndr, byte_mul*(c_len+1));
848                 ret = convert_string(CH_UNIX, chset, 
849                                      s, s_len + 1,
850                                      ndr->data+ndr->offset, byte_mul*(c_len+1));
851                 if (ret == -1) {
852                         return ndr_push_error(ndr, NDR_ERR_CHARCNV, 
853                                               "Bad character conversion");
854                 }
855                 ndr->offset += byte_mul*(c_len+1);
856                 break;
857
858         case LIBNDR_FLAG_STR_NULLTERM:
859                 NDR_PUSH_NEED_BYTES(ndr, byte_mul*(c_len+1));
860                 ret = convert_string(CH_UNIX, chset, 
861                                      s, s_len+1,
862                                      ndr->data+ndr->offset, byte_mul*(c_len+1));
863                 if (ret == -1) {
864                         return ndr_push_error(ndr, NDR_ERR_CHARCNV, 
865                                               "Bad character conversion");
866                 }
867                 ndr->offset += byte_mul*(c_len+1);
868                 break;
869
870         case LIBNDR_FLAG_STR_SIZE2|LIBNDR_FLAG_STR_NOTERM|LIBNDR_FLAG_STR_BYTESIZE:
871                 NDR_CHECK(ndr_push_uint16(ndr, NDR_SCALARS, c_len*byte_mul));
872                 NDR_PUSH_NEED_BYTES(ndr, c_len*byte_mul);
873                 ret = convert_string(CH_UNIX, chset, 
874                                      s, s_len,
875                                      ndr->data+ndr->offset, c_len*byte_mul);
876                 if (ret == -1) {
877                         return ndr_push_error(ndr, NDR_ERR_CHARCNV, 
878                                               "Bad character conversion");
879                 }
880                 ndr->offset += c_len*byte_mul;
881                 break;
882
883         case LIBNDR_FLAG_STR_FIXLEN15:
884         case LIBNDR_FLAG_STR_FIXLEN32:
885                 d_len = (flags & LIBNDR_FLAG_STR_FIXLEN32)?32:15;
886                 NDR_PUSH_NEED_BYTES(ndr, byte_mul*d_len);
887                 ret = convert_string(CH_UNIX, chset, 
888                                      s, s_len,
889                                      ndr->data+ndr->offset, byte_mul*d_len);
890                 if (ret == -1) {
891                         return ndr_push_error(ndr, NDR_ERR_CHARCNV, 
892                                               "Bad character conversion");
893                 }
894                 ndr->offset += byte_mul*d_len;
895                 break;
896
897         default:
898                 return ndr_push_error(ndr, NDR_ERR_STRING, "Bad string flags 0x%x\n",
899                                       ndr->flags & LIBNDR_STRING_FLAGS);
900         }
901
902         return NT_STATUS_OK;
903 }
904
905 /*
906   push a general string onto the wire
907 */
908 size_t ndr_string_array_size(struct ndr_push *ndr, const char *s)
909 {
910         size_t c_len;
911         unsigned flags = ndr->flags;
912         unsigned byte_mul = 2;
913         unsigned c_len_term = 1;
914
915         if (flags & LIBNDR_FLAG_STR_FIXLEN32) {
916                 return 32;
917         }
918         if (flags & LIBNDR_FLAG_STR_FIXLEN15) {
919                 return 15;
920         }
921         
922         c_len = s?strlen_m(s):0;
923
924         if (flags & (LIBNDR_FLAG_STR_ASCII|LIBNDR_FLAG_STR_UTF8)) {
925                 byte_mul = 1;
926         }
927
928         if (flags & LIBNDR_FLAG_STR_NOTERM) {
929                 c_len_term = 0;
930         }
931
932         c_len = c_len + c_len_term;
933
934         if (flags & LIBNDR_FLAG_STR_BYTESIZE) {
935                 c_len = c_len * byte_mul;
936         }
937
938         return c_len;
939 }
940
941
942 /*
943   push a NTTIME
944 */
945 NTSTATUS ndr_push_NTTIME(struct ndr_push *ndr, int ndr_flags, NTTIME t)
946 {
947         NDR_CHECK(ndr_push_udlong(ndr, ndr_flags, t));
948         return NT_STATUS_OK;
949 }
950
951 /*
952   pull a NTTIME
953 */
954 NTSTATUS ndr_pull_NTTIME(struct ndr_pull *ndr, int ndr_flags, NTTIME *t)
955 {
956         NDR_CHECK(ndr_pull_udlong(ndr, ndr_flags, t));
957         return NT_STATUS_OK;
958 }
959
960 /*
961   push a NTTIME
962 */
963 NTSTATUS ndr_push_NTTIME_1sec(struct ndr_push *ndr, int ndr_flags, NTTIME t)
964 {
965         t /= 10000000;
966         NDR_CHECK(ndr_push_hyper(ndr, ndr_flags, t));
967         return NT_STATUS_OK;
968 }
969
970 /*
971   pull a NTTIME_1sec
972 */
973 NTSTATUS ndr_pull_NTTIME_1sec(struct ndr_pull *ndr, int ndr_flags, NTTIME *t)
974 {
975         NDR_CHECK(ndr_pull_hyper(ndr, ndr_flags, t));
976         (*t) *= 10000000;
977         return NT_STATUS_OK;
978 }
979
980 /*
981   pull a NTTIME_hyper
982 */
983 NTSTATUS ndr_pull_NTTIME_hyper(struct ndr_pull *ndr, int ndr_flags, NTTIME *t)
984 {
985         NDR_CHECK(ndr_pull_hyper(ndr, ndr_flags, t));
986         return NT_STATUS_OK;
987 }
988
989 /*
990   push a NTTIME_hyper
991 */
992 NTSTATUS ndr_push_NTTIME_hyper(struct ndr_push *ndr, int ndr_flags, NTTIME t)
993 {
994         NDR_CHECK(ndr_push_hyper(ndr, ndr_flags, t));
995         return NT_STATUS_OK;
996 }
997
998 /*
999   push a time_t
1000 */
1001 NTSTATUS ndr_push_time_t(struct ndr_push *ndr, int ndr_flags, time_t t)
1002 {
1003         return ndr_push_uint32(ndr, ndr_flags, t);
1004 }
1005
1006 /*
1007   pull a time_t
1008 */
1009 NTSTATUS ndr_pull_time_t(struct ndr_pull *ndr, int ndr_flags, time_t *t)
1010 {
1011         uint32_t tt;
1012         NDR_CHECK(ndr_pull_uint32(ndr, ndr_flags, &tt));
1013         *t = tt;
1014         return NT_STATUS_OK;
1015 }
1016
1017
1018 /*
1019   pull a ipv4address
1020 */
1021 NTSTATUS ndr_pull_ipv4address(struct ndr_pull *ndr, int ndr_flags, const char **address)
1022 {
1023         struct ipv4_addr in;
1024         NDR_CHECK(ndr_pull_uint32(ndr, ndr_flags, &in.addr));
1025         in.addr = htonl(in.addr);
1026         *address = talloc_strdup(ndr, sys_inet_ntoa(in));
1027         NT_STATUS_HAVE_NO_MEMORY(*address);
1028         return NT_STATUS_OK;
1029 }
1030
1031 /*
1032   push a ipv4address
1033 */
1034 NTSTATUS ndr_push_ipv4address(struct ndr_push *ndr, int ndr_flags, const char *address)
1035 {
1036         uint32_t addr = interpret_addr(address);
1037         NDR_CHECK(ndr_push_uint32(ndr, ndr_flags, htonl(addr)));
1038         return NT_STATUS_OK;
1039 }
1040
1041 /*
1042   print a ipv4address
1043 */
1044 void ndr_print_ipv4address(struct ndr_print *ndr, const char *name, 
1045                            const char *address)
1046 {
1047         ndr->print(ndr, "%-25s: %s", name, address);
1048 }
1049
1050
1051 void ndr_print_struct(struct ndr_print *ndr, const char *name, const char *type)
1052 {
1053         ndr->print(ndr, "%s: struct %s", name, type);
1054 }
1055
1056 void ndr_print_enum(struct ndr_print *ndr, const char *name, const char *type, 
1057                     const char *val, uint_t value)
1058 {
1059         if (ndr->flags & LIBNDR_PRINT_ARRAY_HEX) {
1060                 ndr->print(ndr, "%-25s: %s (0x%X)", name, val?val:"UNKNOWN_ENUM_VALUE", value);
1061         } else {
1062                 ndr->print(ndr, "%-25s: %s (%d)", name, val?val:"UNKNOWN_ENUM_VALUE", value);
1063         }
1064 }
1065
1066 void ndr_print_bitmap_flag(struct ndr_print *ndr, size_t size, const char *flag_name, uint_t flag, uint_t value)
1067 {
1068         /* this is an attempt to support multi-bit bitmap masks */
1069         value &= flag;
1070
1071         while (!(flag & 1)) {
1072                 flag >>= 1;
1073                 value >>= 1;
1074         }       
1075         if (flag == 1) {
1076                 ndr->print(ndr, "   %d: %-25s", value, flag_name);
1077         } else {
1078                 ndr->print(ndr, "0x%02x: %-25s (%d)", value, flag_name, value);
1079         }
1080 }
1081
1082 void ndr_print_uint8(struct ndr_print *ndr, const char *name, uint8_t v)
1083 {
1084         ndr->print(ndr, "%-25s: 0x%02x (%u)", name, v, v);
1085 }
1086
1087 void ndr_print_uint16(struct ndr_print *ndr, const char *name, uint16_t v)
1088 {
1089         ndr->print(ndr, "%-25s: 0x%04x (%u)", name, v, v);
1090 }
1091
1092 void ndr_print_uint32(struct ndr_print *ndr, const char *name, uint32_t v)
1093 {
1094         ndr->print(ndr, "%-25s: 0x%08x (%u)", name, v, v);
1095 }
1096
1097 void ndr_print_int32(struct ndr_print *ndr, const char *name, int32_t v)
1098 {
1099         ndr->print(ndr, "%-25s: %d", name, v);
1100 }
1101
1102 void ndr_print_udlong(struct ndr_print *ndr, const char *name, uint64_t v)
1103 {
1104         ndr->print(ndr, "%-25s: 0x%08x%08x (%llu)", name,
1105                    (uint32_t)(v >> 32),
1106                    (uint32_t)(v & 0xFFFFFFFF),
1107                    v);
1108 }
1109
1110 void ndr_print_dlong(struct ndr_print *ndr, const char *name, int64_t v)
1111 {
1112         ndr->print(ndr, "%-25s: 0x%08x%08x (%lld)", name, 
1113                    (uint32_t)(v >> 32), 
1114                    (uint32_t)(v & 0xFFFFFFFF),
1115                    v);
1116 }
1117
1118 void ndr_print_hyper(struct ndr_print *ndr, const char *name, uint64_t v)
1119 {
1120         ndr_print_dlong(ndr, name, v);
1121 }
1122
1123 void ndr_print_ptr(struct ndr_print *ndr, const char *name, const void *p)
1124 {
1125         if (p) {
1126                 ndr->print(ndr, "%-25s: *", name);
1127         } else {
1128                 ndr->print(ndr, "%-25s: NULL", name);
1129         }
1130 }
1131
1132 void ndr_print_string(struct ndr_print *ndr, const char *name, const char *s)
1133 {
1134         if (s) {
1135                 ndr->print(ndr, "%-25s: '%s'", name, s);
1136         } else {
1137                 ndr->print(ndr, "%-25s: NULL", name);
1138         }
1139 }
1140
1141 void ndr_print_NTTIME(struct ndr_print *ndr, const char *name, NTTIME t)
1142 {
1143         ndr->print(ndr, "%-25s: %s", name, nt_time_string(ndr, t));
1144 }
1145
1146 void ndr_print_NTTIME_1sec(struct ndr_print *ndr, const char *name, NTTIME t)
1147 {
1148         /* this is a standard NTTIME here
1149          * as it's already converted in the pull/push code
1150          */
1151         ndr_print_NTTIME(ndr, name, t);
1152 }
1153
1154 void ndr_print_NTTIME_hyper(struct ndr_print *ndr, const char *name, NTTIME t)
1155 {
1156         ndr_print_NTTIME(ndr, name, t);
1157 }
1158
1159 void ndr_print_time_t(struct ndr_print *ndr, const char *name, time_t t)
1160 {
1161         if (t == (time_t)-1 || t == 0) {
1162                 ndr->print(ndr, "%-25s: (time_t)%d", name, (int)t);
1163         } else {
1164                 ndr->print(ndr, "%-25s: %s", name, timestring(ndr, t));
1165         }
1166 }
1167
1168 void ndr_print_union(struct ndr_print *ndr, const char *name, int level, const char *type)
1169 {
1170         ndr->print(ndr, "%-25s: union %s(case %d)", name, type, level);
1171 }
1172
1173 void ndr_print_bad_level(struct ndr_print *ndr, const char *name, uint16_t level)
1174 {
1175         ndr->print(ndr, "UNKNOWN LEVEL %u", level);
1176 }
1177
1178 void ndr_print_array_WERROR(struct ndr_print *ndr, const char *name, 
1179                             const WERROR *data, uint32_t count)
1180 {
1181         int i;
1182
1183         ndr->print(ndr, "%s: ARRAY(%d)", name, count);
1184         ndr->depth++;
1185         for (i=0;i<count;i++) {
1186                 char *idx=NULL;
1187                 asprintf(&idx, "[%d]", i);
1188                 if (idx) {
1189                         ndr_print_WERROR(ndr, idx, data[i]);
1190                         free(idx);
1191                 }
1192         }
1193         ndr->depth--;   
1194 }
1195
1196 void ndr_print_array_hyper(struct ndr_print *ndr, const char *name, 
1197                             const uint64_t *data, uint32_t count)
1198 {
1199         int i;
1200
1201         ndr->print(ndr, "%s: ARRAY(%d)", name, count);
1202         ndr->depth++;
1203         for (i=0;i<count;i++) {
1204                 char *idx=NULL;
1205                 asprintf(&idx, "[%d]", i);
1206                 if (idx) {
1207                         ndr_print_hyper(ndr, idx, data[i]);
1208                         free(idx);
1209                 }
1210         }
1211         ndr->depth--;   
1212 }
1213
1214 void ndr_print_array_uint32(struct ndr_print *ndr, const char *name, 
1215                             const uint32_t *data, uint32_t count)
1216 {
1217         int i;
1218
1219         ndr->print(ndr, "%s: ARRAY(%d)", name, count);
1220         ndr->depth++;
1221         for (i=0;i<count;i++) {
1222                 char *idx=NULL;
1223                 asprintf(&idx, "[%d]", i);
1224                 if (idx) {
1225                         ndr_print_uint32(ndr, idx, data[i]);
1226                         free(idx);
1227                 }
1228         }
1229         ndr->depth--;   
1230 }
1231
1232 void ndr_print_array_uint16(struct ndr_print *ndr, const char *name, 
1233                             const uint16_t *data, uint32_t count)
1234 {
1235         int i;
1236
1237         ndr->print(ndr, "%s: ARRAY(%d)", name, count);
1238         ndr->depth++;
1239         for (i=0;i<count;i++) {
1240                 char *idx=NULL;
1241                 asprintf(&idx, "[%d]", i);
1242                 if (idx) {
1243                         ndr_print_uint16(ndr, idx, data[i]);
1244                         free(idx);
1245                 }
1246         }
1247         ndr->depth--;   
1248 }
1249
1250 void ndr_print_array_uint8(struct ndr_print *ndr, const char *name, 
1251                            const uint8_t *data, uint32_t count)
1252 {
1253         int i;
1254
1255         if (count <= 600 && (ndr->flags & LIBNDR_PRINT_ARRAY_HEX)) {
1256                 char s[1202];
1257                 for (i=0;i<count;i++) {
1258                         snprintf(&s[i*2], 3, "%02x", data[i]);
1259                 }
1260                 s[i*2] = 0;
1261                 ndr->print(ndr, "%-25s: %s", name, s);
1262                 return;
1263         }
1264
1265         ndr->print(ndr, "%s: ARRAY(%d)", name, count);
1266         ndr->depth++;
1267         for (i=0;i<count;i++) {
1268                 char *idx=NULL;
1269                 asprintf(&idx, "[%d]", i);
1270                 if (idx) {
1271                         ndr_print_uint8(ndr, idx, data[i]);
1272                         free(idx);
1273                 }
1274         }
1275         ndr->depth--;   
1276 }
1277
1278 void ndr_print_DATA_BLOB(struct ndr_print *ndr, const char *name, DATA_BLOB r)
1279 {
1280         ndr->print(ndr, "%-25s: DATA_BLOB length=%u", name, r.length);
1281         if (r.length) {
1282                 dump_data(10, r.data, r.length);
1283         }
1284 }
1285
1286
1287 /*
1288   push a DATA_BLOB onto the wire. 
1289 */
1290 NTSTATUS ndr_push_DATA_BLOB(struct ndr_push *ndr, int ndr_flags, DATA_BLOB blob)
1291 {
1292         if (ndr->flags & LIBNDR_ALIGN_FLAGS) {
1293                 if (ndr->flags & LIBNDR_FLAG_ALIGN2) {
1294                         blob.length = NDR_ALIGN(ndr, 2);
1295                 } else if (ndr->flags & LIBNDR_FLAG_ALIGN4) {
1296                         blob.length = NDR_ALIGN(ndr, 4);
1297                 } else if (ndr->flags & LIBNDR_FLAG_ALIGN8) {
1298                         blob.length = NDR_ALIGN(ndr, 8);
1299                 }
1300                 NDR_PUSH_ALLOC_SIZE(ndr, blob.data, blob.length);
1301                 data_blob_clear(&blob);
1302         } else if (!(ndr->flags & LIBNDR_FLAG_REMAINING)) {
1303                 NDR_CHECK(ndr_push_uint32(ndr, NDR_SCALARS, blob.length));
1304         }
1305         NDR_CHECK(ndr_push_bytes(ndr, blob.data, blob.length));
1306         return NT_STATUS_OK;
1307 }
1308
1309 /*
1310   pull a DATA_BLOB from the wire. 
1311 */
1312 NTSTATUS ndr_pull_DATA_BLOB(struct ndr_pull *ndr, int ndr_flags, DATA_BLOB *blob)
1313 {
1314         uint32_t length;
1315
1316         if (ndr->flags & LIBNDR_ALIGN_FLAGS) {
1317                 if (ndr->flags & LIBNDR_FLAG_ALIGN2) {
1318                         length = NDR_ALIGN(ndr, 2);
1319                 } else if (ndr->flags & LIBNDR_FLAG_ALIGN4) {
1320                         length = NDR_ALIGN(ndr, 4);
1321                 } else if (ndr->flags & LIBNDR_FLAG_ALIGN8) {
1322                         length = NDR_ALIGN(ndr, 8);
1323                 }
1324                 if (ndr->data_size - ndr->offset < length) {
1325                         length = ndr->data_size - ndr->offset;
1326                 }
1327         } else if (ndr->flags & LIBNDR_FLAG_REMAINING) {
1328                 length = ndr->data_size - ndr->offset;
1329         } else {
1330                 NDR_CHECK(ndr_pull_uint32(ndr, NDR_SCALARS, &length));
1331         }
1332         NDR_PULL_NEED_BYTES(ndr, length);
1333         *blob = data_blob_talloc(ndr, ndr->data+ndr->offset, length);
1334         ndr->offset += length;
1335         return NT_STATUS_OK;
1336 }
1337
1338 uint32_t ndr_size_DATA_BLOB(int ret, const DATA_BLOB *data, int flags)
1339 {
1340         return ret + data->length;
1341 }
1342
1343 uint32_t ndr_size_string(int ret, const char * const* string, int flags) 
1344 {
1345         /* FIXME: Is this correct for all strings ? */
1346         if(!(*string)) return ret;
1347         return ret+strlen(*string)+1;
1348 }