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