r8940: Add TDR (Trivial Data Representation). The aim is to use this later for
authorJelmer Vernooij <jelmer@samba.org>
Tue, 2 Aug 2005 20:12:31 +0000 (20:12 +0000)
committerGerald (Jerry) Carter <jerry@samba.org>
Wed, 10 Oct 2007 18:30:59 +0000 (13:30 -0500)
NBT/WINS/etc rather then having to depend on NDR.
(This used to be commit 5ee7af26dd220de06f1764cd1683abedeeda5131)

source4/build/pidl/Parse/Pidl/Samba/TDR.pm [new file with mode: 0644]
source4/build/pidl/pidl
source4/include/includes.h
source4/lib/basic.mk
source4/lib/tdr/tdr.c [new file with mode: 0644]
source4/lib/tdr/tdr.h [new file with mode: 0644]

diff --git a/source4/build/pidl/Parse/Pidl/Samba/TDR.pm b/source4/build/pidl/Parse/Pidl/Samba/TDR.pm
new file mode 100644 (file)
index 0000000..fb9dd0d
--- /dev/null
@@ -0,0 +1,252 @@
+###################################################
+# Trivial Parser Generator
+# Copyright jelmer@samba.org 2005
+# released under the GNU GPL
+
+package Parse::Pidl::Samba::TDR;
+use Parse::Pidl::Util qw(has_property ParseExpr is_constant);
+use Data::Dumper;
+
+use strict;
+
+my $ret = "";
+my $tabs = "";
+
+sub indent() { $tabs.="\t"; }
+sub deindent() { $tabs = substr($tabs, 1); }
+sub pidl($) { $ret .= $tabs.(shift)."\n"; }
+sub fatal($$) { my ($e,$s) = @_; die("$e->{FILE}:$e->{LINE}: $s\n"); }
+sub static($) { my $p = shift; return("static ") unless ($p); return ""; }
+sub printarg($) { 
+       my $t = shift; 
+       return(", const char *name") if ($t eq "print");
+       return("");
+}
+
+sub ContainsArray($)
+{
+       my $e = shift;
+       foreach (@{$e->{ELEMENTS}}) {
+               next if (has_property($_, "charset") and
+                       scalar(@{$_->{ARRAY_LEN}}) == 1);
+               return 1 if (defined($_->{ARRAY_LEN}) and 
+                               scalar(@{$_->{ARRAY_LEN}}) > 0);
+       }
+       return 0;
+}
+
+sub ParserElement($$$)
+{
+       my ($e,$t,$env) = @_;
+       my $switch = "";
+       my $array = "";
+       my $name = "";
+
+       fatal($e,"Pointers not supported in TDR") if ($e->{POINTERS} > 0);
+       fatal($e,"size_is() not supported in TDR") if (has_property($e, "size_is"));
+       fatal($e,"length_is() not supported in TDR") if (has_property($e, "length_is"));
+
+       if ($t eq "print") {
+               $name = ", \"$e->{NAME}\"$array";
+       }
+
+       if (has_property($e, "charset")) {
+               fatal($e,"charset() on non-array element") unless (defined($e->{ARRAY_LEN}) and scalar(@{$e->{ARRAY_LEN}}) > 0);
+               
+               my $len = @{$e->{ARRAY_LEN}}[0];
+               if ($len eq "*") { $len = "-1"; }
+               pidl "TDR_CHECK(tdr_$t\_charset(tdr$name, &v->$e->{NAME}, $len, sizeof($e->{TYPE}_t), CH_$e->{PROPERTIES}->{charset}));";
+               return;
+       }
+
+       if (has_property($e, "switch_is")) {
+               $switch = ", " . ParseExpr($e->{PROPERTIES}->{switch_is}, $env);
+       }
+
+       if (defined($e->{ARRAY_LEN}) and scalar(@{$e->{ARRAY_LEN}}) > 0) {
+               my $len = ParseExpr($e->{ARRAY_LEN}[0], $env);
+
+               if ($t eq "pull" and not is_constant($len)) {
+                       pidl "TDR_ALLOC(tdr, v->$e->{NAME}, $len);"
+               }
+
+               pidl "for (i = 0; i < $len; i++) {";
+               indent;
+               $array = "[i]";
+       }
+
+       if (has_property($e, "value") && $t eq "push") {
+               pidl "v->$e->{NAME} = ".ParseExpr($e->{PROPERTIES}->{value}, $env).";";
+       }
+
+       pidl "TDR_CHECK(tdr_$t\_$e->{TYPE}(tdr$name$switch, &v->$e->{NAME}$array));";
+
+       if ($array) { deindent; pidl "}"; }
+}
+
+sub ParserStruct($$$$)
+{
+       my ($e,$n,$t,$p) = @_;
+
+       pidl static($p)."NTSTATUS tdr_$t\_$n (struct tdr_$t *tdr".printarg($t).", struct $n *v)";
+       pidl "{"; indent;
+       pidl "int i;" if (ContainsArray($e));
+
+       if ($t eq "print") {
+               pidl "tdr->print(tdr, \"\%-25s: struct $n\", name);";
+               pidl "tdr->level++;";
+       }
+
+       my %env = map { $_->{NAME} => "v->$_->{NAME}" } @{$e->{ELEMENTS}};
+       ParserElement($_, $t, \%env) foreach (@{$e->{ELEMENTS}});
+       
+       if ($t eq "print") {
+               pidl "tdr->level--;";
+       }
+
+       pidl "return NT_STATUS_OK;";
+
+       deindent; pidl "}";
+}
+
+sub ParserUnion($$$$)
+{
+       my ($e,$n,$t,$p) = @_;
+
+       pidl static($p)."NTSTATUS tdr_$t\_$n(struct tdr_$t *tdr".printarg($t).", int level, union $n *v)";
+       pidl "{"; indent;
+       pidl "int i;" if (ContainsArray($e));
+
+       if ($t eq "print") {
+               pidl "tdr->print(tdr, \"\%-25s: union $n\", name);";
+               pidl "tdr->level++;";
+       }
+       
+       pidl "switch (level) {"; indent;
+       foreach (@{$e->{ELEMENTS}}) {
+               if (has_property($_, "case")) {
+                       pidl "case " . $_->{PROPERTIES}->{case} . ":";
+               } elsif (has_property($_, "default")) {
+                       pidl "default:";
+               }
+               indent; ParserElement($_, $t, {}); deindent;
+               pidl "break;";
+       }
+       deindent; pidl "}";
+
+       if ($t eq "print") {
+               pidl "tdr->level--;";
+       }
+       
+       pidl "return NT_STATUS_OK;\n";
+       deindent; pidl "}";
+}
+
+sub ParserBitmap($$$$)
+{
+       my ($e,$n,$t,$p) = @_;
+       return if ($p);
+       pidl "#define tdr_$t\_$n tdr_$t\_" . Parse::Pidl::Typelist::bitmap_type_fn($e);
+}
+
+sub ParserEnum($$$$)
+{
+       my ($e,$n,$t,$p) = @_;
+       my $bt = Parse::Pidl::Typelist::enum_type_fn($e);
+       
+       pidl static($p)."NTSTATUS tdr_$t\_$n (struct tdr_$t *tdr".printarg($t).", enum $n *v)";
+       pidl "{";
+       if ($t eq "pull") {
+               pidl "\t$bt\_t r;";
+               pidl "\tTDR_CHECK(tdr_$t\_$bt(tdr, \&r));";
+               pidl "\t*v = r;";
+       } elsif ($t eq "push") {
+               pidl "\tTDR_CHECK(tdr_$t\_$bt(tdr, ($bt\_t *)v));";
+       } elsif ($t eq "print") {
+               pidl "\t/* FIXME */";
+       }
+       pidl "\treturn NT_STATUS_OK;";
+       pidl "}";
+}
+
+sub ParserTypedef($$)
+{
+       my ($e,$t) = @_;
+
+       return if (has_property($e, "no$t"));
+
+       { STRUCT => \&ParserStruct, UNION => \&ParserUnion, 
+               ENUM => \&ParserEnum, BITMAP => \&ParserBitmap
+       }->{$e->{DATA}->{TYPE}}($e->{DATA}, $e->{NAME}, $t, has_property($e, "public"));
+
+       pidl "";
+}
+
+sub ParserInterface($)
+{
+       my $x = shift;
+
+       foreach (@{$x->{DATA}}) {
+               next if ($_->{TYPE} ne "TYPEDEF");
+               ParserTypedef($_, "pull");
+               ParserTypedef($_, "push");
+               ParserTypedef($_, "print");
+       }
+}
+
+sub Parser($$)
+{
+       my ($idl,$hdrname) = @_;
+       $ret = "";
+       pidl "/* autogenerated by pidl */";
+       pidl "#include \"includes.h\"";
+       pidl "#include \"$hdrname\"";
+       foreach (@$idl) { ParserInterface($_) if ($_->{TYPE} eq "INTERFACE"); } 
+       return $ret;
+}
+
+sub HeaderInterface($$)
+{
+       my ($x,$outputdir) = @_;
+
+       pidl "#ifndef __TDR_$x->{NAME}_HEADER__";
+       pidl "#define __TDR_$x->{NAME}_HEADER__";
+
+       pidl "#include \"$outputdir/$x->{NAME}.h\"";
+       
+       foreach my $e (@{$x->{DATA}}) { 
+               next unless ($e->{TYPE} eq "TYPEDEF"); 
+               next unless has_property($e, "public");
+
+               my $switch = "";
+
+               $switch = ", int level" if ($e->{DATA}->{TYPE} eq "UNION");
+
+               if ($e->{DATA}->{TYPE} eq "BITMAP") {
+                       # FIXME
+               } else {
+                       my ($n, $d) = ($e->{NAME}, lc($e->{DATA}->{TYPE}));
+                       pidl "NTSTATUS tdr_pull\_$n(struct tdr_pull *tdr$switch, $d $n *v);";
+                       pidl "NTSTATUS tdr_print\_$n(struct tdr_print *tdr, const char *name$switch, $d $n *v);";
+                       pidl "NTSTATUS tdr_push\_$n(struct tdr_push *tdr$switch, $d $n *v);";
+               }
+       
+               pidl "";
+       }
+       
+       pidl "#endif /* __TDR_$x->{NAME}_HEADER__ */";
+}
+
+sub Header($$)
+{
+       my ($idl,$outputdir) = @_;
+       $ret = "";
+       pidl "/* Generated by pidl */";
+       
+       foreach (@$idl) { 
+               HeaderInterface($_, $outputdir) if ($_->{TYPE} eq "INTERFACE"); 
+       }       
+       return $ret;
+}
+
+1;
index 7523f0349561a8035e22b6e2cb054f6a9b55ec2c..99e5cbc076114eecaec63201000205e4077509e7 100755 (executable)
@@ -43,6 +43,8 @@ my($opt_template) = 0;
 my($opt_client);
 my($opt_server);
 my($opt_ndr_parser);
