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