summaryrefslogtreecommitdiff
path: root/source4
diff options
context:
space:
mode:
Diffstat (limited to 'source4')
-rw-r--r--source4/build/pidl/Parse/Pidl/Samba/TDR.pm252
-rwxr-xr-xsource4/build/pidl/pidl18
-rw-r--r--source4/include/includes.h1
-rw-r--r--source4/lib/basic.mk3
-rw-r--r--source4/lib/tdr/tdr.c229
-rw-r--r--source4/lib/tdr/tdr.h52
6 files changed, 555 insertions, 0 deletions
diff --git a/source4/build/pidl/Parse/Pidl/Samba/TDR.pm b/source4/build/pidl/Parse/Pidl/Samba/TDR.pm
new file mode 100644
index 0000000000..fb9dd0daea
--- /dev/null
+++ b/source4/build/pidl/Parse/Pidl/Samba/TDR.pm
@@ -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;
diff --git a/source4/build/pidl/pidl b/source4/build/pidl/pidl
index 7523f03495..99e5cbc076 100755
--- a/source4/build/pidl/pidl
+++ b/source4/build/pidl/pidl
@@ -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);
diff --git a/source4/include/includes.h b/source4/include/includes.h
index 7b6b2014e6..ea7abb0c9b 100644
--- a/source4/include/includes.h
+++ b/source4/include/includes.h
@@ -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"
diff --git a/source4/lib/basic.mk b/source4/lib/basic.mk
index 58cbca0198..3953d702bc 100644
--- a/source4/lib/basic.mk
+++ b/source4/lib/basic.mk
@@ -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
index 0000000000..c9aa289f00
--- /dev/null
+++ b/source4/lib/tdr/tdr.c
@@ -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
index 0000000000..604f9d549a
--- /dev/null
+++ b/source4/lib/tdr/tdr.h
@@ -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)