1 ###################################################
2 # Samba4 parser generator for IDL structures
3 # Copyright tridge@samba.org 2000-2003
4 # Copyright tpot@samba.org 2001
5 # released under the GNU GPL
13 # the list of needed functions
27 #####################################################################
28 # parse a properties list
29 sub ParseProperties($)
32 foreach my $d (@{$props}) {
33 if (ref($d) ne "HASH") {
36 foreach my $k (keys %{$d}) {
37 pidl "[$k($d->{$k})] ";
43 ###################################
44 # find a sibling var in a structure
49 my($fn) = $e->{PARENT};
51 if ($name =~ /\*(.*)/) {
55 if ($fn->{TYPE} eq "FUNCTION") {
56 for my $e2 (@{$fn->{DATA}}) {
57 if ($e2->{NAME} eq $name) {
63 for my $e2 (@{$fn->{ELEMENTS}}) {
64 if ($e2->{NAME} eq $name) {
68 die "invalid sibling '$name'";
71 ####################################################################
72 # work out the name of a size_is() variable
73 sub find_size_var($$$)
77 my($var_prefix) = shift;
79 my($fn) = $e->{PARENT};
81 if (util::is_constant($size)) {
85 if ($size =~ /ndr->|\(/) {
91 if ($size =~ /\*(.*)/) {
96 if ($fn->{TYPE} ne "FUNCTION") {
97 return $prefix . "r->$size";
100 my $e2 = find_sibling($e, $size);
102 if (util::has_property($e2, "in") && util::has_property($e2, "out")) {
103 return $prefix . "$var_prefix$size";
105 if (util::has_property($e2, "in")) {
106 return $prefix . "r->in.$size";
108 if (util::has_property($e2, "out")) {
109 return $prefix . "r->out.$size";
112 die "invalid variable in $size for element $e->{NAME} in $fn->{NAME}\n";
116 #####################################################################
117 # work out is a parse function should be declared static or not
121 if ($fn->{TYPE} eq "TYPEDEF") {
122 if (util::has_property($fn->{DATA}, "public")) {
127 if ($fn->{TYPE} eq "FUNCTION") {
128 if (util::has_property($fn, "public")) {
136 ###################################################################
137 # setup any special flags for an element or structure
141 my $flags = util::has_property($e, "flag");
142 if (defined $flags) {
143 pidl "\t{ guint32 _flags_save_$e->{TYPE} = flags;\n";
144 pidl "\tflags |= $flags;\n";
148 ###################################################################
149 # end any special flags for an element or structure
153 my $flags = util::has_property($e, "flag");
154 if (defined $flags) {
155 pidl "\tflags = _flags_save_$e->{TYPE};\n\t}\n";
160 #####################################################################
161 # work out the correct alignment for a structure
167 for my $e (@{$s->{ELEMENTS}}) {
170 if (!util::need_wire_pointer($e)
171 && defined $structs{$e->{TYPE}}) {
172 if ($structs{$e->{TYPE}}->{DATA}->{TYPE} eq "STRUCT") {
173 $a = struct_alignment($structs{$e->{TYPE}}->{DATA});
174 } elsif ($structs{$e->{TYPE}}->{DATA}->{TYPE} eq "UNION") {
175 if (defined $structs{$e->{TYPE}}->{DATA}) {
176 $a = union_alignment($structs{$e->{TYPE}}->{DATA});
180 $a = util::type_align($e);
191 #####################################################################
192 # work out the correct alignment for a union
199 foreach my $e (@{$u->{DATA}}) {
202 if ($e->{TYPE} eq "EMPTY") {
206 if (!util::need_wire_pointer($e)
207 && defined $structs{$e->{DATA}->{TYPE}}) {
208 my $s = $structs{$e->{DATA}->{TYPE}};
209 if ($s->{DATA}->{TYPE} eq "STRUCT") {
210 $a = struct_alignment($s->{DATA});
211 } elsif ($s->{DATA}->{TYPE} eq "UNION") {
212 $a = union_alignment($s->{DATA});
215 $a = util::type_align($e->{DATA});
226 #####################################################################
227 # parse an array - push side
228 sub ParseArrayPush($$$)
231 my $var_prefix = shift;
232 my $ndr_flags = shift;
234 my $size = find_size_var($e, util::array_size($e), $var_prefix);
236 if (defined $e->{CONFORMANT_SIZE}) {
237 # the conformant size has already been pushed
238 } elsif (!util::is_inline_array($e)) {
239 # we need to emit the array size
240 pidl "\t\toffset = dissect_ndr_uint32(tvb, offset, pinfo, tree, drep, hf_array_size, NULL);\n";
243 if (my $length = util::has_property($e, "length_is")) {
244 $length = find_size_var($e, $length, $var_prefix);
245 pidl "\t\toffset = dissect_ndr_uint32(tvb, offset, pinfo, tree, drep, hf_length_is, NULL);\n";
246 pidl "\t\toffset = dissect_ndr_uint32(tvb, offset, pinfo, tree, drep, hf_length_is, NULL);\n";
250 if (util::is_scalar_type($e->{TYPE})) {
251 pidl "\t\t// ndr_push_array_$e->{TYPE}(ndr, $ndr_flags, $var_prefix$e->{NAME}, $size);\n";
253 pidl "\t\t// ndr_push_array(ndr, $ndr_flags, $var_prefix$e->{NAME}, sizeof($var_prefix$e->{NAME}\[0]), $size, (ndr_push_flags_fn_t)ndr_push_$e->{TYPE});\n";
257 #####################################################################
258 # parse an array - pull side
259 sub ParseArrayPull($$$)
262 my $var_prefix = shift;
263 my $ndr_flags = shift;
265 my $size = find_size_var($e, util::array_size($e), $var_prefix);
266 my $alloc_size = $size;
268 # if this is a conformant array then we use that size to allocate, and make sure
269 # we allocate enough to pull the elements
270 if (defined $e->{CONFORMANT_SIZE}) {
271 $alloc_size = $e->{CONFORMANT_SIZE};
273 pidl "\tif ($size > $alloc_size) {\n";
274 pidl "\t\treturn ndr_pull_error(ndr, NDR_ERR_CONFORMANT_SIZE, \"Bad conformant size %u should be %u\", $alloc_size, $size);\n";
276 } elsif (!util::is_inline_array($e)) {
277 if ($var_prefix =~ /^r->out/ && $size =~ /^\*r->in/) {
278 my $size2 = substr($size, 1);
279 pidl "if (flags & LIBNDR_FLAG_REF_ALLOC) { NDR_ALLOC(ndr, $size2); }\n";
282 # non fixed arrays encode the size just before the array
284 pidl "\t\tuint32_t _array_size;\n";
285 pidl "\t\t(ndr_pull_uint32(ndr, &_array_size);\n";
286 if ($size =~ /r->in/) {
287 pidl "\t\tif (!(flags & LIBNDR_FLAG_REF_ALLOC) && _array_size != $size) {\n";
289 pidl "\t\tif ($size != _array_size) {\n";
291 pidl "\t\t\treturn ndr_pull_error(ndr, NDR_ERR_ARRAY_SIZE, \"Bad array size %u should be %u\", _array_size, $size);\n";
293 if ($size =~ /r->in/) {
294 pidl "else { $size = _array_size; }\n";
299 if ((util::need_alloc($e) && !util::is_fixed_array($e)) ||
300 ($var_prefix eq "r->in." && util::has_property($e, "ref"))) {
301 if (!util::is_inline_array($e) || $ndr_flags eq "NDR_SCALARS") {
302 pidl "\t\tNDR_ALLOC_N(ndr, $var_prefix$e->{NAME}, MAX(1, $alloc_size));\n";
306 if (($var_prefix eq "r->out." && util::has_property($e, "ref"))) {
307 if (!util::is_inline_array($e) || $ndr_flags eq "NDR_SCALARS") {
308 pidl "\tif (flags & LIBNDR_FLAG_REF_ALLOC) {";
309 pidl "\t\tNDR_ALLOC_N(ndr, $var_prefix$e->{NAME}, MAX(1, $alloc_size));\n";
316 if (my $length = util::has_property($e, "length_is")) {
317 $length = find_size_var($e, $length, $var_prefix);
318 pidl "\t\tuint32_t _offset, _length;\n";
319 pidl "\t\tndr_pull_uint32(ndr, &_offset);\n";
320 pidl "\t\tndr_pull_uint32(ndr, &_length);\n";
321 pidl "\t\tif (_offset != 0) return ndr_pull_error(ndr, NDR_ERR_OFFSET, \"Bad array offset 0x%08x\", _offset);\n";
322 pidl "\t\tif (_length > $size || _length != $length) return ndr_pull_error(ndr, NDR_ERR_LENGTH, \"Bad array length 0x%08x > size 0x%08x\", _offset, $size);\n\n";
326 if (util::is_scalar_type($e->{TYPE})) {
327 pidl "\t\tndr_pull_array_$e->{TYPE}(ndr, $ndr_flags, $var_prefix$e->{NAME}, $size);\n";
329 pidl "\t\tndr_pull_array(ndr, $ndr_flags, (void **)$var_prefix$e->{NAME}, sizeof($var_prefix$e->{NAME}\[0]), $size, (ndr_pull_flags_fn_t)ndr_pull_$e->{TYPE});\n";
334 sub ParamPolicyHandle($)
339 $res .= "\toffset = dissect_nt_policy_hnd(tvb, offset, pinfo, tree, drep, hf_policy_handle, NULL, NULL, FALSE, FALSE);\n";
350 $res .= "\toffset = dissect_ndr_pointer_cb(tvb, offset, pinfo, tree, drep, dissect_ndr_wchar_cvstring, NDR_POINTER_UNIQUE, \"$p->{NAME}\", hf_$p->{NAME}_string, cb_wstr_postprocess, GINT_TO_POINTER(1));\n";
360 $res .= "\toffset = dissect_ndr_nt_SID(tvb, offset, pinfo, tree, drep);\n";
365 my %param_handlers = (
366 'policy_handle' => \&ParamPolicyHandle,
367 'string' => \&ParamString,
368 'dom_sid2' => \&ParamDomSID,
371 ####################################################################
372 # parse scalars in a structure element
373 sub ParseElementPushScalar($$$)
376 my($var_prefix) = shift;
377 my($ndr_flags) = shift;
378 my $cprefix = util::c_push_prefix($e);
379 my $sub_size = util::has_property($e, "subcontext");
383 if (my $value = util::has_property($e, "value")) {
384 pidl "\t$cprefix$var_prefix$e->{NAME} = $value;\n";
387 if (util::has_property($e, "relative")) {
388 pidl "\tndr_push_relative(ndr, NDR_SCALARS, $var_prefix$e->{NAME}, (ndr_push_const_fn_t) ndr_push_$e->{TYPE});\n";
389 } elsif (util::is_inline_array($e)) {
390 ParseArrayPush($e, "r->", "NDR_SCALARS");
391 } elsif (util::need_wire_pointer($e)) {
392 pidl "\toffset = dissect_ndr_uint32(tvb, offset, pinfo, tree, drep, hf_ptr, &ptr);\n";
393 } elsif (util::need_alloc($e)) {
394 # no scalar component
395 } elsif (my $switch = util::has_property($e, "switch_is")) {
396 ParseElementPushSwitch($e, $var_prefix, $ndr_flags, $switch);
397 } elsif (defined $sub_size) {
398 if (util::is_builtin_type($e->{TYPE})) {
399 pidl "\tndr_push_subcontext_fn(ndr, $sub_size, $cprefix$var_prefix$e->{NAME}, (ndr_push_fn_t) ndr_push_$e->{TYPE});\n";
401 pidl "\tndr_push_subcontext_flags_fn(ndr, $sub_size, $cprefix$var_prefix$e->{NAME}, (ndr_push_flags_fn_t) ndr_push_$e->{TYPE});\n";
403 } elsif (util::is_builtin_type($e->{TYPE})) {
404 pidl "\toffset = dissect_ndr_$e->{TYPE}(tvb, offset, pinfo, tree, drep, hf_$e->{NAME}_$e->{TYPE}, NULL);\n";
406 if (defined($param_handlers{$e->{TYPE}})) {
407 pidl &{$param_handlers{$e->{TYPE}}}($e);
409 pidl "\tproto_tree_add_text(tree, tvb, offset, -1, \"Unhandled IDL type '$e->{TYPE}'\");\n";
416 #####################################################################
417 # print scalars in a structure element
418 sub ParseElementPrintScalar($$)
421 my($var_prefix) = shift;
422 my $cprefix = util::c_push_prefix($e);
424 if (util::has_property($e, "noprint")) {
428 if (my $value = util::has_property($e, "value")) {
429 pidl "\tif (flags & LIBNDR_PRINT_SET_VALUES) {\n";
430 pidl "\t\t$cprefix$var_prefix$e->{NAME} = $value;\n";
434 if (util::is_fixed_array($e)) {
435 ParseElementPrintBuffer($e, $var_prefix);
436 } elsif (util::has_direct_buffers($e)) {
437 pidl "\tndr_print_ptr(ndr, \"$e->{NAME}\", $var_prefix$e->{NAME});\n";
438 pidl "\tndr->depth++;\n";
439 ParseElementPrintBuffer($e, $var_prefix);
440 pidl "\tndr->depth--;\n";
441 } elsif (my $switch = util::has_property($e, "switch_is")) {
442 ParseElementPrintSwitch($e, $var_prefix, $switch);
444 pidl "\tndr_print_$e->{TYPE}(ndr, \"$e->{NAME}\", $cprefix$var_prefix$e->{NAME});\n";
448 #####################################################################
449 # parse scalars in a structure element - pull size
450 sub ParseElementPullSwitch($$$$)
453 my($var_prefix) = shift;
454 my($ndr_flags) = shift;
456 my $switch_var = find_size_var($e, $switch, $var_prefix);
458 my $cprefix = util::c_pull_prefix($e);
460 my $utype = $structs{$e->{TYPE}};
461 if (!defined $utype ||
462 !util::has_property($utype->{DATA}, "nodiscriminant")) {
463 my $e2 = find_sibling($e, $switch);
464 pidl "\tif (($ndr_flags) & NDR_SCALARS) {\n";
465 pidl "\t\t $e2->{TYPE} _level;\n";
466 pidl "\t\tndr_pull_$e2->{TYPE}(ndr, &_level);\n";
467 if ($switch_var =~ /r->in/) {
468 pidl "\t\tif (!(flags & LIBNDR_FLAG_REF_ALLOC) && _level != $switch_var) {\n";
470 pidl "\t\tif (_level != $switch_var) {\n";
472 pidl "\t\t\treturn ndr_pull_error(ndr, NDR_ERR_BAD_SWITCH, \"Bad switch value %u in $e->{NAME}\");\t\t}\n";
473 if ($switch_var =~ /r->/) {
474 pidl "else { $switch_var = _level; }\n";
479 my $sub_size = util::has_property($e, "subcontext");
480 if (defined $sub_size) {
481 pidl "\tndr_pull_subcontext_union_fn(ndr, $sub_size, $switch_var, $cprefix$var_prefix$e->{NAME}, (ndr_pull_union_fn_t) ndr_pull_$e->{TYPE});\n";
483 pidl "\tndr_pull_$e->{TYPE}(ndr, $ndr_flags, $switch_var, $cprefix$var_prefix$e->{NAME});\n";
489 #####################################################################
490 # push switch element
491 sub ParseElementPushSwitch($$$$)
494 my($var_prefix) = shift;
495 my($ndr_flags) = shift;
497 my $switch_var = find_size_var($e, $switch, $var_prefix);
498 my $cprefix = util::c_push_prefix($e);
500 my $utype = $structs{$e->{TYPE}};
501 if (!defined $utype ||
502 !util::has_property($utype->{DATA}, "nodiscriminant")) {
503 my $e2 = find_sibling($e, $switch);
504 pidl "\tif (($ndr_flags) & NDR_SCALARS) {\n";
505 pidl "\t\toffset = dissect_ndr_$e2->{TYPE}(tvb, offset, pinfo, tree, drep, hf_switch, NULL);\n";
509 my $sub_size = util::has_property($e, "subcontext");
510 if (defined $sub_size) {
511 pidl "\tndr_push_subcontext_union_fn(ndr, $sub_size, $switch_var, $cprefix$var_prefix$e->{NAME}, (ndr_push_union_fn_t) ndr_push_$e->{TYPE});\n";
513 if (defined($param_handlers{$e->{TYPE}})) {
514 pidl &{$param_handlers{$e->{TYPE}}}($e);
516 pidl "\tproto_tree_add_text(tree, tvb, offset, -1, \"Unhandled IDL type '$e->{TYPE}'\");\n";
518 # pidl "\tndr_push_$e->{TYPE}(ndr, $ndr_flags, $switch_var, $cprefix$var_prefix$e->{NAME});\n";
522 #####################################################################
523 # print scalars in a structure element
524 sub ParseElementPrintSwitch($$$)
527 my($var_prefix) = shift;
529 my $switch_var = find_size_var($e, $switch, $var_prefix);
530 my $cprefix = util::c_push_prefix($e);
532 pidl "\tndr_print_$e->{TYPE}(ndr, \"$e->{NAME}\", $switch_var, $cprefix$var_prefix$e->{NAME});\n";
536 #####################################################################
537 # parse scalars in a structure element - pull size
538 sub ParseElementPullScalar($$$)
541 my($var_prefix) = shift;
542 my($ndr_flags) = shift;
543 my $cprefix = util::c_pull_prefix($e);
544 my $sub_size = util::has_property($e, "subcontext");
548 if (util::has_property($e, "relative")) {
549 pidl "\tndr_pull_relative(ndr, (const void **)&$var_prefix$e->{NAME}, sizeof(*$var_prefix$e->{NAME}), (ndr_pull_flags_fn_t)ndr_pull_$e->{TYPE});\n";
550 } elsif (util::is_inline_array($e)) {
551 ParseArrayPull($e, "r->", "NDR_SCALARS");
552 } elsif (util::need_wire_pointer($e)) {
553 pidl "\tndr_pull_uint32(ndr, &_ptr_$e->{NAME});\n";
554 pidl "\tif (_ptr_$e->{NAME}) {\n";
555 pidl "\t\tNDR_ALLOC(ndr, $var_prefix$e->{NAME});\n";
557 pidl "\t\t$var_prefix$e->{NAME} = NULL;\n";
559 } elsif (util::need_alloc($e)) {
560 # no scalar component
561 } elsif (my $switch = util::has_property($e, "switch_is")) {
562 ParseElementPullSwitch($e, $var_prefix, $ndr_flags, $switch);
563 } elsif (defined $sub_size) {
564 if (util::is_builtin_type($e->{TYPE})) {
565 pidl "\tndr_pull_subcontext_fn(ndr, $sub_size, $cprefix$var_prefix$e->{NAME}, (ndr_pull_fn_t) ndr_pull_$e->{TYPE});\n";
567 pidl "\tndr_pull_subcontext_flags_fn(ndr, $sub_size, $cprefix$var_prefix$e->{NAME}, (ndr_pull_flags_fn_t) ndr_pull_$e->{TYPE});\n";
569 } elsif (util::is_builtin_type($e->{TYPE})) {
570 pidl "\tndr_pull_$e->{TYPE}(ndr, $cprefix$var_prefix$e->{NAME});\n";
572 pidl "\tndr_pull_$e->{TYPE}(ndr, $ndr_flags, $cprefix$var_prefix$e->{NAME});\n";
578 #####################################################################
579 # parse buffers in a structure element
580 sub ParseElementPushBuffer($$$)
583 my($var_prefix) = shift;
584 my($ndr_flags) = shift;
585 my $cprefix = util::c_push_prefix($e);
586 my $sub_size = util::has_property($e, "subcontext");
588 if (util::is_pure_scalar($e)) {
594 if (util::need_wire_pointer($e)) {
595 pidl "\tif (ptr) {\n";
598 if (util::has_property($e, "relative")) {
599 pidl "\tndr_push_relative(ndr, NDR_BUFFERS, $cprefix$var_prefix$e->{NAME}, (ndr_push_const_fn_t) ndr_push_$e->{TYPE});\n";
600 } elsif (util::is_inline_array($e)) {
601 ParseArrayPush($e, "r->", "NDR_BUFFERS");
602 } elsif (util::array_size($e)) {
603 ParseArrayPush($e, "r->", "NDR_SCALARS|NDR_BUFFERS");
604 } elsif (my $switch = util::has_property($e, "switch_is")) {
605 if ($e->{POINTERS}) {
606 ParseElementPushSwitch($e, $var_prefix, "NDR_BUFFERS|NDR_SCALARS", $switch);
608 ParseElementPushSwitch($e, $var_prefix, "NDR_BUFFERS", $switch);
610 } elsif (defined $sub_size) {
611 if ($e->{POINTERS}) {
612 if (util::is_builtin_type($e->{TYPE})) {
613 pidl "\tndr_push_subcontext_fn(ndr, $sub_size, $cprefix$var_prefix$e->{NAME}, (ndr_push_fn_t) ndr_push_$e->{TYPE});\n";
615 pidl "\tndr_push_subcontext_flags_fn(ndr, $sub_size, $cprefix$var_prefix$e->{NAME}, (ndr_push_flags_fn_t) ndr_push_$e->{TYPE});\n";
618 } elsif (util::is_builtin_type($e->{TYPE})) {
619 pidl "\toffset = dissect_ndr_$e->{TYPE}(tvb, offset, pinfo, tree, drep, hf_$e->{NAME}_$e->{TYPE}, NULL);\n";
620 } elsif ($e->{POINTERS}) {
621 if (defined($param_handlers{$e->{TYPE}})) {
622 pidl &{$param_handlers{$e->{TYPE}}}($e);
624 pidl "\t\toffset = dissect_$e->{TYPE}(tvb, offset, pinfo, tree, drep, NDR_SCALARS|NDR_BUFFERS);\n";
627 if (defined($param_handlers{$e->{TYPE}})) {
628 pidl &{$param_handlers{$e->{TYPE}}}($e);
630 pidl "\t\toffset = dissect__$e->{TYPE}(tvb, offset, pinfo, tree, drep, $ndr_flags);\n";
634 if (util::need_wire_pointer($e)) {
641 #####################################################################
642 # print buffers in a structure element
643 sub ParseElementPrintBuffer($$)
646 my($var_prefix) = shift;
647 my $cprefix = util::c_push_prefix($e);
649 if (util::need_wire_pointer($e)) {
650 pidl "\tif ($var_prefix$e->{NAME}) {\n";
653 if (util::array_size($e)) {
654 ParseArrayPrint($e, $var_prefix);
655 } elsif (my $switch = util::has_property($e, "switch_is")) {
656 ParseElementPrintSwitch($e, $var_prefix, $switch);
658 pidl "\t\tndr_print_$e->{TYPE}(ndr, \"$e->{NAME}\", $cprefix$var_prefix$e->{NAME});\n";
661 if (util::need_wire_pointer($e)) {
667 #####################################################################
668 # parse buffers in a structure element - pull side
669 sub ParseElementPullBuffer($$$)
672 my($var_prefix) = shift;
673 my($ndr_flags) = shift;
674 my $cprefix = util::c_pull_prefix($e);
675 my $sub_size = util::has_property($e, "subcontext");
677 if (util::is_pure_scalar($e)) {
681 if (util::has_property($e, "relative")) {
687 if (util::need_wire_pointer($e)) {
688 pidl "\tif ($var_prefix$e->{NAME}) {\n";
691 if (util::is_inline_array($e)) {
692 ParseArrayPull($e, "r->", "NDR_BUFFERS");
693 } elsif (util::array_size($e)) {
694 ParseArrayPull($e, "r->", "NDR_SCALARS|NDR_BUFFERS");
695 } elsif (my $switch = util::has_property($e, "switch_is")) {
696 if ($e->{POINTERS}) {
697 ParseElementPullSwitch($e, $var_prefix, "NDR_SCALARS|NDR_BUFFERS", $switch);
699 ParseElementPullSwitch($e, $var_prefix, "NDR_BUFFERS", $switch);
701 } elsif (defined $sub_size) {
702 if ($e->{POINTERS}) {
703 if (util::is_builtin_type($e->{TYPE})) {
704 pidl "\tndr_pull_subcontext_fn(ndr, $sub_size, $cprefix$var_prefix$e->{NAME}, (ndr_pull_fn_t) ndr_pull_$e->{TYPE});\n";
706 pidl "\tndr_pull_subcontext_flags_fn(ndr, $sub_size, $cprefix$var_prefix$e->{NAME}, (ndr_pull_flags_fn_t) ndr_pull_$e->{TYPE});\n";
709 } elsif (util::is_builtin_type($e->{TYPE})) {
710 pidl "\t\tndr_pull_$e->{TYPE}(ndr, $cprefix$var_prefix$e->{NAME});\n";
711 } elsif ($e->{POINTERS}) {
712 pidl "\t\tndr_pull_$e->{TYPE}(ndr, NDR_SCALARS|NDR_BUFFERS, $cprefix$var_prefix$e->{NAME});\n";
714 pidl "\t\tndr_pull_$e->{TYPE}(ndr, $ndr_flags, $cprefix$var_prefix$e->{NAME});\n";
717 if (util::need_wire_pointer($e)) {
724 #####################################################################
726 sub ParseStructPush($)
731 if (! defined $struct->{ELEMENTS}) {
735 start_flags($struct);
737 # see if the structure contains a conformant array. If it
738 # does, then it must be the last element of the structure, and
739 # we need to push the conformant length early, as it fits on
740 # the wire before the structure (and even before the structure
742 my $e = $struct->{ELEMENTS}[-1];
743 if (defined $e->{ARRAY_LEN} && $e->{ARRAY_LEN} eq "*") {
744 my $size = find_size_var($e, util::array_size($e), "r->");
745 $e->{CONFORMANT_SIZE} = $size;
747 pidl "\tndr_push_uint32(ndr, $size);\n";
750 pidl "\tif (!(ndr_flags & NDR_SCALARS)) goto buffers;\n";
752 pidl "\tndr_push_struct_start(ndr);\n";
754 my $align = struct_alignment($struct);
755 pidl "\tndr_push_align(ndr, $align);\n";
757 foreach my $e (@{$struct->{ELEMENTS}}) {
758 ParseElementPushScalar($e, "r->", "NDR_SCALARS");
762 pidl "\tif (!(ndr_flags & NDR_BUFFERS)) goto done;\n";
763 foreach my $e (@{$struct->{ELEMENTS}}) {
764 ParseElementPushBuffer($e, "r->", "NDR_BUFFERS");
767 pidl "\tndr_push_struct_end(ndr);\n";
774 #####################################################################
775 # parse a struct - pull side
776 sub ParseStructPull($)
781 if (! defined $struct->{ELEMENTS}) {
785 # see if the structure contains a conformant array. If it
786 # does, then it must be the last element of the structure, and
787 # we need to pull the conformant length early, as it fits on
788 # the wire before the structure (and even before the structure
790 my $e = $struct->{ELEMENTS}[-1];
791 if (defined $e->{ARRAY_LEN} && $e->{ARRAY_LEN} eq "*") {
793 pidl "\tuint32_t _conformant_size;\n";
794 $conform_e->{CONFORMANT_SIZE} = "_conformant_size";
797 # declare any internal pointers we need
798 foreach my $e (@{$struct->{ELEMENTS}}) {
799 if (util::need_wire_pointer($e) &&
800 !util::has_property($e, "relative")) {
801 pidl "\tuint32_t _ptr_$e->{NAME};\n";
805 start_flags($struct);
807 pidl "\tif (!(ndr_flags & NDR_SCALARS)) goto buffers;\n";
809 pidl "\tndr_pull_struct_start(ndr);\n";
811 if (defined $conform_e) {
812 pidl "\tndr_pull_uint32(ndr, &$conform_e->{CONFORMANT_SIZE});\n";
815 my $align = struct_alignment($struct);
816 pidl "\tndr_pull_align(ndr, $align);\n";
818 foreach my $e (@{$struct->{ELEMENTS}}) {
819 ParseElementPullScalar($e, "r->", "NDR_SCALARS");
823 pidl "\tif (!(ndr_flags & NDR_BUFFERS)) goto done;\n";
824 foreach my $e (@{$struct->{ELEMENTS}}) {
825 ParseElementPullBuffer($e, "r->", "NDR_BUFFERS");
828 pidl "\tndr_pull_struct_end(ndr);\n";
836 #####################################################################
837 # parse a union - push side
838 sub ParseUnionPush($)
841 my $have_default = 0;
845 pidl "\tif (!(ndr_flags & NDR_SCALARS)) goto buffers;\n";
847 pidl "\tndr_push_struct_start(ndr);\n";
849 # my $align = union_alignment($e);
850 # pidl "\tndr_push_align(ndr, $align);\n";
852 pidl "\tswitch (level) {\n";
853 foreach my $el (@{$e->{DATA}}) {
854 if ($el->{CASE} eq "default") {
858 pidl "\tcase $el->{CASE}:\n";
860 if ($el->{TYPE} eq "UNION_ELEMENT") {
861 ParseElementPushScalar($el->{DATA}, "r->", "NDR_SCALARS");
865 if (! $have_default) {
867 pidl "\t\treturn ndr_push_error(ndr, NDR_ERR_BAD_SWITCH, \"Bad switch value \%u\", level);\n";
871 pidl "\tif (!(ndr_flags & NDR_BUFFERS)) goto done;\n";
872 pidl "\tswitch (level) {\n";
873 foreach my $el (@{$e->{DATA}}) {
874 if ($el->{CASE} eq "default") {
877 pidl "\tcase $el->{CASE}:\n";
879 if ($el->{TYPE} eq "UNION_ELEMENT") {
880 ParseElementPushBuffer($el->{DATA}, "r->", "NDR_BUFFERS");
884 if (! $have_default) {
886 pidl "\t\treturn ndr_push_error(ndr, NDR_ERR_BAD_SWITCH, \"Bad switch value \%u\", level);\n";
889 pidl "\tndr_push_struct_end(ndr);\n";
894 #####################################################################
895 # parse a union - pull side
896 sub ParseUnionPull($)
899 my $have_default = 0;
903 pidl "\tif (!(ndr_flags & NDR_SCALARS)) goto buffers;\n";
905 pidl "\tndr_pull_struct_start(ndr);\n";
907 # my $align = union_alignment($e);
908 # pidl "\tndr_pull_align(ndr, $align);\n";
910 pidl "\tswitch (level) {\n";
911 foreach my $el (@{$e->{DATA}}) {
912 if ($el->{CASE} eq "default") {
913 pidl "\tdefault: {\n";
916 pidl "\tcase $el->{CASE}: {\n";
918 if ($el->{TYPE} eq "UNION_ELEMENT") {
919 my $e2 = $el->{DATA};
920 if ($e2->{POINTERS}) {
921 pidl "\t\tuint32_t _ptr_$e2->{NAME};\n";
923 ParseElementPullScalar($el->{DATA}, "r->", "NDR_SCALARS");
925 pidl "\tbreak; }\n\n";
927 if (! $have_default) {
929 pidl "\t\treturn ndr_pull_error(ndr, NDR_ERR_BAD_SWITCH, \"Bad switch value \%u\", level);\n";
933 pidl "\tif (!(ndr_flags & NDR_BUFFERS)) goto done;\n";
934 pidl "\tswitch (level) {\n";
935 foreach my $el (@{$e->{DATA}}) {
936 if ($el->{CASE} eq "default") {
939 pidl "\tcase $el->{CASE}:\n";
941 if ($el->{TYPE} eq "UNION_ELEMENT") {
942 ParseElementPullBuffer($el->{DATA}, "r->", "NDR_BUFFERS");
946 if (! $have_default) {
948 pidl "\t\treturn ndr_pull_error(ndr, NDR_ERR_BAD_SWITCH, \"Bad switch value \%u\", level);\n";
951 pidl "\tndr_pull_struct_end(ndr);\n";
956 #####################################################################
962 if (ref($data) eq "HASH") {
963 ($data->{TYPE} eq "STRUCT") &&
964 ParseStructPush($data);
965 ($data->{TYPE} eq "UNION") &&
966 ParseUnionPush($data);
970 #####################################################################
976 if (ref($data) eq "HASH") {
977 ($data->{TYPE} eq "STRUCT") &&
978 ParseStructPull($data);
979 ($data->{TYPE} eq "UNION") &&
980 ParseUnionPull($data);
984 #####################################################################
986 sub ParseTypedefEthereal($)
989 my $static = fn_prefix($e);
991 if ($e->{DATA}->{TYPE} eq "STRUCT") {
992 pidl $static . "int dissect_$e->{NAME}(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree, guint8 *drep, int flags)\n";
994 # ParseTypePush($e->{DATA});
995 pidl "\treturn offset;\n";
999 if ($e->{DATA}->{TYPE} eq "UNION") {
1000 pidl $static . "int dissect_$e->{NAME}(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree, guint8 *drep, int flags)\n";
1002 # ParseTypePush($e->{DATA});
1003 pidl "\treturn offset;\n";
1009 #####################################################################
1010 # parse a function element
1011 sub ParseFunctionElementPush($$)
1016 if (util::array_size($e)) {
1017 if (util::need_wire_pointer($e)) {
1018 pidl "\toffset = dissect_ndr_uint32(tvb, offset, pinfo, tree, drep, hf_ptr, &ptr);\n";
1019 pidl "\tif (ptr) {\n";
1020 ParseArrayPush($e, "r->$inout.", "NDR_SCALARS|NDR_BUFFERS");
1023 ParseArrayPush($e, "r->$inout.", "NDR_SCALARS|NDR_BUFFERS");
1026 ParseElementPushScalar($e, "r->$inout.", "NDR_SCALARS|NDR_BUFFERS");
1027 if ($e->{POINTERS}) {
1028 ParseElementPushBuffer($e, "r->$inout.", "NDR_SCALARS|NDR_BUFFERS");
1033 #####################################################################
1035 sub ParseFunctionEthereal($)
1038 my $static = fn_prefix($fn);
1040 # Comment displaying IDL for this function
1043 pidl IdlDump::DumpFunction($fn);
1048 pidl $static . "int $fn->{NAME}_rqst(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree, guint8 *drep)\n";
1050 pidl "\tint flags = NDR_SCALARS|NDR_BUFFERS;\n\n";
1051 pidl "\tguint32 ptr;\n\n";
1053 foreach my $e (@{$fn->{DATA}}) {
1054 if (util::has_property($e, "in")) {
1055 ParseFunctionElementPush($e, "in");
1059 pidl "\n\treturn offset;\n";
1064 pidl $static . "int $fn->{NAME}_resp(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree, guint8 *drep)\n";
1066 pidl "\tint flags = NDR_SCALARS|NDR_BUFFERS;\n\n";
1067 pidl "\tguint32 ptr;\n\n";
1069 foreach my $e (@{$fn->{DATA}}) {
1070 if (util::has_property($e, "out")) {
1071 ParseFunctionElementPush($e, "out");
1075 if ($fn->{RETURN_TYPE} && $fn->{RETURN_TYPE} ne "void") {
1076 if ($fn->{RETURN_TYPE} eq "NTSTATUS") {
1077 pidl "\n\toffset = dissect_ntstatus(tvb, offset, pinfo, tree, drep, hf_rc, NULL);\n";
1079 pidl "\tproto_tree_add_text(tree, tvb, offset, -1, \"Unhandled return type '$fn->{RETURN_TYPE}'\");\n";
1083 pidl "\n\treturn offset;\n";
1087 #####################################################################
1088 # produce a function call table
1089 sub FunctionTable($)
1091 my($interface) = shift;
1092 my($data) = $interface->{DATA};
1094 my $uname = uc $interface->{NAME};
1096 foreach my $d (@{$data}) {
1097 if ($d->{TYPE} eq "FUNCTION") { $count++; }
1104 pidl "static dcerpc_sub_dissector dcerpc_dissectors[] = {\n";
1106 foreach my $d (@{$data}) {
1107 if ($d->{TYPE} eq "FUNCTION") {
1108 # Strip module name from function name, if present
1109 my($n) = $d->{NAME};
1110 $n = substr($d->{NAME}, length($module) + 1),
1111 if $module eq substr($d->{NAME}, 0, length($module));
1112 pidl "\t{ $num, \"$n\",\n";
1113 pidl "\t\t$d->{NAME}_rqst,\n";
1114 pidl "\t\t$d->{NAME}_resp },\n";
1122 #####################################################################
1123 # parse the interface definitions
1124 sub ParseInterface($)
1126 my($interface) = shift;
1127 my($data) = $interface->{DATA};
1129 foreach my $d (@{$data}) {
1130 if ($d->{TYPE} eq "TYPEDEF") {
1131 $structs{$d->{NAME}} = $d;
1135 foreach my $d (@{$data}) {
1136 ($d->{TYPE} eq "TYPEDEF") &&
1137 ParseTypedefEthereal($d);
1138 ($d->{TYPE} eq "FUNCTION") &&
1139 ParseFunctionEthereal($d);
1142 FunctionTable($interface);
1145 # Convert an idl type to an ethereal FT_* type
1151 return "FT_UINT32", if ($t eq "uint32");
1152 return "FT_UINT16", if ($t eq "uint16");
1156 # Select an ethereal BASE_* type for an idl type
1162 return "BASE_DEC", if ($t eq "uint32") or ($t eq "uint16");
1166 sub NeededFunction($)
1169 $needed{"pull_$fn->{NAME}"} = 1;
1170 $needed{"push_$fn->{NAME}"} = 1;
1171 foreach my $e (@{$fn->{DATA}}) {
1172 $needed{"hf_$e->{NAME}_$e->{TYPE}"} = {
1173 'name' => $e->{NAME},
1174 'type' => $e->{TYPE},
1175 'ft' => type2ft($e->{TYPE}),
1176 'base' => type2base($e->{TYPE})
1179 $needed{"pull_$e->{TYPE}"} = 1;
1180 $needed{"push_$e->{TYPE}"} = 1;
1184 sub NeededTypedef($)
1187 if (util::has_property($t->{DATA}, "public")) {
1188 $needed{"pull_$t->{NAME}"} = 1;
1189 $needed{"push_$t->{NAME}"} = 1;
1191 if ($t->{DATA}->{TYPE} eq "STRUCT") {
1192 for my $e (@{$t->{DATA}->{ELEMENTS}}) {
1193 $e->{PARENT} = $t->{DATA};
1194 if ($needed{"pull_$t->{NAME}"}) {
1195 $needed{"pull_$e->{TYPE}"} = 1;
1197 if ($needed{"push_$t->{NAME}"}) {
1198 $needed{"push_$e->{TYPE}"} = 1;
1202 if ($t->{DATA}->{TYPE} eq "UNION") {
1203 for my $e (@{$t->{DATA}->{DATA}}) {
1204 $e->{PARENT} = $t->{DATA};
1205 if ($e->{TYPE} eq "UNION_ELEMENT") {
1206 if ($needed{"pull_$t->{NAME}"}) {
1207 $needed{"pull_$e->{DATA}->{TYPE}"} = 1;
1209 if ($needed{"push_$t->{NAME}"}) {
1210 $needed{"push_$e->{DATA}->{TYPE}"} = 1;
1217 #####################################################################
1218 # work out what parse functions are needed
1221 my($interface) = shift;
1222 my($data) = $interface->{DATA};
1223 foreach my $d (@{$data}) {
1224 ($d->{TYPE} eq "FUNCTION") &&
1227 foreach my $d (reverse @{$data}) {
1228 ($d->{TYPE} eq "TYPEDEF") &&
1233 #####################################################################
1234 # parse the interface definitions
1239 $if_uuid = $h->{PROPERTIES}->{uuid};
1240 $if_version = $h->{PROPERTIES}->{version};
1241 $if_endpoints = $h->{PROPERTIES}->{endpoints};
1244 #####################################################################
1245 # parse a parsed IDL structure back into an IDL file
1249 my($filename) = shift;
1251 open(OUT, ">$filename") || die "can't open $filename";
1253 pidl "/* parser auto-generated by pidl */\n\n";
1254 pidl "#ifdef HAVE_CONFIG_H\n";
1255 pidl "#include \"config.h\"\n";
1258 pidl "#include \"packet-dcerpc.h\"\n";
1259 pidl "#include \"packet-dcerpc-nt.h\"\n\n";
1260 pidl "#include \"packet-dcerpc-common.h\"\n\n";
1262 pidl "#define NDR_SCALARS 1\n";
1263 pidl "#define NDR_BUFFERS 2\n\n";
1265 pidl "extern const value_string NT_errors[];\n\n";
1267 foreach my $x (@{$idl}) {
1268 $module = $x->{NAME}, if $x->{TYPE} eq "INTERFACE";
1271 pidl "static int proto_dcerpc_$module = -1;\n\n";
1273 pidl "static gint ett_dcerpc_$module = -1;\n\n";
1275 pidl "static int hf_opnum = -1;\n";
1276 pidl "static int hf_rc = -1;\n";
1277 pidl "static int hf_ptr = -1;\n";
1278 pidl "static int hf_switch = -1;\n";
1279 pidl "static int hf_policy_handle = -1;\n";
1280 pidl "static int hf_array_size = -1;\n";
1281 pidl "static int hf_length_is = -1;\n";
1283 foreach my $x (@{$idl}) {
1284 ($x->{TYPE} eq "MODULEHEADER") &&
1287 if ($x->{TYPE} eq "INTERFACE") {
1290 foreach my $y (keys(%needed)) {
1291 pidl "static int $y = -1;\n", if $y =~ /^hf_/;
1298 pidl "static e_uuid_t uuid_dcerpc_$module = {\n";
1299 pidl "\t0x" . substr($if_uuid, 0, 8);
1300 pidl ", 0x" . substr($if_uuid, 9, 4);
1301 pidl ", 0x" . substr($if_uuid, 14, 4) . ",\n";
1302 pidl "\t{ 0x" . substr($if_uuid, 19, 2);
1303 pidl ", 0x" . substr($if_uuid, 21, 2);
1304 pidl ", 0x" . substr($if_uuid, 24, 2);
1305 pidl ", 0x" . substr($if_uuid, 26, 2);
1306 pidl ", 0x" . substr($if_uuid, 28, 2);
1307 pidl ", 0x" . substr($if_uuid, 30, 2);
1308 pidl ", 0x" . substr($if_uuid, 32, 2);
1309 pidl ", 0x" . substr($if_uuid, 34, 2) . " }\n";
1312 pidl "static guint16 ver_dcerpc_$module = " . $if_version . ";\n\n";
1315 pidl "void proto_register_dcerpc_samr(void)\n";
1317 pidl "\tstatic hf_register_info hf[] = {\n";
1319 pidl "\t{ &hf_opnum, { \"Operation\", \"$module.opnum\", FT_UINT16, BASE_DEC, NULL, 0x0, \"Operation\", HFILL }},\n";
1320 pidl "\t{ &hf_policy_handle, { \"Policy handle\", \"$module.policy\", FT_BYTES, BASE_NONE, NULL, 0x0, \"Policy handle\", HFILL }},\n";
1321 pidl "\t{ &hf_rc, { \"Return code\", \"$module.rc\", FT_UINT32, BASE_HEX, VALS(NT_errors), 0x0, \"Return status code\", HFILL }},\n";
1322 pidl "\t{ &hf_switch, { \"Switch\", \"$module.switch\", FT_UINT16, BASE_DEC, NULL, 0x0, \"Switch\", HFILL }},\n";
1323 pidl "\t{ &hf_array_size, { \"Array size\", \"$module.array_size\", FT_UINT32, BASE_DEC, NULL, 0x0, \"Array size\", HFILL }},\n";
1324 pidl "\t{ &hf_length_is, { \"Length is\", \"$module.length_is\", FT_UINT32, BASE_DEC, NULL, 0x0, \"Length is\", HFILL }},\n";
1325 pidl "\t{ &hf_ptr, { \"Pointer\", \"$module.ptr\", FT_UINT32, BASE_HEX, NULL, 0x0, \"Pointer\", HFILL }},\n";
1327 foreach my $x (keys(%needed)) {
1328 next, if !($x =~ /^hf_/);
1331 pidl "\t { \"$needed{$x}{name}\", \"$x\", $needed{$x}{ft}, $needed{$x}{base},\n";
1332 pidl"\t NULL, 0, \"$x\", HFILL }},\n";
1337 pidl "\tstatic gint *ett[] = {\n";
1338 pidl "\t\t&ett_dcerpc_$module,\n";
1341 pidl "\tproto_dcerpc_$module = proto_register_protocol(\"$module\", \"$module\", \"$module\");\n\n";
1343 pidl "\tproto_register_field_array(proto_dcerpc_$module, hf, array_length (hf));\n";
1344 pidl "\tproto_register_subtree_array(ett, array_length(ett));\n";
1348 pidl "void proto_reg_handoff_dcerpc_$module(void)\n";
1350 pidl "\tdcerpc_init_uuid(proto_dcerpc_$module, ett_dcerpc_$module, \n";
1351 pidl "\t\t&uuid_dcerpc_$module, ver_dcerpc_$module, \n";
1352 pidl "\t\tdcerpc_dissectors, hf_opnum);\n";