+my($opt_tdr_header);
+my($opt_tdr_parser);
 my($opt_eth_parser);
 my($opt_eth_header);
 my($opt_keep);
@@ -74,6 +76,8 @@ Options:
  --header[=OUTFILE]    create generic header file
  --ndr-header[=OUTFILE]create a C NDR-specific header file
  --ndr-parser[=OUTFILE]create a C NDR parser
+ --tdr-header[=OUTFILE]create a C TDR header file
+ --tdr-parser[=OUTFILE]create a C TDR parser
  --ejs[=OUTFILE]       create ejs wrapper file
  --client[=OUTFILE]    create a C NDR client
  --server[=OUTFILE]    create server boilerplate
@@ -103,6 +107,8 @@ GetOptions (
            'ndr-header:s' => \$opt_ndr_header,
                'header:s' => \$opt_header,
            'server:s' => \$opt_server,
+           'tdr-header:s' => \$opt_tdr_header,
+           'tdr-parser:s' => \$opt_tdr_parser,
            'template' => \$opt_template,
            'ndr-parser:s' => \$opt_ndr_parser,
            'client:s' => \$opt_client,
@@ -295,6 +301,18 @@ $dcom
          Parse::Pidl::Util::FileSave($eparser, Parse::Pidl::Ethereal::NDR::Parser::Parse($ndr, $basename, $eparser));
        }
 
