librpc: fix builds without IPv6 suport (HP-UX 11.00)
[ddiss/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 #include "lib/util/util_net.h"
26
27 #define NDR_SVAL(ndr, ofs) (NDR_BE(ndr)?RSVAL(ndr->data,ofs):SVAL(ndr->data,ofs))
28 #define NDR_IVAL(ndr, ofs) (NDR_BE(ndr)?RIVAL(ndr->data,ofs):IVAL(ndr->data,ofs))
29 #define NDR_IVALS(ndr, ofs) (NDR_BE(ndr)?RIVALS(ndr->data,ofs):IVALS(ndr->data,ofs))
30 #define NDR_SSVAL(ndr, ofs, v) do { if (NDR_BE(ndr))  { RSSVAL(ndr->data,ofs,v); } else SSVAL(ndr->data,ofs,v); } while (0)
31 #define NDR_SIVAL(ndr, ofs, v) do { if (NDR_BE(ndr))  { RSIVAL(ndr->data,ofs,v); } else SIVAL(ndr->data,ofs,v); } while (0)
32 #define NDR_SIVALS(ndr, ofs, v) do { if (NDR_BE(ndr))  { RSIVALS(ndr->data,ofs,v); } else SIVALS(ndr->data,ofs,v); } while (0)
33
34
35 /*
36   check for data leaks from the server by looking for non-zero pad bytes
37   these could also indicate that real structure elements have been
38   mistaken for padding in the IDL
39 */
40 _PUBLIC_ void ndr_check_padding(struct ndr_pull *ndr, size_t n)
41 {
42         size_t ofs2 = (ndr->offset + (n-1)) & ~(n-1);
43         int i;
44         for (i=ndr->offset;i<ofs2;i++) {
45                 if (ndr->data[i] != 0) {
46                         break;
47                 }
48         }
49         if (i<ofs2) {
50                 DEBUG(0,("WARNING: Non-zero padding to %d: ", (int)n));
51                 for (i=ndr->offset;i<ofs2;i++) {
52                         DEBUG(0,("%02x ", ndr->data[i]));
53                 }
54                 DEBUG(0,("\n"));
55         }
56
57 }
58
59 /*
60   parse a int8_t
61 */
62 _PUBLIC_ enum ndr_err_code ndr_pull_int8(struct ndr_pull *ndr, int ndr_flags, int8_t *v)
63 {
64         NDR_PULL_NEED_BYTES(ndr, 1);
65         *v = (int8_t)CVAL(ndr->data, ndr->offset);
66         ndr->offset += 1;
67         return NDR_ERR_SUCCESS;
68 }
69
70 /*
71   parse a uint8_t
72 */
73 _PUBLIC_ enum ndr_err_code ndr_pull_uint8(struct ndr_pull *ndr, int ndr_flags, uint8_t *v)
74 {
75         NDR_PULL_NEED_BYTES(ndr, 1);
76         *v = CVAL(ndr->data, ndr->offset);
77         ndr->offset += 1;
78         return NDR_ERR_SUCCESS;
79 }
80
81 /*
82   parse a int16_t
83 */
84 _PUBLIC_ enum ndr_err_code ndr_pull_int16(struct ndr_pull *ndr, int ndr_flags, int16_t *v)
85 {
86         NDR_PULL_ALIGN(ndr, 2);
87         NDR_PULL_NEED_BYTES(ndr, 2);
88         *v = (uint16_t)NDR_SVAL(ndr, ndr->offset);
89         ndr->offset += 2;
90         return NDR_ERR_SUCCESS;
91 }
92
93 /*
94   parse a uint16_t
95 */
96 _PUBLIC_ enum ndr_err_code ndr_pull_uint16(struct ndr_pull *ndr, int ndr_flags, uint16_t *v)
97 {
98         NDR_PULL_ALIGN(ndr, 2);
99         NDR_PULL_NEED_BYTES(ndr, 2);
100         *v = NDR_SVAL(ndr, ndr->offset);
101         ndr->offset += 2;
102         return NDR_ERR_SUCCESS;
103 }
104
105 /*
106   parse a uint1632_t
107 */
108 _PUBLIC_ enum ndr_err_code ndr_pull_uint1632(struct ndr_pull *ndr, int ndr_flags, uint16_t *v)
109 {
110         if (unlikely(ndr->flags & LIBNDR_FLAG_NDR64)) {
111                 uint32_t v32 = 0;
112                 enum ndr_err_code err = ndr_pull_uint32(ndr, ndr_flags, &v32);
113                 *v = v32;
114                 if (unlikely(v32 != *v)) {
115                         DEBUG(0,(__location__ ": non-zero upper 16 bits 0x%08x\n", (unsigned)v32));
116                         return NDR_ERR_NDR64;
117                 }
118                 return err;
119         }
120         return ndr_pull_uint16(ndr, ndr_flags, v);
121 }
122
123 /*
124   parse a int32_t
125 */
126 _PUBLIC_ enum ndr_err_code ndr_pull_int32(struct ndr_pull *ndr, int ndr_flags, int32_t *v)
127 {
128         NDR_PULL_ALIGN(ndr, 4);
129         NDR_PULL_NEED_BYTES(ndr, 4);
130         *v = NDR_IVALS(ndr, ndr->offset);
131         ndr->offset += 4;
132         return NDR_ERR_SUCCESS;
133 }
134
135 /*
136   parse a uint32_t
137 */
138 _PUBLIC_ enum ndr_err_code ndr_pull_uint32(struct ndr_pull *ndr, int ndr_flags, uint32_t *v)
139 {
140         NDR_PULL_ALIGN(ndr, 4);
141         NDR_PULL_NEED_BYTES(ndr, 4);
142         *v = NDR_IVAL(ndr, ndr->offset);
143         ndr->offset += 4;
144         return NDR_ERR_SUCCESS;
145 }
146
147 /*
148   parse a arch dependent uint32/uint64
149 */
150 _PUBLIC_ enum ndr_err_code ndr_pull_uint3264(struct ndr_pull *ndr, int ndr_flags, uint32_t *v)
151 {
152         uint64_t v64;
153         enum ndr_err_code err;
154         if (likely(!(ndr->flags & LIBNDR_FLAG_NDR64))) {
155                 return ndr_pull_uint32(ndr, ndr_flags, v);
156         }
157         err = ndr_pull_hyper(ndr, ndr_flags, &v64);
158         *v = (uint32_t)v64;
159         if (unlikely(v64 != *v)) {
160                 DEBUG(0,(__location__ ": non-zero upper 32 bits 0x%016llx\n",
161                          (unsigned long long)v64));
162                 return NDR_ERR_NDR64;
163         }
164         return err;
165 }
166
167 /*
168   parse a double
169 */
170 _PUBLIC_ enum ndr_err_code ndr_pull_double(struct ndr_pull *ndr, int ndr_flags, double *v)
171 {
172         NDR_PULL_ALIGN(ndr, 8);
173         NDR_PULL_NEED_BYTES(ndr, 8);
174         memcpy(v, ndr->data+ndr->offset, 8);
175         ndr->offset += 8;
176         return NDR_ERR_SUCCESS;
177 }
178
179 /*
180   parse a pointer referent identifier stored in 2 bytes
181 */
182 _PUBLIC_ enum ndr_err_code ndr_pull_relative_ptr_short(struct ndr_pull *ndr, uint16_t *v)
183 {
184         NDR_CHECK(ndr_pull_uint16(ndr, NDR_SCALARS, v));
185         if (*v != 0) {
186                 ndr->ptr_count++;
187         }
188         *(v) -= ndr->relative_rap_convert;
189         return NDR_ERR_SUCCESS;
190 }
191
192 /*
193   parse a pointer referent identifier
194 */
195 _PUBLIC_ enum ndr_err_code ndr_pull_generic_ptr(struct ndr_pull *ndr, uint32_t *v)
196 {
197         NDR_CHECK(ndr_pull_uint3264(ndr, NDR_SCALARS, v));
198         if (*v != 0) {
199                 ndr->ptr_count++;
200         }
201         return NDR_ERR_SUCCESS;
202 }
203
204 /*
205   parse a ref pointer referent identifier
206 */
207 _PUBLIC_ enum ndr_err_code ndr_pull_ref_ptr(struct ndr_pull *ndr, uint32_t *v)
208 {
209         NDR_CHECK(ndr_pull_uint3264(ndr, NDR_SCALARS, v));
210         /* ref pointers always point to data */
211         *v = 1;
212         return NDR_ERR_SUCCESS;
213 }
214
215 /*
216   parse a udlong
217 */
218 _PUBLIC_ enum ndr_err_code ndr_pull_udlong(struct ndr_pull *ndr, int ndr_flags, uint64_t *v)
219 {
220         NDR_PULL_ALIGN(ndr, 4);
221         NDR_PULL_NEED_BYTES(ndr, 8);
222         *v = NDR_IVAL(ndr, ndr->offset);
223         *v |= (uint64_t)(NDR_IVAL(ndr, ndr->offset+4)) << 32;
224         ndr->offset += 8;
225         return NDR_ERR_SUCCESS;
226 }
227
228 /*
229   parse a udlongr
230 */
231 _PUBLIC_ enum ndr_err_code ndr_pull_udlongr(struct ndr_pull *ndr, int ndr_flags, uint64_t *v)
232 {
233         NDR_PULL_ALIGN(ndr, 4);
234         NDR_PULL_NEED_BYTES(ndr, 8);
235         *v = ((uint64_t)NDR_IVAL(ndr, ndr->offset)) << 32;
236         *v |= NDR_IVAL(ndr, ndr->offset+4);
237         ndr->offset += 8;
238         return NDR_ERR_SUCCESS;
239 }
240
241 /*
242   parse a dlong
243 */
244 _PUBLIC_ enum ndr_err_code ndr_pull_dlong(struct ndr_pull *ndr, int ndr_flags, int64_t *v)
245 {
246         return ndr_pull_udlong(ndr, ndr_flags, (uint64_t *)v);
247 }
248
249 /*
250   parse a hyper
251 */
252 _PUBLIC_ enum ndr_err_code ndr_pull_hyper(struct ndr_pull *ndr, int ndr_flags, uint64_t *v)
253 {
254         NDR_PULL_ALIGN(ndr, 8);
255         if (NDR_BE(ndr)) {
256                 return ndr_pull_udlongr(ndr, ndr_flags, v);
257         }
258         return ndr_pull_udlong(ndr, ndr_flags, v);
259 }
260
261 /*
262   parse a pointer
263 */
264 _PUBLIC_ enum ndr_err_code ndr_pull_pointer(struct ndr_pull *ndr, int ndr_flags, void* *v)
265 {
266         uintptr_t h;
267         NDR_PULL_ALIGN(ndr, sizeof(h));
268         NDR_PULL_NEED_BYTES(ndr, sizeof(h));
269         memcpy(&h, ndr->data+ndr->offset, sizeof(h));
270         ndr->offset += sizeof(h);
271         *v = (void *)h;
272         return NDR_ERR_SUCCESS;
273 }
274
275 /*
276   pull a NTSTATUS
277 */
278 _PUBLIC_ enum ndr_err_code ndr_pull_NTSTATUS(struct ndr_pull *ndr, int ndr_flags, NTSTATUS *status)
279 {
280         uint32_t v;
281         NDR_CHECK(ndr_pull_uint32(ndr, NDR_SCALARS, &v));
282         *status = NT_STATUS(v);
283         return NDR_ERR_SUCCESS;
284 }
285
286 /*
287   push a NTSTATUS
288 */
289 _PUBLIC_ enum ndr_err_code ndr_push_NTSTATUS(struct ndr_push *ndr, int ndr_flags, NTSTATUS status)
290 {
291         return ndr_push_uint32(ndr, ndr_flags, NT_STATUS_V(status));
292 }
293
294 _PUBLIC_ void ndr_print_NTSTATUS(struct ndr_print *ndr, const char *name, NTSTATUS r)
295 {
296         ndr->print(ndr, "%-25s: %s", name, nt_errstr(r));
297 }
298
299 /*
300   pull a WERROR
301 */
302 _PUBLIC_ enum ndr_err_code ndr_pull_WERROR(struct ndr_pull *ndr, int ndr_flags, WERROR *status)
303 {
304         uint32_t v;
305         NDR_CHECK(ndr_pull_uint32(ndr, NDR_SCALARS, &v));
306         *status = W_ERROR(v);
307         return NDR_ERR_SUCCESS;
308 }
309
310
311 /*
312   parse a uint8_t enum
313 */
314 _PUBLIC_ enum ndr_err_code ndr_pull_enum_uint8(struct ndr_pull *ndr, int ndr_flags, uint8_t *v)
315 {
316         return ndr_pull_uint8(ndr, ndr_flags, v);
317 }
318
319 /*
320   parse a uint16_t enum
321 */
322 _PUBLIC_ enum ndr_err_code ndr_pull_enum_uint16(struct ndr_pull *ndr, int ndr_flags, uint16_t *v)
323 {
324         return ndr_pull_uint16(ndr, ndr_flags, v);
325 }
326
327 /*
328   parse a uint1632_t enum (uint32_t on NDR64)
329 */
330 _PUBLIC_ enum ndr_err_code ndr_pull_enum_uint1632(struct ndr_pull *ndr, int ndr_flags, uint16_t *v)
331 {
332         if (unlikely(ndr->flags & LIBNDR_FLAG_NDR64)) {
333                 uint32_t v32;
334                 NDR_CHECK(ndr_pull_uint32(ndr, ndr_flags, &v32));
335                 *v = v32;
336                 if (v32 != *v) {
337                         DEBUG(0,(__location__ ": non-zero upper 16 bits 0x%08x\n", (unsigned)v32));
338                         return NDR_ERR_NDR64;
339                 }
340                 return NDR_ERR_SUCCESS;
341         }
342         return ndr_pull_uint16(ndr, ndr_flags, v);
343 }
344
345 /*
346   parse a uint32_t enum
347 */
348 _PUBLIC_ enum ndr_err_code ndr_pull_enum_uint32(struct ndr_pull *ndr, int ndr_flags, uint32_t *v)
349 {
350         return ndr_pull_uint32(ndr, ndr_flags, v);
351 }
352
353 /*
354   push a uint8_t enum
355 */
356 _PUBLIC_ enum ndr_err_code ndr_push_enum_uint8(struct ndr_push *ndr, int ndr_flags, uint8_t v)
357 {
358         return ndr_push_uint8(ndr, ndr_flags, v);
359 }
360
361 /*
362   push a uint16_t enum
363 */
364 _PUBLIC_ enum ndr_err_code ndr_push_enum_uint16(struct ndr_push *ndr, int ndr_flags, uint16_t v)
365 {
366         return ndr_push_uint16(ndr, ndr_flags, v);
367 }
368
369 /*
370   push a uint32_t enum
371 */
372 _PUBLIC_ enum ndr_err_code ndr_push_enum_uint32(struct ndr_push *ndr, int ndr_flags, uint32_t v)
373 {
374         return ndr_push_uint32(ndr, ndr_flags, v);
375 }
376
377 /*
378   push a uint1632_t enum
379 */
380 _PUBLIC_ enum ndr_err_code ndr_push_enum_uint1632(struct ndr_push *ndr, int ndr_flags, uint16_t v)
381 {
382         if (unlikely(ndr->flags & LIBNDR_FLAG_NDR64)) {
383                 return ndr_push_uint32(ndr, ndr_flags, v);
384         }
385         return ndr_push_uint16(ndr, ndr_flags, v);
386 }
387
388 /*
389   push a WERROR
390 */
391 _PUBLIC_ enum ndr_err_code ndr_push_WERROR(struct ndr_push *ndr, int ndr_flags, WERROR status)
392 {
393         return ndr_push_uint32(ndr, NDR_SCALARS, W_ERROR_V(status));
394 }
395
396 _PUBLIC_ void ndr_print_WERROR(struct ndr_print *ndr, const char *name, WERROR r)
397 {
398         ndr->print(ndr, "%-25s: %s", name, win_errstr(r));
399 }
400
401 /*
402   parse a set of bytes
403 */
404 _PUBLIC_ enum ndr_err_code ndr_pull_bytes(struct ndr_pull *ndr, uint8_t *data, uint32_t n)
405 {
406         NDR_PULL_NEED_BYTES(ndr, n);
407         memcpy(data, ndr->data + ndr->offset, n);
408         ndr->offset += n;
409         return NDR_ERR_SUCCESS;
410 }
411
412 /*
413   pull an array of uint8
414 */
415 _PUBLIC_ enum ndr_err_code ndr_pull_array_uint8(struct ndr_pull *ndr, int ndr_flags, uint8_t *data, uint32_t n)
416 {
417         if (!(ndr_flags & NDR_SCALARS)) {
418                 return NDR_ERR_SUCCESS;
419         }
420         return ndr_pull_bytes(ndr, data, n);
421 }
422
423 /*
424   push a int8_t
425 */
426 _PUBLIC_ enum ndr_err_code ndr_push_int8(struct ndr_push *ndr, int ndr_flags, int8_t v)
427 {
428         NDR_PUSH_NEED_BYTES(ndr, 1);
429         SCVAL(ndr->data, ndr->offset, (uint8_t)v);
430         ndr->offset += 1;
431         return NDR_ERR_SUCCESS;
432 }
433
434 /*
435   push a uint8_t
436 */
437 _PUBLIC_ enum ndr_err_code ndr_push_uint8(struct ndr_push *ndr, int ndr_flags, uint8_t v)
438 {
439         NDR_PUSH_NEED_BYTES(ndr, 1);
440         SCVAL(ndr->data, ndr->offset, v);
441         ndr->offset += 1;
442         return NDR_ERR_SUCCESS;
443 }
444
445 /*
446   push a int16_t
447 */
448 _PUBLIC_ enum ndr_err_code ndr_push_int16(struct ndr_push *ndr, int ndr_flags, int16_t v)
449 {
450         NDR_PUSH_ALIGN(ndr, 2);
451         NDR_PUSH_NEED_BYTES(ndr, 2);
452         NDR_SSVAL(ndr, ndr->offset, (uint16_t)v);
453         ndr->offset += 2;
454         return NDR_ERR_SUCCESS;
455 }
456
457 /*
458   push a uint16_t
459 */
460 _PUBLIC_ enum ndr_err_code ndr_push_uint16(struct ndr_push *ndr, int ndr_flags, uint16_t v)
461 {
462         NDR_PUSH_ALIGN(ndr, 2);
463         NDR_PUSH_NEED_BYTES(ndr, 2);
464         NDR_SSVAL(ndr, ndr->offset, v);
465         ndr->offset += 2;
466         return NDR_ERR_SUCCESS;
467 }
468
469 /*
470   push a uint1632
471 */
472 _PUBLIC_ enum ndr_err_code ndr_push_uint1632(struct ndr_push *ndr, int ndr_flags, uint16_t v)
473 {
474         if (unlikely(ndr->flags & LIBNDR_FLAG_NDR64)) {
475                 return ndr_push_uint32(ndr, ndr_flags, v);
476         }
477         return ndr_push_uint16(ndr, ndr_flags, v);
478 }
479
480 /*
481   push a int32_t
482 */
483 _PUBLIC_ enum ndr_err_code ndr_push_int32(struct ndr_push *ndr, int ndr_flags, int32_t v)
484 {
485         NDR_PUSH_ALIGN(ndr, 4);
486         NDR_PUSH_NEED_BYTES(ndr, 4);
487         NDR_SIVALS(ndr, ndr->offset, v);
488         ndr->offset += 4;
489         return NDR_ERR_SUCCESS;
490 }
491
492 /*
493   push a uint32_t
494 */
495 _PUBLIC_ enum ndr_err_code ndr_push_uint32(struct ndr_push *ndr, int ndr_flags, uint32_t v)
496 {
497         NDR_PUSH_ALIGN(ndr, 4);
498         NDR_PUSH_NEED_BYTES(ndr, 4);
499         NDR_SIVAL(ndr, ndr->offset, v);
500         ndr->offset += 4;
501         return NDR_ERR_SUCCESS;
502 }
503
504 /*
505   push a uint3264
506 */
507 _PUBLIC_ enum ndr_err_code ndr_push_uint3264(struct ndr_push *ndr, int ndr_flags, uint32_t v)
508 {
509         if (unlikely(ndr->flags & LIBNDR_FLAG_NDR64)) {
510                 return ndr_push_hyper(ndr, ndr_flags, v);
511         }
512         return ndr_push_uint32(ndr, ndr_flags, v);
513 }
514
515 /*
516   push a udlong
517 */
518 _PUBLIC_ enum ndr_err_code ndr_push_udlong(struct ndr_push *ndr, int ndr_flags, uint64_t v)
519 {
520         NDR_PUSH_ALIGN(ndr, 4);
521         NDR_PUSH_NEED_BYTES(ndr, 8);
522         NDR_SIVAL(ndr, ndr->offset, (v & 0xFFFFFFFF));
523         NDR_SIVAL(ndr, ndr->offset+4, (v>>32));
524         ndr->offset += 8;
525         return NDR_ERR_SUCCESS;
526 }
527
528 /*
529   push a udlongr
530 */
531 _PUBLIC_ enum ndr_err_code ndr_push_udlongr(struct ndr_push *ndr, int ndr_flags, uint64_t v)
532 {
533         NDR_PUSH_ALIGN(ndr, 4);
534         NDR_PUSH_NEED_BYTES(ndr, 8);
535         NDR_SIVAL(ndr, ndr->offset, (v>>32));
536         NDR_SIVAL(ndr, ndr->offset+4, (v & 0xFFFFFFFF));
537         ndr->offset += 8;
538         return NDR_ERR_SUCCESS;
539 }
540
541 /*
542   push a dlong
543 */
544 _PUBLIC_ enum ndr_err_code ndr_push_dlong(struct ndr_push *ndr, int ndr_flags, int64_t v)
545 {
546         return ndr_push_udlong(ndr, NDR_SCALARS, (uint64_t)v);
547 }
548
549 /*
550   push a hyper
551 */
552 _PUBLIC_ enum ndr_err_code ndr_push_hyper(struct ndr_push *ndr, int ndr_flags, uint64_t v)
553 {
554         NDR_PUSH_ALIGN(ndr, 8);
555         if (NDR_BE(ndr)) {
556                 return ndr_push_udlongr(ndr, NDR_SCALARS, v);
557         }
558         return ndr_push_udlong(ndr, NDR_SCALARS, v);
559 }
560
561 /*
562   push a double
563 */
564 _PUBLIC_ enum ndr_err_code ndr_push_double(struct ndr_push *ndr, int ndr_flags, double v)
565 {
566         NDR_PUSH_ALIGN(ndr, 8);
567         NDR_PUSH_NEED_BYTES(ndr, 8);
568         memcpy(ndr->data+ndr->offset, &v, 8);
569         ndr->offset += 8;
570         return NDR_ERR_SUCCESS;
571 }
572
573 /*
574   push a pointer
575 */
576 _PUBLIC_ enum ndr_err_code ndr_push_pointer(struct ndr_push *ndr, int ndr_flags, void* v)
577 {
578         uintptr_t h = (intptr_t)v;
579         NDR_PUSH_ALIGN(ndr, sizeof(h));
580         NDR_PUSH_NEED_BYTES(ndr, sizeof(h));
581         memcpy(ndr->data+ndr->offset, &h, sizeof(h));
582         ndr->offset += sizeof(h);
583         return NDR_ERR_SUCCESS;
584 }
585
586 _PUBLIC_ enum ndr_err_code ndr_push_align(struct ndr_push *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_PUSH_ALIGN(ndr, size);
603         return NDR_ERR_SUCCESS;
604 }
605
606 _PUBLIC_ enum ndr_err_code ndr_pull_align(struct ndr_pull *ndr, size_t size)
607 {
608         /* this is a nasty hack to make pidl work with NDR64 */
609         if (size == 5) {
610                 if (ndr->flags & LIBNDR_FLAG_NDR64) {
611                         size = 8;
612                 } else {
613                         size = 4;
614                 }
615         } else if (size == 3) {
616                 if (ndr->flags & LIBNDR_FLAG_NDR64) {
617                         size = 4;
618                 } else {
619                         size = 2;
620                 }
621         }
622         NDR_PULL_ALIGN(ndr, size);
623         return NDR_ERR_SUCCESS;
624 }
625
626 _PUBLIC_ enum ndr_err_code ndr_push_union_align(struct ndr_push *ndr, size_t size)
627 {
628         /* MS-RPCE section 2.2.5.3.4.4 */
629         if (ndr->flags & LIBNDR_FLAG_NDR64) {
630                 return ndr_push_align(ndr, size);
631         }
632         return NDR_ERR_SUCCESS;
633 }
634
635 _PUBLIC_ enum ndr_err_code ndr_pull_union_align(struct ndr_pull *ndr, size_t size)
636 {
637         /* MS-RPCE section 2.2.5.3.4.4 */
638         if (ndr->flags & LIBNDR_FLAG_NDR64) {
639                 return ndr_pull_align(ndr, size);
640         }
641         return NDR_ERR_SUCCESS;
642 }
643
644 _PUBLIC_ enum ndr_err_code ndr_push_trailer_align(struct ndr_push *ndr, size_t size)
645 {
646         /* MS-RPCE section 2.2.5.3.4.1 */
647         if (ndr->flags & LIBNDR_FLAG_NDR64) {
648                 return ndr_push_align(ndr, size);
649         }
650         return NDR_ERR_SUCCESS;
651 }
652
653 _PUBLIC_ enum ndr_err_code ndr_pull_trailer_align(struct ndr_pull *ndr, size_t size)
654 {
655         /* MS-RPCE section 2.2.5.3.4.1 */
656         if (ndr->flags & LIBNDR_FLAG_NDR64) {
657                 return ndr_pull_align(ndr, size);
658         }
659         return NDR_ERR_SUCCESS;
660 }
661
662 /*
663   push some bytes
664 */
665 _PUBLIC_ enum ndr_err_code ndr_push_bytes(struct ndr_push *ndr, const uint8_t *data, uint32_t n)
666 {
667         NDR_PUSH_NEED_BYTES(ndr, n);
668         memcpy(ndr->data + ndr->offset, data, n);
669         ndr->offset += n;
670         return NDR_ERR_SUCCESS;
671 }
672
673 /*
674   push some zero bytes
675 */
676 _PUBLIC_ enum ndr_err_code ndr_push_zero(struct ndr_push *ndr, uint32_t n)
677 {
678         NDR_PUSH_NEED_BYTES(ndr, n);
679         memset(ndr->data + ndr->offset, 0, n);
680         ndr->offset += n;
681         return NDR_ERR_SUCCESS;
682 }
683
684 /*
685   push an array of uint8
686 */
687 _PUBLIC_ enum ndr_err_code ndr_push_array_uint8(struct ndr_push *ndr, int ndr_flags, const uint8_t *data, uint32_t n)
688 {
689         if (!(ndr_flags & NDR_SCALARS)) {
690                 return NDR_ERR_SUCCESS;
691         }
692         return ndr_push_bytes(ndr, data, n);
693 }
694
695 /*
696   push a unique non-zero value if a pointer is non-NULL, otherwise 0
697 */
698 _PUBLIC_ enum ndr_err_code ndr_push_unique_ptr(struct ndr_push *ndr, const void *p)
699 {
700         uint32_t ptr = 0;
701         if (p) {
702                 ptr = ndr->ptr_count * 4;
703                 ptr |= 0x00020000;
704                 ndr->ptr_count++;
705         }
706         return ndr_push_uint3264(ndr, NDR_SCALARS, ptr);
707 }
708
709 /*
710   push a 'simple' full non-zero value if a pointer is non-NULL, otherwise 0
711 */
712 _PUBLIC_ enum ndr_err_code ndr_push_full_ptr(struct ndr_push *ndr, const void *p)
713 {
714         uint32_t ptr = 0;
715         if (p) {
716                 /* Check if the pointer already exists and has an id */
717                 ptr = ndr_token_peek(&ndr->full_ptr_list, p);
718                 if (ptr == 0) {
719                         ndr->ptr_count++;
720                         ptr = ndr->ptr_count;
721                         ndr_token_store(ndr, &ndr->full_ptr_list, p, ptr);
722                 }
723         }
724         return ndr_push_uint3264(ndr, NDR_SCALARS, ptr);
725 }
726
727 /*
728   push always a 0, if a pointer is NULL it's a fatal error
729 */
730 _PUBLIC_ enum ndr_err_code ndr_push_ref_ptr(struct ndr_push *ndr)
731 {
732         return ndr_push_uint3264(ndr, NDR_SCALARS, 0xAEF1AEF1);
733 }
734
735
736 /*
737   push a NTTIME
738 */
739 _PUBLIC_ enum ndr_err_code ndr_push_NTTIME(struct ndr_push *ndr, int ndr_flags, NTTIME t)
740 {
741         NDR_CHECK(ndr_push_udlong(ndr, ndr_flags, t));
742         return NDR_ERR_SUCCESS;
743 }
744
745 /*
746   pull a NTTIME
747 */
748 _PUBLIC_ enum ndr_err_code ndr_pull_NTTIME(struct ndr_pull *ndr, int ndr_flags, NTTIME *t)
749 {
750         NDR_CHECK(ndr_pull_udlong(ndr, ndr_flags, t));
751         return NDR_ERR_SUCCESS;
752 }
753
754 /*
755   push a NTTIME_1sec
756 */
757 _PUBLIC_ enum ndr_err_code ndr_push_NTTIME_1sec(struct ndr_push *ndr, int ndr_flags, NTTIME t)
758 {
759         t /= 10000000;
760         NDR_CHECK(ndr_push_hyper(ndr, ndr_flags, t));
761         return NDR_ERR_SUCCESS;
762 }
763
764 /*
765   pull a NTTIME_1sec
766 */
767 _PUBLIC_ enum ndr_err_code ndr_pull_NTTIME_1sec(struct ndr_pull *ndr, int ndr_flags, NTTIME *t)
768 {
769         NDR_CHECK(ndr_pull_hyper(ndr, ndr_flags, t));
770         (*t) *= 10000000;
771         return NDR_ERR_SUCCESS;
772 }
773
774 /*
775   pull a NTTIME_hyper
776 */
777 _PUBLIC_ enum ndr_err_code ndr_pull_NTTIME_hyper(struct ndr_pull *ndr, int ndr_flags, NTTIME *t)
778 {
779         NDR_CHECK(ndr_pull_hyper(ndr, ndr_flags, t));
780         return NDR_ERR_SUCCESS;
781 }
782
783 /*
784   push a NTTIME_hyper
785 */
786 _PUBLIC_ enum ndr_err_code ndr_push_NTTIME_hyper(struct ndr_push *ndr, int ndr_flags, NTTIME t)
787 {
788         NDR_CHECK(ndr_push_hyper(ndr, ndr_flags, t));
789         return NDR_ERR_SUCCESS;
790 }
791
792 /*
793   push a time_t
794 */
795 _PUBLIC_ enum ndr_err_code ndr_push_time_t(struct ndr_push *ndr, int ndr_flags, time_t t)
796 {
797         return ndr_push_uint32(ndr, ndr_flags, t);
798 }
799
800 /*
801   pull a time_t
802 */
803 _PUBLIC_ enum ndr_err_code ndr_pull_time_t(struct ndr_pull *ndr, int ndr_flags, time_t *t)
804 {
805         uint32_t tt;
806         NDR_CHECK(ndr_pull_uint32(ndr, ndr_flags, &tt));
807         *t = tt;
808         return NDR_ERR_SUCCESS;
809 }
810
811
812 /*
813   pull a ipv4address
814 */
815 _PUBLIC_ enum ndr_err_code ndr_pull_ipv4address(struct ndr_pull *ndr, int ndr_flags, const char **address)
816 {
817         uint32_t addr;
818         struct in_addr in;
819         NDR_CHECK(ndr_pull_uint32(ndr, ndr_flags, &addr));
820         in.s_addr = htonl(addr);
821         *address = talloc_strdup(ndr->current_mem_ctx, inet_ntoa(in));
822         NDR_ERR_HAVE_NO_MEMORY(*address);
823         return NDR_ERR_SUCCESS;
824 }
825
826 /*
827   push a ipv4address
828 */
829 _PUBLIC_ enum ndr_err_code ndr_push_ipv4address(struct ndr_push *ndr, int ndr_flags, const char *address)
830 {
831         uint32_t addr;
832         if (!is_ipaddress(address)) {
833                 return ndr_push_error(ndr, NDR_ERR_IPV4ADDRESS,
834                                       "Invalid IPv4 address: '%s'",
835                                       address);
836         }
837         addr = inet_addr(address);
838         NDR_CHECK(ndr_push_uint32(ndr, ndr_flags, htonl(addr)));
839         return NDR_ERR_SUCCESS;
840 }
841
842 /*
843   print a ipv4address
844 */
845 _PUBLIC_ void ndr_print_ipv4address(struct ndr_print *ndr, const char *name,
846                            const char *address)
847 {
848         ndr->print(ndr, "%-25s: %s", name, address);
849 }
850
851 #ifdef AF_INET6
852 /*
853   pull a ipv6address
854 */
855 #define IPV6_BYTES 16
856 #define IPV6_ADDR_STR_LEN 39
857 _PUBLIC_ enum ndr_err_code ndr_pull_ipv6address(struct ndr_pull *ndr, int ndr_flags, const char **address)
858 {
859         uint8_t addr[IPV6_BYTES];
860         char *addr_str = talloc_strdup(ndr->current_mem_ctx, "");
861         int i;
862         NDR_CHECK(ndr_pull_array_uint8(ndr, ndr_flags, addr, IPV6_BYTES));
863         for (i = 0; i < IPV6_BYTES; ++i) {
864                 addr_str = talloc_asprintf_append(addr_str, "%02x", addr[i]);
865                 /* We need a ':' every second byte but the last one */
866                 if (i%2 == 1 && i != (IPV6_BYTES - 1)) {
867                         addr_str = talloc_strdup_append(addr_str, ":");
868                 }
869         }
870         *address = addr_str;
871         NDR_ERR_HAVE_NO_MEMORY(*address);
872         return NDR_ERR_SUCCESS;
873 }
874
875 /*
876   push a ipv6address
877 */
878 _PUBLIC_ enum ndr_err_code ndr_push_ipv6address(struct ndr_push *ndr, int ndr_flags, const char *address)
879 {
880         uint8_t addr[IPV6_BYTES];
881         int ret;
882
883         if (!is_ipaddress(address)) {
884                 return ndr_push_error(ndr, NDR_ERR_IPV6ADDRESS,
885                                       "Invalid IPv6 address: '%s'",
886                                       address);
887         }
888         ret = inet_pton(AF_INET6, address, addr);
889         if (ret <= 0) {
890                 return NDR_ERR_IPV6ADDRESS;
891         }
892
893         NDR_CHECK(ndr_push_array_uint8(ndr, ndr_flags, addr, IPV6_BYTES));
894
895         return NDR_ERR_SUCCESS;
896 }
897
898 /*
899   print a ipv6address
900 */
901 _PUBLIC_ void ndr_print_ipv6address(struct ndr_print *ndr, const char *name,
902                            const char *address)
903 {
904         ndr->print(ndr, "%-25s: %s", name, address);
905 }
906 #undef IPV6_BYTES
907 #endif
908
909 _PUBLIC_ void ndr_print_struct(struct ndr_print *ndr, const char *name, const char *type)
910 {
911         ndr->print(ndr, "%s: struct %s", name, type);
912 }
913
914 _PUBLIC_ void ndr_print_null(struct ndr_print *ndr)
915 {
916         ndr->print(ndr, "UNEXPECTED NULL POINTER");
917 }
918
919 _PUBLIC_ void ndr_print_enum(struct ndr_print *ndr, const char *name, const char *type, 
920                     const char *val, uint32_t value)
921 {
922         if (ndr->flags & LIBNDR_PRINT_ARRAY_HEX) {
923                 ndr->print(ndr, "%-25s: %s (0x%X)", name, val?val:"UNKNOWN_ENUM_VALUE", value);
924         } else {
925                 ndr->print(ndr, "%-25s: %s (%d)", name, val?val:"UNKNOWN_ENUM_VALUE", value);
926         }
927 }
928
929 _PUBLIC_ void ndr_print_bitmap_flag(struct ndr_print *ndr, size_t size, const char *flag_name, uint32_t flag, uint32_t value)
930 {
931         /* this is an attempt to support multi-bit bitmap masks */
932         value &= flag;
933
934         while (!(flag & 1)) {
935                 flag >>= 1;
936                 value >>= 1;
937         }       
938         if (flag == 1) {
939                 ndr->print(ndr, "   %d: %-25s", value, flag_name);
940         } else {
941                 ndr->print(ndr, "0x%02x: %-25s (%d)", value, flag_name, value);
942         }
943 }
944
945 _PUBLIC_ void ndr_print_int8(struct ndr_print *ndr, const char *name, int8_t v)
946 {
947         ndr->print(ndr, "%-25s: %d", name, v);
948 }
949
950 _PUBLIC_ void ndr_print_uint8(struct ndr_print *ndr, const char *name, uint8_t v)
951 {
952         ndr->print(ndr, "%-25s: 0x%02x (%u)", name, v, v);
953 }
954
955 _PUBLIC_ void ndr_print_int16(struct ndr_print *ndr, const char *name, int16_t v)
956 {
957         ndr->print(ndr, "%-25s: %d", name, v);
958 }
959
960 _PUBLIC_ void ndr_print_uint16(struct ndr_print *ndr, const char *name, uint16_t v)
961 {
962         ndr->print(ndr, "%-25s: 0x%04x (%u)", name, v, v);
963 }
964
965 _PUBLIC_ void ndr_print_int32(struct ndr_print *ndr, const char *name, int32_t v)
966 {
967         ndr->print(ndr, "%-25s: %d", name, v);
968 }
969
970 _PUBLIC_ void ndr_print_uint32(struct ndr_print *ndr, const char *name, uint32_t v)
971 {
972         ndr->print(ndr, "%-25s: 0x%08x (%u)", name, v, v);
973 }
974
975 _PUBLIC_ void ndr_print_int3264(struct ndr_print *ndr, const char *name, int32_t v)
976 {
977         ndr->print(ndr, "%-25s: %d", name, v);
978 }
979
980 _PUBLIC_ void ndr_print_uint3264(struct ndr_print *ndr, const char *name, uint32_t v)
981 {
982         ndr->print(ndr, "%-25s: 0x%08x (%u)", name, v, v);
983 }
984
985 _PUBLIC_ void ndr_print_udlong(struct ndr_print *ndr, const char *name, uint64_t v)
986 {
987         ndr->print(ndr, "%-25s: 0x%016llx (%llu)", name, (unsigned long long)v, (unsigned long long)v);
988 }
989
990 _PUBLIC_ void ndr_print_udlongr(struct ndr_print *ndr, const char *name, uint64_t v)
991 {
992         ndr_print_udlong(ndr, name, v);
993 }
994
995 _PUBLIC_ void ndr_print_dlong(struct ndr_print *ndr, const char *name, int64_t v)
996 {
997         ndr->print(ndr, "%-25s: 0x%016llx (%lld)", name, (unsigned long long)v, (long long)v);
998 }
999
1000 _PUBLIC_ void ndr_print_double(struct ndr_print *ndr, const char *name, double v)
1001 {
1002         ndr->print(ndr, "%-25s: %f", name, v);
1003 }
1004
1005 _PUBLIC_ void ndr_print_hyper(struct ndr_print *ndr, const char *name, uint64_t v)
1006 {
1007         ndr_print_dlong(ndr, name, v);
1008 }
1009
1010 _PUBLIC_ void ndr_print_pointer(struct ndr_print *ndr, const char *name, void *v)
1011 {
1012         ndr->print(ndr, "%-25s: %p", name, v);
1013 }
1014
1015 _PUBLIC_ void ndr_print_ptr(struct ndr_print *ndr, const char *name, const void *p)
1016 {
1017         if (p) {
1018                 ndr->print(ndr, "%-25s: *", name);
1019         } else {
1020                 ndr->print(ndr, "%-25s: NULL", name);
1021         }
1022 }
1023
1024 _PUBLIC_ void ndr_print_NTTIME(struct ndr_print *ndr, const char *name, NTTIME t)
1025 {
1026         ndr->print(ndr, "%-25s: %s", name, nt_time_string(ndr, t));
1027 }
1028
1029 _PUBLIC_ void ndr_print_NTTIME_1sec(struct ndr_print *ndr, const char *name, NTTIME t)
1030 {
1031         /* this is a standard NTTIME here
1032          * as it's already converted in the pull/push code
1033          */
1034         ndr_print_NTTIME(ndr, name, t);
1035 }
1036
1037 _PUBLIC_ void ndr_print_NTTIME_hyper(struct ndr_print *ndr, const char *name, NTTIME t)
1038 {
1039         ndr_print_NTTIME(ndr, name, t);
1040 }
1041
1042 _PUBLIC_ void ndr_print_time_t(struct ndr_print *ndr, const char *name, time_t t)
1043 {
1044         if (t == (time_t)-1 || t == 0) {
1045                 ndr->print(ndr, "%-25s: (time_t)%d", name, (int)t);
1046         } else {
1047                 ndr->print(ndr, "%-25s: %s", name, timestring(ndr, t));
1048         }
1049 }
1050
1051 _PUBLIC_ void ndr_print_union(struct ndr_print *ndr, const char *name, int level, const char *type)
1052 {
1053         if (ndr->flags & LIBNDR_PRINT_ARRAY_HEX) {
1054                 ndr->print(ndr, "%-25s: union %s(case 0x%X)", name, type, level);
1055         } else {
1056                 ndr->print(ndr, "%-25s: union %s(case %d)", name, type, level);
1057         }
1058 }
1059
1060 _PUBLIC_ void ndr_print_bad_level(struct ndr_print *ndr, const char *name, uint16_t level)
1061 {
1062         ndr->print(ndr, "UNKNOWN LEVEL %u", level);
1063 }
1064
1065 _PUBLIC_ void ndr_print_array_uint8(struct ndr_print *ndr, const char *name, 
1066                            const uint8_t *data, uint32_t count)
1067 {
1068         int i;
1069
1070         if (data == NULL) {
1071                 ndr->print(ndr, "%s: ARRAY(%d) : NULL", name, count);
1072                 return;
1073         }
1074
1075         if (count <= 600 && (ndr->flags & LIBNDR_PRINT_ARRAY_HEX)) {
1076                 char s[1202];
1077                 for (i=0;i<count;i++) {
1078                         snprintf(&s[i*2], 3, "%02x", data[i]);
1079                 }
1080                 s[i*2] = 0;
1081                 ndr->print(ndr, "%-25s: %s", name, s);
1082                 return;
1083         }
1084
1085         ndr->print(ndr, "%s: ARRAY(%d)", name, count);
1086         ndr->depth++;
1087         for (i=0;i<count;i++) {
1088                 char *idx=NULL;
1089                 if (asprintf(&idx, "[%d]", i) != -1) {
1090                         ndr_print_uint8(ndr, idx, data[i]);
1091                         free(idx);
1092                 }
1093         }
1094         ndr->depth--;   
1095 }
1096
1097 static void ndr_print_asc(struct ndr_print *ndr, const uint8_t *buf, int len)
1098 {
1099         int i;
1100         for (i=0;i<len;i++)
1101                 ndr->print(ndr, "%c", isprint(buf[i])?buf[i]:'.');
1102 }
1103
1104 /*
1105   ndr_print version of dump_data()
1106  */
1107 static void ndr_dump_data(struct ndr_print *ndr, const uint8_t *buf, int len)
1108 {
1109         int i=0;
1110
1111         ndr->no_newline = true;
1112
1113         for (i=0;i<len;) {
1114                 if (i%16 == 0 && i<len) {
1115                         ndr->print(ndr, "[%04X] ",i);
1116                 }
1117
1118                 ndr->print(ndr, "%02X ",(int)buf[i]);
1119                 i++;
1120                 if (i%8 == 0) ndr->print(ndr,"  ");
1121                 if (i%16 == 0) {
1122                         ndr_print_asc(ndr,&buf[i-16],8); ndr->print(ndr," ");
1123                         ndr_print_asc(ndr,&buf[i-8],8); ndr->print(ndr, "\n");
1124                 }
1125         }
1126
1127         if (i%16) {
1128                 int n;
1129                 n = 16 - (i%16);
1130                 ndr->print(ndr, " ");
1131                 if (n>8) ndr->print(ndr," ");
1132                 while (n--) ndr->print(ndr,"   ");
1133                 n = MIN(8,i%16);
1134                 ndr_print_asc(ndr,&buf[i-(i%16)],n); ndr->print(ndr, " ");
1135                 n = (i%16) - n;
1136                 if (n>0) ndr_print_asc(ndr,&buf[i-n],n);
1137                 ndr->print(ndr,"\n");
1138         }
1139
1140         ndr->no_newline = false;
1141 }
1142
1143
1144 _PUBLIC_ void ndr_print_DATA_BLOB(struct ndr_print *ndr, const char *name, DATA_BLOB r)
1145 {
1146         ndr->print(ndr, "%-25s: DATA_BLOB length=%u", name, (unsigned)r.length);
1147         if (r.length) {
1148                 ndr_dump_data(ndr, r.data, r.length);
1149         }
1150 }
1151
1152
1153 /*
1154   push a DATA_BLOB onto the wire. 
1155 */
1156 _PUBLIC_ enum ndr_err_code ndr_push_DATA_BLOB(struct ndr_push *ndr, int ndr_flags, DATA_BLOB blob)
1157 {
1158         if (ndr->flags & LIBNDR_ALIGN_FLAGS) {
1159                 if (ndr->flags & LIBNDR_FLAG_ALIGN2) {
1160                         blob.length = NDR_ALIGN(ndr, 2);
1161                 } else if (ndr->flags & LIBNDR_FLAG_ALIGN4) {
1162                         blob.length = NDR_ALIGN(ndr, 4);
1163                 } else if (ndr->flags & LIBNDR_FLAG_ALIGN8) {
1164                         blob.length = NDR_ALIGN(ndr, 8);
1165                 }
1166                 NDR_PUSH_ALLOC_SIZE(ndr, blob.data, blob.length);
1167                 data_blob_clear(&blob);
1168         } else if (!(ndr->flags & LIBNDR_FLAG_REMAINING)) {
1169                 NDR_CHECK(ndr_push_uint32(ndr, NDR_SCALARS, blob.length));
1170         }
1171         NDR_CHECK(ndr_push_bytes(ndr, blob.data, blob.length));
1172         return NDR_ERR_SUCCESS;
1173 }
1174
1175 /*
1176   pull a DATA_BLOB from the wire. 
1177 */
1178 _PUBLIC_ enum ndr_err_code ndr_pull_DATA_BLOB(struct ndr_pull *ndr, int ndr_flags, DATA_BLOB *blob)
1179 {
1180         uint32_t length = 0;
1181
1182         if (ndr->flags & LIBNDR_ALIGN_FLAGS) {
1183                 if (ndr->flags & LIBNDR_FLAG_ALIGN2) {
1184                         length = NDR_ALIGN(ndr, 2);
1185                 } else if (ndr->flags & LIBNDR_FLAG_ALIGN4) {
1186                         length = NDR_ALIGN(ndr, 4);
1187                 } else if (ndr->flags & LIBNDR_FLAG_ALIGN8) {
1188                         length = NDR_ALIGN(ndr, 8);
1189                 }
1190                 if (ndr->data_size - ndr->offset < length) {
1191                         length = ndr->data_size - ndr->offset;
1192                 }
1193         } else if (ndr->flags & LIBNDR_FLAG_REMAINING) {
1194                 length = ndr->data_size - ndr->offset;
1195         } else {
1196                 NDR_CHECK(ndr_pull_uint32(ndr, NDR_SCALARS, &length));
1197         }
1198         NDR_PULL_NEED_BYTES(ndr, length);
1199         *blob = data_blob_talloc(ndr->current_mem_ctx, ndr->data+ndr->offset, length);
1200         ndr->offset += length;
1201         return NDR_ERR_SUCCESS;
1202 }
1203
1204 _PUBLIC_ uint32_t ndr_size_DATA_BLOB(int ret, const DATA_BLOB *data, int flags)
1205 {
1206         if (!data) return ret;
1207         return ret + data->length;
1208 }