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