WHATSNEW: Prepare release notes for Samba 3.5.21.
[samba.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 uint1632_t
106 */
107 _PUBLIC_ enum ndr_err_code ndr_pull_uint1632(struct ndr_pull *ndr, int ndr_flags, uint16_t *v)
108 {
109         if (unlikely(ndr->flags & LIBNDR_FLAG_NDR64)) {
110                 uint32_t v32 = 0;
111                 enum ndr_err_code err = ndr_pull_uint32(ndr, ndr_flags, &v32);
112                 *v = v32;
113                 if (unlikely(v32 != *v)) {
114                         DEBUG(0,(__location__ ": non-zero upper 16 bits 0x%08x\n", (unsigned)v32));
115                         return NDR_ERR_NDR64;
116                 }
117                 return err;
118         }
119         return ndr_pull_uint16(ndr, ndr_flags, v);
120 }
121
122 /*
123   parse a int32_t
124 */
125 _PUBLIC_ enum ndr_err_code ndr_pull_int32(struct ndr_pull *ndr, int ndr_flags, int32_t *v)
126 {
127         NDR_PULL_ALIGN(ndr, 4);
128         NDR_PULL_NEED_BYTES(ndr, 4);
129         *v = NDR_IVALS(ndr, ndr->offset);
130         ndr->offset += 4;
131         return NDR_ERR_SUCCESS;
132 }
133
134 /*
135   parse a uint32_t
136 */
137 _PUBLIC_ enum ndr_err_code ndr_pull_uint32(struct ndr_pull *ndr, int ndr_flags, uint32_t *v)
138 {
139         NDR_PULL_ALIGN(ndr, 4);
140         NDR_PULL_NEED_BYTES(ndr, 4);
141         *v = NDR_IVAL(ndr, ndr->offset);
142         ndr->offset += 4;
143         return NDR_ERR_SUCCESS;
144 }
145
146 /*
147   parse a arch dependent uint32/uint64
148 */
149 _PUBLIC_ enum ndr_err_code ndr_pull_uint3264(struct ndr_pull *ndr, int ndr_flags, uint32_t *v)
150 {
151         uint64_t v64;
152         enum ndr_err_code err;
153         if (likely(!(ndr->flags & LIBNDR_FLAG_NDR64))) {
154                 return ndr_pull_uint32(ndr, ndr_flags, v);
155         }
156         err = ndr_pull_hyper(ndr, ndr_flags, &v64);
157         *v = (uint32_t)v64;
158         if (unlikely(v64 != *v)) {
159                 DEBUG(0,(__location__ ": non-zero upper 32 bits 0x%016llx\n",
160                          (unsigned long long)v64));
161                 return NDR_ERR_NDR64;
162         }
163         return err;
164 }
165
166 /*
167   parse a double
168 */
169 _PUBLIC_ enum ndr_err_code ndr_pull_double(struct ndr_pull *ndr, int ndr_flags, double *v)
170 {
171         NDR_PULL_ALIGN(ndr, 8);
172         NDR_PULL_NEED_BYTES(ndr, 8);
173         memcpy(v, ndr->data+ndr->offset, 8);
174         ndr->offset += 8;
175         return NDR_ERR_SUCCESS;
176 }
177
178 /*
179   parse a pointer referent identifier
180 */
181 _PUBLIC_ enum ndr_err_code ndr_pull_generic_ptr(struct ndr_pull *ndr, uint32_t *v)
182 {
183         NDR_CHECK(ndr_pull_uint3264(ndr, NDR_SCALARS, v));
184         if (*v != 0) {
185                 ndr->ptr_count++;
186         }
187         return NDR_ERR_SUCCESS;
188 }
189
190 /*
191   parse a ref pointer referent identifier
192 */
193 _PUBLIC_ enum ndr_err_code ndr_pull_ref_ptr(struct ndr_pull *ndr, uint32_t *v)
194 {
195         NDR_CHECK(ndr_pull_uint3264(ndr, NDR_SCALARS, v));
196         /* ref pointers always point to data */
197         *v = 1;
198         return NDR_ERR_SUCCESS;
199 }
200
201 /*
202   parse a udlong
203 */
204 _PUBLIC_ enum ndr_err_code ndr_pull_udlong(struct ndr_pull *ndr, int ndr_flags, uint64_t *v)
205 {
206         NDR_PULL_ALIGN(ndr, 4);
207         NDR_PULL_NEED_BYTES(ndr, 8);
208         *v = NDR_IVAL(ndr, ndr->offset);
209         *v |= (uint64_t)(NDR_IVAL(ndr, ndr->offset+4)) << 32;
210         ndr->offset += 8;
211         return NDR_ERR_SUCCESS;
212 }
213
214 /*
215   parse a udlongr
216 */
217 _PUBLIC_ enum ndr_err_code ndr_pull_udlongr(struct ndr_pull *ndr, int ndr_flags, uint64_t *v)
218 {
219         NDR_PULL_ALIGN(ndr, 4);
220         NDR_PULL_NEED_BYTES(ndr, 8);
221         *v = ((uint64_t)NDR_IVAL(ndr, ndr->offset)) << 32;
222         *v |= NDR_IVAL(ndr, ndr->offset+4);
223         ndr->offset += 8;
224         return NDR_ERR_SUCCESS;
225 }
226
227 /*
228   parse a dlong
229 */
230 _PUBLIC_ enum ndr_err_code ndr_pull_dlong(struct ndr_pull *ndr, int ndr_flags, int64_t *v)
231 {
232         return ndr_pull_udlong(ndr, ndr_flags, (uint64_t *)v);
233 }
234
235 /*
236   parse a hyper
237 */
238 _PUBLIC_ enum ndr_err_code ndr_pull_hyper(struct ndr_pull *ndr, int ndr_flags, uint64_t *v)
239 {
240         NDR_PULL_ALIGN(ndr, 8);
241         return ndr_pull_udlong(ndr, ndr_flags, v);
242 }
243
244 /*
245   parse a pointer
246 */
247 _PUBLIC_ enum ndr_err_code ndr_pull_pointer(struct ndr_pull *ndr, int ndr_flags, void* *v)
248 {
249         uintptr_t h;
250         NDR_PULL_ALIGN(ndr, sizeof(h));
251         NDR_PULL_NEED_BYTES(ndr, sizeof(h));
252         memcpy(&h, ndr->data+ndr->offset, sizeof(h));
253         ndr->offset += sizeof(h);
254         *v = (void *)h;
255         return NDR_ERR_SUCCESS;
256 }
257
258 /*
259   pull a NTSTATUS
260 */
261 _PUBLIC_ enum ndr_err_code ndr_pull_NTSTATUS(struct ndr_pull *ndr, int ndr_flags, NTSTATUS *status)
262 {
263         uint32_t v;
264         NDR_CHECK(ndr_pull_uint32(ndr, NDR_SCALARS, &v));
265         *status = NT_STATUS(v);
266         return NDR_ERR_SUCCESS;
267 }
268
269 /*
270   push a NTSTATUS
271 */
272 _PUBLIC_ enum ndr_err_code ndr_push_NTSTATUS(struct ndr_push *ndr, int ndr_flags, NTSTATUS status)
273 {
274         return ndr_push_uint32(ndr, ndr_flags, NT_STATUS_V(status));
275 }
276
277 _PUBLIC_ void ndr_print_NTSTATUS(struct ndr_print *ndr, const char *name, NTSTATUS r)
278 {
279         ndr->print(ndr, "%-25s: %s", name, nt_errstr(r));
280 }
281
282 /*
283   pull a WERROR
284 */
285 _PUBLIC_ enum ndr_err_code ndr_pull_WERROR(struct ndr_pull *ndr, int ndr_flags, WERROR *status)
286 {
287         uint32_t v;
288         NDR_CHECK(ndr_pull_uint32(ndr, NDR_SCALARS, &v));
289         *status = W_ERROR(v);
290         return NDR_ERR_SUCCESS;
291 }
292
293
294 /*
295   parse a uint8_t enum
296 */
297 _PUBLIC_ enum ndr_err_code ndr_pull_enum_uint8(struct ndr_pull *ndr, int ndr_flags, uint8_t *v)
298 {
299         return ndr_pull_uint8(ndr, ndr_flags, v);
300 }
301
302 /*
303   parse a uint16_t enum
304 */
305 _PUBLIC_ enum ndr_err_code ndr_pull_enum_uint16(struct ndr_pull *ndr, int ndr_flags, uint16_t *v)
306 {
307         return ndr_pull_uint16(ndr, ndr_flags, v);
308 }
309
310 /*
311   parse a uint1632_t enum (uint32_t on NDR64)
312 */
313 _PUBLIC_ enum ndr_err_code ndr_pull_enum_uint1632(struct ndr_pull *ndr, int ndr_flags, uint16_t *v)
314 {
315         if (unlikely(ndr->flags & LIBNDR_FLAG_NDR64)) {
316                 uint32_t v32;
317                 NDR_CHECK(ndr_pull_uint32(ndr, ndr_flags, &v32));
318                 *v = v32;
319                 if (v32 != *v) {
320                         DEBUG(0,(__location__ ": non-zero upper 16 bits 0x%08x\n", (unsigned)v32));
321                         return NDR_ERR_NDR64;
322                 }
323                 return NDR_ERR_SUCCESS;
324         }
325         return ndr_pull_uint16(ndr, ndr_flags, v);
326 }
327
328 /*
329   parse a uint32_t enum
330 */
331 _PUBLIC_ enum ndr_err_code ndr_pull_enum_uint32(struct ndr_pull *ndr, int ndr_flags, uint32_t *v)
332 {
333         return ndr_pull_uint32(ndr, ndr_flags, v);
334 }
335
336 /*
337   push a uint8_t enum
338 */
339 _PUBLIC_ enum ndr_err_code ndr_push_enum_uint8(struct ndr_push *ndr, int ndr_flags, uint8_t v)
340 {
341         return ndr_push_uint8(ndr, ndr_flags, v);
342 }
343
344 /*
345   push a uint16_t enum
346 */
347 _PUBLIC_ enum ndr_err_code ndr_push_enum_uint16(struct ndr_push *ndr, int ndr_flags, uint16_t v)
348 {
349         return ndr_push_uint16(ndr, ndr_flags, v);
350 }
351
352 /*
353   push a uint32_t enum
354 */
355 _PUBLIC_ enum ndr_err_code ndr_push_enum_uint32(struct ndr_push *ndr, int ndr_flags, uint32_t v)
356 {
357         return ndr_push_uint32(ndr, ndr_flags, v);
358 }
359
360 /*
361   push a uint1632_t enum
362 */
363 _PUBLIC_ enum ndr_err_code ndr_push_enum_uint1632(struct ndr_push *ndr, int ndr_flags, uint16_t v)
364 {
365         if (unlikely(ndr->flags & LIBNDR_FLAG_NDR64)) {
366                 return ndr_push_uint32(ndr, ndr_flags, v);
367         }
368         return ndr_push_uint16(ndr, ndr_flags, v);
369 }
370
371 /*
372   push a WERROR
373 */
374 _PUBLIC_ enum ndr_err_code ndr_push_WERROR(struct ndr_push *ndr, int ndr_flags, WERROR status)
375 {
376         return ndr_push_uint32(ndr, NDR_SCALARS, W_ERROR_V(status));
377 }
378
379 _PUBLIC_ void ndr_print_WERROR(struct ndr_print *ndr, const char *name, WERROR r)
380 {
381         ndr->print(ndr, "%-25s: %s", name, win_errstr(r));
382 }
383
384 /*
385   parse a set of bytes
386 */
387 _PUBLIC_ enum ndr_err_code ndr_pull_bytes(struct ndr_pull *ndr, uint8_t *data, uint32_t n)
388 {
389         NDR_PULL_NEED_BYTES(ndr, n);
390         memcpy(data, ndr->data + ndr->offset, n);
391         ndr->offset += n;
392         return NDR_ERR_SUCCESS;
393 }
394
395 /*
396   pull an array of uint8
397 */
398 _PUBLIC_ enum ndr_err_code ndr_pull_array_uint8(struct ndr_pull *ndr, int ndr_flags, uint8_t *data, uint32_t n)
399 {
400         if (!(ndr_flags & NDR_SCALARS)) {
401                 return NDR_ERR_SUCCESS;
402         }
403         return ndr_pull_bytes(ndr, data, n);
404 }
405
406 /*
407   push a int8_t
408 */
409 _PUBLIC_ enum ndr_err_code ndr_push_int8(struct ndr_push *ndr, int ndr_flags, int8_t v)
410 {
411         NDR_PUSH_NEED_BYTES(ndr, 1);
412         SCVAL(ndr->data, ndr->offset, (uint8_t)v);
413         ndr->offset += 1;
414         return NDR_ERR_SUCCESS;
415 }
416
417 /*
418   push a uint8_t
419 */
420 _PUBLIC_ enum ndr_err_code ndr_push_uint8(struct ndr_push *ndr, int ndr_flags, uint8_t v)
421 {
422         NDR_PUSH_NEED_BYTES(ndr, 1);
423         SCVAL(ndr->data, ndr->offset, v);
424         ndr->offset += 1;
425         return NDR_ERR_SUCCESS;
426 }
427
428 /*
429   push a int16_t
430 */
431 _PUBLIC_ enum ndr_err_code ndr_push_int16(struct ndr_push *ndr, int ndr_flags, int16_t v)
432 {
433         NDR_PUSH_ALIGN(ndr, 2);
434         NDR_PUSH_NEED_BYTES(ndr, 2);
435         NDR_SSVAL(ndr, ndr->offset, (uint16_t)v);
436         ndr->offset += 2;
437         return NDR_ERR_SUCCESS;
438 }
439
440 /*
441   push a uint16_t
442 */
443 _PUBLIC_ enum ndr_err_code ndr_push_uint16(struct ndr_push *ndr, int ndr_flags, uint16_t v)
444 {
445         NDR_PUSH_ALIGN(ndr, 2);
446         NDR_PUSH_NEED_BYTES(ndr, 2);
447         NDR_SSVAL(ndr, ndr->offset, v);
448         ndr->offset += 2;
449         return NDR_ERR_SUCCESS;
450 }
451
452 /*
453   push a uint1632
454 */
455 _PUBLIC_ enum ndr_err_code ndr_push_uint1632(struct ndr_push *ndr, int ndr_flags, uint16_t v)
456 {
457         if (unlikely(ndr->flags & LIBNDR_FLAG_NDR64)) {
458                 return ndr_push_uint32(ndr, ndr_flags, v);
459         }
460         return ndr_push_uint16(ndr, ndr_flags, v);
461 }
462
463 /*
464   push a int32_t
465 */
466 _PUBLIC_ enum ndr_err_code ndr_push_int32(struct ndr_push *ndr, int ndr_flags, int32_t v)
467 {
468         NDR_PUSH_ALIGN(ndr, 4);
469         NDR_PUSH_NEED_BYTES(ndr, 4);
470         NDR_SIVALS(ndr, ndr->offset, v);
471         ndr->offset += 4;
472         return NDR_ERR_SUCCESS;
473 }
474
475 /*
476   push a uint32_t
477 */
478 _PUBLIC_ enum ndr_err_code ndr_push_uint32(struct ndr_push *ndr, int ndr_flags, uint32_t v)
479 {
480         NDR_PUSH_ALIGN(ndr, 4);
481         NDR_PUSH_NEED_BYTES(ndr, 4);
482         NDR_SIVAL(ndr, ndr->offset, v);
483         ndr->offset += 4;
484         return NDR_ERR_SUCCESS;
485 }
486
487 /*
488   push a uint3264
489 */
490 _PUBLIC_ enum ndr_err_code ndr_push_uint3264(struct ndr_push *ndr, int ndr_flags, uint32_t v)
491 {
492         if (unlikely(ndr->flags & LIBNDR_FLAG_NDR64)) {
493                 return ndr_push_hyper(ndr, ndr_flags, v);
494         }
495         return ndr_push_uint32(ndr, ndr_flags, v);
496 }
497
498 /*
499   push a udlong
500 */
501 _PUBLIC_ enum ndr_err_code ndr_push_udlong(struct ndr_push *ndr, int ndr_flags, uint64_t v)
502 {
503         NDR_PUSH_ALIGN(ndr, 4);
504         NDR_PUSH_NEED_BYTES(ndr, 8);
505         NDR_SIVAL(ndr, ndr->offset, (v & 0xFFFFFFFF));
506         NDR_SIVAL(ndr, ndr->offset+4, (v>>32));
507         ndr->offset += 8;
508         return NDR_ERR_SUCCESS;
509 }
510
511 /*
512   push a udlongr
513 */
514 _PUBLIC_ enum ndr_err_code ndr_push_udlongr(struct ndr_push *ndr, int ndr_flags, uint64_t v)
515 {
516         NDR_PUSH_ALIGN(ndr, 4);
517         NDR_PUSH_NEED_BYTES(ndr, 8);
518         NDR_SIVAL(ndr, ndr->offset, (v>>32));
519         NDR_SIVAL(ndr, ndr->offset+4, (v & 0xFFFFFFFF));
520         ndr->offset += 8;
521         return NDR_ERR_SUCCESS;
522 }
523
524 /*
525   push a dlong
526 */
527 _PUBLIC_ enum ndr_err_code ndr_push_dlong(struct ndr_push *ndr, int ndr_flags, int64_t v)
528 {
529         return ndr_push_udlong(ndr, NDR_SCALARS, (uint64_t)v);
530 }
531
532 /*
533   push a hyper
534 */
535 _PUBLIC_ enum ndr_err_code ndr_push_hyper(struct ndr_push *ndr, int ndr_flags, uint64_t v)
536 {
537         NDR_PUSH_ALIGN(ndr, 8);
538         return ndr_push_udlong(ndr, NDR_SCALARS, v);
539 }
540
541 /*
542   push a double
543 */
544 _PUBLIC_ enum ndr_err_code ndr_push_double(struct ndr_push *ndr, int ndr_flags, double v)
545 {
546         NDR_PUSH_ALIGN(ndr, 8);
547         NDR_PUSH_NEED_BYTES(ndr, 8);
548         memcpy(ndr->data+ndr->offset, &v, 8);
549         ndr->offset += 8;
550         return NDR_ERR_SUCCESS;
551 }
552
553 /*
554   push a pointer
555 */
556 _PUBLIC_ enum ndr_err_code ndr_push_pointer(struct ndr_push *ndr, int ndr_flags, void* v)
557 {
558         uintptr_t h = (intptr_t)v;
559         NDR_PUSH_ALIGN(ndr, sizeof(h));
560         NDR_PUSH_NEED_BYTES(ndr, sizeof(h));
561         memcpy(ndr->data+ndr->offset, &h, sizeof(h));
562         ndr->offset += sizeof(h);
563         return NDR_ERR_SUCCESS;
564 }
565
566 _PUBLIC_ enum ndr_err_code ndr_push_align(struct ndr_push *ndr, size_t size)
567 {
568         /* this is a nasty hack to make pidl work with NDR64 */
569         if (size == 5) {
570                 if (ndr->flags & LIBNDR_FLAG_NDR64) {
571                         size = 8;
572                 } else {
573                         size = 4;
574                 }
575         } else if (size == 3) {
576                 if (ndr->flags & LIBNDR_FLAG_NDR64) {
577                         size = 4;
578                 } else {
579                         size = 2;
580                 }
581         }
582         NDR_PUSH_ALIGN(ndr, size);
583         return NDR_ERR_SUCCESS;
584 }
585
586 _PUBLIC_ enum ndr_err_code ndr_pull_align(struct ndr_pull *ndr, size_t size)
587 {
588         /* this is a nasty hack to make pidl work with NDR64 */
589         if (size == 5) {
590                 if (ndr->flags & LIBNDR_FLAG_NDR64) {
591                         size = 8;
592                 } else {
593                         size = 4;
594                 }
595         } else if (size == 3) {
596                 if (ndr->flags & LIBNDR_FLAG_NDR64) {
597                         size = 4;
598                 } else {
599                         size = 2;
600                 }
601         }
602         NDR_PULL_ALIGN(ndr, size);
603         return NDR_ERR_SUCCESS;
604 }
605
606 _PUBLIC_ enum ndr_err_code ndr_push_union_align(struct ndr_push *ndr, size_t size)
607 {
608         /* MS-RPCE section 2.2.5.3.4.4 */
609         if (ndr->flags & LIBNDR_FLAG_NDR64) {
610                 return ndr_push_align(ndr, size);
611         }
612         return NDR_ERR_SUCCESS;
613 }
614
615 _PUBLIC_ enum ndr_err_code ndr_pull_union_align(struct ndr_pull *ndr, size_t size)
616 {
617         /* MS-RPCE section 2.2.5.3.4.4 */
618         if (ndr->flags & LIBNDR_FLAG_NDR64) {
619                 return ndr_pull_align(ndr, size);
620         }
621         return NDR_ERR_SUCCESS;
622 }
623
624 _PUBLIC_ enum ndr_err_code ndr_push_trailer_align(struct ndr_push *ndr, size_t size)
625 {
626         /* MS-RPCE section 2.2.5.3.4.1 */
627         if (ndr->flags & LIBNDR_FLAG_NDR64) {
628                 return ndr_push_align(ndr, size);
629         }
630         return NDR_ERR_SUCCESS;
631 }
632
633 _PUBLIC_ enum ndr_err_code ndr_pull_trailer_align(struct ndr_pull *ndr, size_t size)
634 {
635         /* MS-RPCE section 2.2.5.3.4.1 */
636         if (ndr->flags & LIBNDR_FLAG_NDR64) {
637                 return ndr_pull_align(ndr, size);
638         }
639         return NDR_ERR_SUCCESS;
640 }
641
642 /*
643   push some bytes
644 */
645 _PUBLIC_ enum ndr_err_code ndr_push_bytes(struct ndr_push *ndr, const uint8_t *data, uint32_t n)
646 {
647         NDR_PUSH_NEED_BYTES(ndr, n);
648         memcpy(ndr->data + ndr->offset, data, n);
649         ndr->offset += n;
650         return NDR_ERR_SUCCESS;
651 }
652
653 /*
654   push some zero bytes
655 */
656 _PUBLIC_ enum ndr_err_code ndr_push_zero(struct ndr_push *ndr, uint32_t n)
657 {
658         NDR_PUSH_NEED_BYTES(ndr, n);
659         memset(ndr->data + ndr->offset, 0, n);
660         ndr->offset += n;
661         return NDR_ERR_SUCCESS;
662 }
663
664 /*
665   push an array of uint8
666 */
667 _PUBLIC_ enum ndr_err_code ndr_push_array_uint8(struct ndr_push *ndr, int ndr_flags, const uint8_t *data, uint32_t n)
668 {
669         if (!(ndr_flags & NDR_SCALARS)) {
670                 return NDR_ERR_SUCCESS;
671         }
672         return ndr_push_bytes(ndr, data, n);
673 }
674
675 /*
676   push a unique non-zero value if a pointer is non-NULL, otherwise 0
677 */
678 _PUBLIC_ enum ndr_err_code ndr_push_unique_ptr(struct ndr_push *ndr, const void *p)
679 {
680         uint32_t ptr = 0;
681         if (p) {
682                 ptr = ndr->ptr_count * 4;
683                 ptr |= 0x00020000;
684                 ndr->ptr_count++;
685         }
686         return ndr_push_uint3264(ndr, NDR_SCALARS, ptr);
687 }
688
689 /*
690   push a 'simple' full non-zero value if a pointer is non-NULL, otherwise 0
691 */
692 _PUBLIC_ enum ndr_err_code ndr_push_full_ptr(struct ndr_push *ndr, const void *p)
693 {
694         uint32_t ptr = 0;
695         if (p) {
696                 /* Check if the pointer already exists and has an id */
697                 ptr = ndr_token_peek(&ndr->full_ptr_list, p);
698                 if (ptr == 0) {
699                         ndr->ptr_count++;
700                         ptr = ndr->ptr_count;
701                         ndr_token_store(ndr, &ndr->full_ptr_list, p, ptr);
702                 }
703         }
704         return ndr_push_uint3264(ndr, NDR_SCALARS, ptr);
705 }
706
707 /*
708   push always a 0, if a pointer is NULL it's a fatal error
709 */
710 _PUBLIC_ enum ndr_err_code ndr_push_ref_ptr(struct ndr_push *ndr)
711 {
712         return ndr_push_uint3264(ndr, NDR_SCALARS, 0xAEF1AEF1);
713 }
714
715
716 /*
717   push a NTTIME
718 */
719 _PUBLIC_ enum ndr_err_code ndr_push_NTTIME(struct ndr_push *ndr, int ndr_flags, NTTIME t)
720 {
721         NDR_CHECK(ndr_push_udlong(ndr, ndr_flags, t));
722         return NDR_ERR_SUCCESS;
723 }
724
725 /*
726   pull a NTTIME
727 */
728 _PUBLIC_ enum ndr_err_code ndr_pull_NTTIME(struct ndr_pull *ndr, int ndr_flags, NTTIME *t)
729 {
730         NDR_CHECK(ndr_pull_udlong(ndr, ndr_flags, t));
731         return NDR_ERR_SUCCESS;
732 }
733
734 /*
735   push a NTTIME_1sec
736 */
737 _PUBLIC_ enum ndr_err_code ndr_push_NTTIME_1sec(struct ndr_push *ndr, int ndr_flags, NTTIME t)
738 {
739         t /= 10000000;
740         NDR_CHECK(ndr_push_hyper(ndr, ndr_flags, t));
741         return NDR_ERR_SUCCESS;
742 }
743
744 /*
745   pull a NTTIME_1sec
746 */
747 _PUBLIC_ enum ndr_err_code ndr_pull_NTTIME_1sec(struct ndr_pull *ndr, int ndr_flags, NTTIME *t)
748 {
749         NDR_CHECK(ndr_pull_hyper(ndr, ndr_flags, t));
750         (*t) *= 10000000;
751         return NDR_ERR_SUCCESS;
752 }
753
754 /*
755   pull a NTTIME_hyper
756 */
757 _PUBLIC_ enum ndr_err_code ndr_pull_NTTIME_hyper(struct ndr_pull *ndr, int ndr_flags, NTTIME *t)
758 {
759         NDR_CHECK(ndr_pull_hyper(ndr, ndr_flags, t));
760         return NDR_ERR_SUCCESS;
761 }
762
763 /*
764   push a NTTIME_hyper
765 */
766 _PUBLIC_ enum ndr_err_code ndr_push_NTTIME_hyper(struct ndr_push *ndr, int ndr_flags, NTTIME t)
767 {
768         NDR_CHECK(ndr_push_hyper(ndr, ndr_flags, t));
769         return NDR_ERR_SUCCESS;
770 }
771
772 /*
773   push a time_t
774 */
775 _PUBLIC_ enum ndr_err_code ndr_push_time_t(struct ndr_push *ndr, int ndr_flags, time_t t)
776 {
777         return ndr_push_uint32(ndr, ndr_flags, t);
778 }
779
780 /*
781   pull a time_t
782 */
783 _PUBLIC_ enum ndr_err_code ndr_pull_time_t(struct ndr_pull *ndr, int ndr_flags, time_t *t)
784 {
785         uint32_t tt;
786         NDR_CHECK(ndr_pull_uint32(ndr, ndr_flags, &tt));
787         *t = tt;
788         return NDR_ERR_SUCCESS;
789 }
790
791
792 /*
793   pull a ipv4address
794 */
795 _PUBLIC_ enum ndr_err_code ndr_pull_ipv4address(struct ndr_pull *ndr, int ndr_flags, const char **address)
796 {
797         uint32_t addr;
798         struct in_addr in;
799         NDR_CHECK(ndr_pull_uint32(ndr, ndr_flags, &addr));
800         in.s_addr = htonl(addr);
801         *address = talloc_strdup(ndr->current_mem_ctx, inet_ntoa(in));
802         NDR_ERR_HAVE_NO_MEMORY(*address);
803         return NDR_ERR_SUCCESS;
804 }
805
806 /*
807   push a ipv4address
808 */
809 _PUBLIC_ enum ndr_err_code ndr_push_ipv4address(struct ndr_push *ndr, int ndr_flags, const char *address)
810 {
811         uint32_t addr;
812         if (!is_ipaddress(address)) {
813                 return ndr_push_error(ndr, NDR_ERR_IPV4ADDRESS,
814                                       "Invalid IPv4 address: '%s'", 
815                                       address);
816         }
817         addr = inet_addr(address);
818         NDR_CHECK(ndr_push_uint32(ndr, ndr_flags, htonl(addr)));
819         return NDR_ERR_SUCCESS;
820 }
821
822 /*
823   print a ipv4address
824 */
825 _PUBLIC_ void ndr_print_ipv4address(struct ndr_print *ndr, const char *name, 
826                            const char *address)
827 {
828         ndr->print(ndr, "%-25s: %s", name, address);
829 }
830
831
832 _PUBLIC_ void ndr_print_struct(struct ndr_print *ndr, const char *name, const char *type)
833 {
834         ndr->print(ndr, "%s: struct %s", name, type);
835 }
836
837 _PUBLIC_ void ndr_print_enum(struct ndr_print *ndr, const char *name, const char *type, 
838                     const char *val, uint32_t value)
839 {
840         if (ndr->flags & LIBNDR_PRINT_ARRAY_HEX) {
841                 ndr->print(ndr, "%-25s: %s (0x%X)", name, val?val:"UNKNOWN_ENUM_VALUE", value);
842         } else {
843                 ndr->print(ndr, "%-25s: %s (%d)", name, val?val:"UNKNOWN_ENUM_VALUE", value);
844         }
845 }
846
847 _PUBLIC_ void ndr_print_bitmap_flag(struct ndr_print *ndr, size_t size, const char *flag_name, uint32_t flag, uint32_t value)
848 {
849         /* this is an attempt to support multi-bit bitmap masks */
850         value &= flag;
851
852         while (!(flag & 1)) {
853                 flag >>= 1;
854                 value >>= 1;
855         }       
856         if (flag == 1) {
857                 ndr->print(ndr, "   %d: %-25s", value, flag_name);
858         } else {
859                 ndr->print(ndr, "0x%02x: %-25s (%d)", value, flag_name, value);
860         }
861 }
862
863 _PUBLIC_ void ndr_print_int8(struct ndr_print *ndr, const char *name, int8_t v)
864 {
865         ndr->print(ndr, "%-25s: %d", name, v);
866 }
867
868 _PUBLIC_ void ndr_print_uint8(struct ndr_print *ndr, const char *name, uint8_t v)
869 {
870         ndr->print(ndr, "%-25s: 0x%02x (%u)", name, v, v);
871 }
872
873 _PUBLIC_ void ndr_print_int16(struct ndr_print *ndr, const char *name, int16_t v)
874 {
875         ndr->print(ndr, "%-25s: %d", name, v);
876 }
877
878 _PUBLIC_ void ndr_print_uint16(struct ndr_print *ndr, const char *name, uint16_t v)
879 {
880         ndr->print(ndr, "%-25s: 0x%04x (%u)", name, v, v);
881 }
882
883 _PUBLIC_ void ndr_print_int32(struct ndr_print *ndr, const char *name, int32_t v)
884 {
885         ndr->print(ndr, "%-25s: %d", name, v);
886 }
887
888 _PUBLIC_ void ndr_print_uint32(struct ndr_print *ndr, const char *name, uint32_t v)
889 {
890         ndr->print(ndr, "%-25s: 0x%08x (%u)", name, v, v);
891 }
892
893 _PUBLIC_ void ndr_print_udlong(struct ndr_print *ndr, const char *name, uint64_t v)
894 {
895         ndr->print(ndr, "%-25s: 0x%016llx (%llu)", name, (unsigned long long)v, (unsigned long long)v);
896 }
897
898 _PUBLIC_ void ndr_print_udlongr(struct ndr_print *ndr, const char *name, uint64_t v)
899 {
900         ndr_print_udlong(ndr, name, v);
901 }
902
903 _PUBLIC_ void ndr_print_dlong(struct ndr_print *ndr, const char *name, int64_t v)
904 {
905         ndr->print(ndr, "%-25s: 0x%016llx (%lld)", name, (unsigned long long)v, (long long)v);
906 }
907
908 _PUBLIC_ void ndr_print_double(struct ndr_print *ndr, const char *name, double v)
909 {
910         ndr->print(ndr, "%-25s: %f", name, v);
911 }
912
913 _PUBLIC_ void ndr_print_hyper(struct ndr_print *ndr, const char *name, uint64_t v)
914 {
915         ndr_print_dlong(ndr, name, v);
916 }
917
918 _PUBLIC_ void ndr_print_pointer(struct ndr_print *ndr, const char *name, void *v)
919 {
920         ndr->print(ndr, "%-25s: %p", name, v);
921 }
922
923 _PUBLIC_ void ndr_print_ptr(struct ndr_print *ndr, const char *name, const void *p)
924 {
925         if (p) {
926                 ndr->print(ndr, "%-25s: *", name);
927         } else {
928                 ndr->print(ndr, "%-25s: NULL", name);
929         }
930 }
931
932 _PUBLIC_ void ndr_print_NTTIME(struct ndr_print *ndr, const char *name, NTTIME t)
933 {
934         ndr->print(ndr, "%-25s: %s", name, nt_time_string(ndr, t));
935 }
936
937 _PUBLIC_ void ndr_print_NTTIME_1sec(struct ndr_print *ndr, const char *name, NTTIME t)
938 {
939         /* this is a standard NTTIME here
940          * as it's already converted in the pull/push code
941          */
942         ndr_print_NTTIME(ndr, name, t);
943 }
944
945 _PUBLIC_ void ndr_print_NTTIME_hyper(struct ndr_print *ndr, const char *name, NTTIME t)
946 {
947         ndr_print_NTTIME(ndr, name, t);
948 }
949
950 _PUBLIC_ void ndr_print_time_t(struct ndr_print *ndr, const char *name, time_t t)
951 {
952         if (t == (time_t)-1 || t == 0) {
953                 ndr->print(ndr, "%-25s: (time_t)%d", name, (int)t);
954         } else {
955                 ndr->print(ndr, "%-25s: %s", name, timestring(ndr, t));
956         }
957 }
958
959 _PUBLIC_ void ndr_print_union(struct ndr_print *ndr, const char *name, int level, const char *type)
960 {
961         if (ndr->flags & LIBNDR_PRINT_ARRAY_HEX) {
962                 ndr->print(ndr, "%-25s: union %s(case 0x%X)", name, type, level);
963         } else {
964                 ndr->print(ndr, "%-25s: union %s(case %d)", name, type, level);
965         }
966 }
967
968 _PUBLIC_ void ndr_print_bad_level(struct ndr_print *ndr, const char *name, uint16_t level)
969 {
970         ndr->print(ndr, "UNKNOWN LEVEL %u", level);
971 }
972
973 _PUBLIC_ void ndr_print_array_uint8(struct ndr_print *ndr, const char *name, 
974                            const uint8_t *data, uint32_t count)
975 {
976         int i;
977
978         if (count <= 600 && (ndr->flags & LIBNDR_PRINT_ARRAY_HEX)) {
979                 char s[1202];
980                 for (i=0;i<count;i++) {
981                         snprintf(&s[i*2], 3, "%02x", data[i]);
982                 }
983                 s[i*2] = 0;
984                 ndr->print(ndr, "%-25s: %s", name, s);
985                 return;
986         }
987
988         ndr->print(ndr, "%s: ARRAY(%d)", name, count);
989         ndr->depth++;
990         for (i=0;i<count;i++) {
991                 char *idx=NULL;
992                 if (asprintf(&idx, "[%d]", i) != -1) {
993                         ndr_print_uint8(ndr, idx, data[i]);
994                         free(idx);
995                 }
996         }
997         ndr->depth--;   
998 }
999
1000 _PUBLIC_ void ndr_print_DATA_BLOB(struct ndr_print *ndr, const char *name, DATA_BLOB r)
1001 {
1002         ndr->print(ndr, "%-25s: DATA_BLOB length=%u", name, (unsigned)r.length);
1003         if (r.length) {
1004                 dump_data(10, r.data, r.length);
1005         }
1006 }
1007
1008
1009 /*
1010   push a DATA_BLOB onto the wire. 
1011 */
1012 _PUBLIC_ enum ndr_err_code ndr_push_DATA_BLOB(struct ndr_push *ndr, int ndr_flags, DATA_BLOB blob)
1013 {
1014         if (ndr->flags & LIBNDR_FLAG_REMAINING) {
1015                 /* nothing to do */
1016         } else if (ndr->flags & LIBNDR_ALIGN_FLAGS) {
1017                 if (ndr->flags & LIBNDR_FLAG_NOALIGN) {
1018                         blob.length = 0;
1019                 } else if (ndr->flags & LIBNDR_FLAG_ALIGN2) {
1020                         blob.length = NDR_ALIGN(ndr, 2);
1021                 } else if (ndr->flags & LIBNDR_FLAG_ALIGN4) {
1022                         blob.length = NDR_ALIGN(ndr, 4);
1023                 } else if (ndr->flags & LIBNDR_FLAG_ALIGN8) {
1024                         blob.length = NDR_ALIGN(ndr, 8);
1025                 }
1026                 NDR_PUSH_ALLOC_SIZE(ndr, blob.data, blob.length);
1027                 data_blob_clear(&blob);
1028         } else {
1029                 NDR_CHECK(ndr_push_uint32(ndr, NDR_SCALARS, blob.length));
1030         }
1031         NDR_CHECK(ndr_push_bytes(ndr, blob.data, blob.length));
1032         return NDR_ERR_SUCCESS;
1033 }
1034
1035 /*
1036   pull a DATA_BLOB from the wire. 
1037 */
1038 _PUBLIC_ enum ndr_err_code ndr_pull_DATA_BLOB(struct ndr_pull *ndr, int ndr_flags, DATA_BLOB *blob)
1039 {
1040         uint32_t length = 0;
1041
1042         if (ndr->flags & LIBNDR_FLAG_REMAINING) {
1043                 length = ndr->data_size - ndr->offset;
1044         } else if (ndr->flags & LIBNDR_ALIGN_FLAGS) {
1045                 if (ndr->flags & LIBNDR_FLAG_NOALIGN) {
1046                         length = 0;
1047                 } else if (ndr->flags & LIBNDR_FLAG_ALIGN2) {
1048                         length = NDR_ALIGN(ndr, 2);
1049                 } else if (ndr->flags & LIBNDR_FLAG_ALIGN4) {
1050                         length = NDR_ALIGN(ndr, 4);
1051                 } else if (ndr->flags & LIBNDR_FLAG_ALIGN8) {
1052                         length = NDR_ALIGN(ndr, 8);
1053                 }
1054                 if (ndr->data_size - ndr->offset < length) {
1055                         length = ndr->data_size - ndr->offset;
1056                 }
1057         } else {
1058                 NDR_CHECK(ndr_pull_uint32(ndr, NDR_SCALARS, &length));
1059         }
1060         NDR_PULL_NEED_BYTES(ndr, length);
1061         *blob = data_blob_talloc(ndr->current_mem_ctx, ndr->data+ndr->offset, length);
1062         ndr->offset += length;
1063         return NDR_ERR_SUCCESS;
1064 }
1065
1066 _PUBLIC_ uint32_t ndr_size_DATA_BLOB(int ret, const DATA_BLOB *data, int flags)
1067 {
1068         if (!data) return ret;
1069         return ret + data->length;
1070 }