+       my $tdr_parser = ($opt_tdr_parser or "$outputdir/tdr_$basename.c");
+       my $tdr_header = ($opt_tdr_header or "$outputdir/tdr_$basename.h");
+       if (defined($opt_tdr_parser)) {
+               require Parse::Pidl::Samba::TDR;
+               Parse::Pidl::Util::FileSave($tdr_parser, Parse::Pidl::Samba::TDR::Parser($pidl, $tdr_header));
+       }
+
+       if (defined($opt_tdr_header)) {
+               require Parse::Pidl::Samba::TDR;
+               Parse::Pidl::Util::FileSave($tdr_header, Parse::Pidl::Samba::TDR::Header($pidl, $outputdir));
+       }
+
        if ($opt_template) {
                require Parse::Pidl::Samba::Template;
                print Parse::Pidl::Samba::Template::Parse($pidl);
index 7b6b2014e66c3f77d005fd615b339d01cb4d1509..ea7abb0c9ba9de2e81a2e38809293305a2458cbc 100644 (file)
@@ -132,6 +132,7 @@ extern int errno;
 #include "smb.h"
 #include "byteorder.h"
 #include "module.h"
+#include "lib/tdr/tdr.h"
 #include "librpc/ndr/libndr.h"
 #include "librpc/gen_ndr/misc.h"
 #include "librpc/gen_ndr/dcerpc.h"
index 58cbca0198ab4b1959bde1f93423fb8cd263cdee..3953d702bc9572ae7e5ee0aa4c3ba0dd78b664a7 100644 (file)
@@ -10,6 +10,9 @@ ADD_OBJ_FILES = \
 # End SUBSYSTEM LIBNETIF
 ##############################
 
+[SUBSYSTEM::TDR]
+INIT_OBJ_FILES = lib/tdr/tdr.o
+
 ##############################
 # Start SUBSYSTEM LIBCRYPTO
 [SUBSYSTEM::LIBCRYPTO]
diff --git a/source4/lib/tdr/tdr.c b/source4/lib/tdr/tdr.c
new file mode 100644 (file)
index 0000000..c9aa289
--- /dev/null
@@ -0,0 +1,229 @@
+/* 
+   Unix SMB/CIFS implementation.
+
+   TDR (Trivial Data Representation) helper functions
+     Based loosely on ndr.c by Andrew Tridgell.
+
+   Copyright (C) Jelmer Vernooij 2005
+   
+   This program is free software; you can redistribute it and/or modify
+   it under the terms of the GNU General Public License as published by
+   the Free Software Foundation; either version 2 of the License, or
+   (at your option) any later version.
+   
+   This program is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+   GNU General Public License for more details.
+   
+   You should have received a copy of the GNU General Public License
+   along with this program; if not, write to the Free Software
+   Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+*/
+
+#include "includes.h"
+#include "system/network.h"
+
+#define TDR_BASE_MARSHALL_SIZE 1024
+
+#define TDR_PUSH_NEED_BYTES(tdr, n) TDR_CHECK(tdr_push_expand(tdr, tdr->offset+(n)))
+
+#define TDR_PULL_NEED_BYTES(tdr, n) do { \
+       if ((n) > tdr->length || tdr->offset + (n) > tdr->length) { \
+               return NT_STATUS_BUFFER_TOO_SMALL; \
+       } \
+} while(0)
+
+#define TDR_BE(tdr) ((tdr)->flags & TDR_FLAG_BIGENDIAN)
+
+#define TDR_SVAL(tdr, ofs) (TDR_BE(tdr)?RSVAL(tdr->data,ofs):SVAL(tdr->data,ofs))
+#define TDR_IVAL(tdr, ofs) (TDR_BE(tdr)?RIVAL(tdr->data,ofs):IVAL(tdr->data,ofs))
+#define TDR_IVALS(tdr, ofs) (TDR_BE(tdr)?RIVALS(tdr->data,ofs):IVALS(tdr->data,ofs))
+#define TDR_SSVAL(tdr, ofs, v) do { if (TDR_BE(tdr))  { RSSVAL(tdr->data,ofs,v); } else SSVAL(tdr->data,ofs,v); } while (0)
+#define TDR_SIVAL(tdr, ofs, v) do { if (TDR_BE(tdr))  { RSIVAL(tdr->data,ofs,v); } else SIVAL(tdr->data,ofs,v); } while (0)
+#define TDR_SIVALS(tdr, ofs, v) do { if (TDR_BE(tdr))  { RSIVALS(tdr->data,ofs,v); } else SIVALS(tdr->data,ofs,v); } while (0)
+
+struct tdr_pull *tdr_pull_init(TALLOC_CTX *mem_ctx, DATA_BLOB *blob)
+{
+       struct tdr_pull *tdr = talloc(mem_ctx, struct tdr_pull);
+       tdr->data = blob->data;
+       tdr->length = blob->length;
+       tdr->offset = 0;
+       tdr->flags = 0;
+       return tdr;
+}
+
+struct tdr_push *tdr_push_init(TALLOC_CTX *mem_ctx)
+{
+       return talloc_zero(mem_ctx, struct tdr_push);
+}
+
+struct tdr_print *tdr_print_init(TALLOC_CTX *mem_ctx)
+{
+       return talloc_zero(mem_ctx, struct tdr_print);
+}
+
+/*
+  expand the available space in the buffer to 'size'
+*/
+NTSTATUS tdr_push_expand(struct tdr_push *tdr, uint32_t size)
+{
+       if (tdr->alloc_size >= size) {
+               return NT_STATUS_OK;
+       }
+
+       tdr->alloc_size += TDR_BASE_MARSHALL_SIZE;
+       if (size > tdr->alloc_size) {
+               tdr->length = size;
+       }
+       tdr->data = talloc_realloc(tdr, tdr->data, uint8_t, tdr->alloc_size);
+       return NT_STATUS_NO_MEMORY;
+}
+
+
+NTSTATUS tdr_pull_uint8(struct tdr_pull *tdr, uint8_t *v)
+{
+       TDR_PULL_NEED_BYTES(tdr, 1);
+       SCVAL(tdr->data, tdr->offset, *v);
+       tdr->offset += 1;
+       return NT_STATUS_OK;
+}
+
+NTSTATUS tdr_push_uint8(struct tdr_push *tdr, const uint8_t *v)
+{
+       TDR_PUSH_NEED_BYTES(tdr, 1);
+       SCVAL(tdr->data, tdr->offset, *v);
+       tdr->offset += 1;
+       return NT_STATUS_OK;
+}
+
+NTSTATUS tdr_print_uint8(struct tdr_print *tdr, const char *name, uint8_t *v)
+{
+       tdr->print(tdr, "%-25s: 0x%02x (%u)", name, *v, *v);
+       return NT_STATUS_OK;
+}
+
+NTSTATUS tdr_pull_uint16(struct tdr_pull *tdr, uint16_t *v)
+{
+       TDR_PULL_NEED_BYTES(tdr, 2);
+       *v = TDR_SVAL(tdr, tdr->offset);
+       tdr->offset += 2;
+       return NT_STATUS_OK;
+}
+
+NTSTATUS tdr_push_uint16(struct tdr_push *tdr, const uint16_t *v)
+{
+       TDR_PUSH_NEED_BYTES(tdr, 2);
+       TDR_SSVAL(tdr, tdr->offset, *v);
+       tdr->offset += 2;
+       return NT_STATUS_OK;
+}
+
+NTSTATUS tdr_print_uint16(struct tdr_print *tdr, const char *name, uint16_t *v)
+{
+       tdr->print(tdr, "%-25s: 0x%02x (%u)", name, *v, *v);
+       return NT_STATUS_OK;
+}
+
+NTSTATUS tdr_pull_uint32(struct tdr_pull *tdr, uint16_t *v)
+{
+       TDR_PULL_NEED_BYTES(tdr, 4);
+       *v = TDR_IVAL(tdr, tdr->offset);
+       tdr->offset += 4;
+       return NT_STATUS_OK;
+}
+
+NTSTATUS tdr_push_uint32(struct tdr_push *tdr, const uint16_t *v)
+{
+       TDR_PUSH_NEED_BYTES(tdr, 4);
+       TDR_SIVAL(tdr, tdr->offset, *v);
+       tdr->offset += 4;
+       return NT_STATUS_OK;
+}
+
+NTSTATUS tdr_print_uint32(struct tdr_print *tdr, const char *name, uint32_t *v)
+{
+       tdr->print(tdr, "%-25s: 0x%02x (%u)", name, *v, *v);
+       return NT_STATUS_OK;
+}
+
+NTSTATUS tdr_pull_charset(struct tdr_pull *tdr, char **v, uint32_t length, uint32_t el_size, int chset)
+{
+       int ret;
+       if (length == -1) {
+               switch (chset) {
+               case CH_DOS:
+                       length = ascii_len_n((const char*)tdr->data+tdr->offset, tdr->length-tdr->offset);
+                       break;
+               case CH_UTF16:
+                       length = utf16_len_n(tdr->data+tdr->offset, tdr->length-tdr->offset);
+               default:
+                       return NT_STATUS_INVALID_PARAMETER;
+               }
+       }
+       
+       TDR_PULL_NEED_BYTES(tdr, el_size*length);
+       
+       ret = convert_string_talloc(tdr, chset, CH_UNIX, tdr->data+tdr->offset, el_size*length, (void **)v);
+
+       if (ret == -1) {
+               return NT_STATUS_INVALID_PARAMETER;
+       }
+
+       return NT_STATUS_OK;
+}
+
+NTSTATUS tdr_push_charset(struct tdr_push *tdr, const char **v, uint32_t length, uint32_t el_size, int chset)
+{
+       int ret;
+       TDR_PUSH_NEED_BYTES(tdr, el_size*length);
+
+       ret = convert_string(CH_UNIX, chset, *v, length, tdr->data+tdr->offset, el_size*length);
+
+       if (ret == -1) {
+               return NT_STATUS_INVALID_PARAMETER;
+       }
+       
+       tdr->offset += ret;
+                                                
+       return NT_STATUS_OK;
+}
+
+NTSTATUS tdr_print_charset(struct tdr_print *tdr, const char *name, const char **v, uint32_t length, uint32_t el_size, int chset)
+{
+       tdr->print(tdr, "%-25s: %s", name, *v);
+       return NT_STATUS_OK;
+}
+
+/*
+  pull a ipv4address
+*/
+NTSTATUS tdr_pull_ipv4address(struct tdr_pull *tdr, const char **address)
+{
+       struct ipv4_addr in;
+       TDR_CHECK(tdr_pull_uint32(tdr, &in.addr));
+       in.addr = htonl(in.addr);
+       *address = talloc_strdup(tdr, sys_inet_ntoa(in));
+       NT_STATUS_HAVE_NO_MEMORY(*address);
+       return NT_STATUS_OK;
+}
+
+/*
+  push a ipv4address
+*/
+NTSTATUS tdr_push_ipv4address(struct tdr_push *tdr, const char **address)
+{
+       uint32_t addr = htonl(interpret_addr(*address));
+       TDR_CHECK(tdr_push_uint32(tdr, &addr));
+       return NT_STATUS_OK;
+}
+
+/*
+  print a ipv4address
+*/
+NTSTATUS tdr_print_ipv4address(struct tdr_print *tdr, const char *name, 
+                          const char **address)
+{
+       tdr->print(tdr, "%-25s: %s", name, *address);
+       return NT_STATUS_OK;
+}
diff --git a/source4/lib/tdr/tdr.h b/source4/lib/tdr/tdr.h
new file mode 100644 (file)
index 0000000..604f9d5
--- /dev/null
@@ -0,0 +1,52 @@
+/* 
+   Unix SMB/CIFS implementation.
+   TDR definitions
+   Copyright (C) Jelmer Vernooij 2005
+   
+   This program is free software; you can redistribute it and/or modify
+   it under the terms of the GNU General Public License as published by
+   the Free Software Foundation; either version 2 of the License, or
+   (at your option) any later version.
+   
+   This program is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+   GNU General Public License for more details.
+   
+   You should have received a copy of the GNU General Public License
+   along with this program; if not, write to the Free Software
+   Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+*/
+
+#define TDR_FLAG_BIGENDIAN             1
+
+struct tdr_pull {
+       uint8_t *data;
+       uint32_t offset;
+       uint32_t length;
+       int flags;
+};
+
+struct tdr_push {
+       uint8_t *data;
+       uint32_t alloc_size;
+       uint32_t offset;
+       uint32_t length;
+       int flags;
+};
+
+struct tdr_print {
+       int level;
+       void (*print)(struct tdr_print *, const char *, ...);
+};
+
+#define TDR_CHECK(call) do { NTSTATUS _status; \
+                             _status = call; \
+                             if (!NT_STATUS_IS_OK(_status)) \
+                                return _status; \
+                        } while (0)
+
+#define TDR_ALLOC(tdr, s, n) do { \
+                              (s) = talloc_array_size(tdr, sizeof(*(s)), n); \
+                           if ((n) && !(s)) return NT_STATUS_NO_MEMORY; \
+                           } while (0)