r4288: don't use struct dcerpc_interface_table anymore in the
authorStefan Metzmacher <metze@samba.org>
Mon, 20 Dec 2004 14:37:54 +0000 (14:37 +0000)
committerGerald (Jerry) Carter <jerry@samba.org>
Wed, 10 Oct 2007 18:07:32 +0000 (13:07 -0500)
main rpc server code. let the backends specify a ndr_push/ndr_pull function
like we already do with the dispatch() function.

this allows an interface implmentation to work as real proxy
without needing to know the idl for an interface that means
just the plain decrypted payload can be forwarded

If someone want to write such a backend, patches are wellcome

metze
(This used to be commit a150bdf140d9165a05cbc7cac40b6e3c03a7bd3c)

source4/build/pidl/server.pm
source4/build/pidl/stub.pm
source4/rpc_server/dcerpc_server.c
source4/rpc_server/dcerpc_server.h
source4/rpc_server/epmapper/rpc_epmapper.c
source4/rpc_server/remote/dcesrv_remote.c

index 4deca54ac5b2f6c6d97ac6cfb6336431ec39dd53..9c72df105ba9c5f6ff35f3b6639da61a889a9a4c 100644 (file)
@@ -54,17 +54,10 @@ sub Boilerplate_Iface($)
 {
        my($interface) = shift;
        my($data) = $interface->{DATA};
-       my $count = 0;
        my $name = $interface->{NAME};
        my $uname = uc $name;
-
-       foreach my $d (@{$data}) {
-               if ($d->{TYPE} eq "FUNCTION") { $count++; }
-       }
-
-       if ($count == 0) {
-               return;
-       }
+       my $uuid = util::make_str($interface->{PROPERTIES}->{uuid});
+       my $if_version = $interface->{PROPERTIES}->{version};
 
        pidl "
 static NTSTATUS $name\__op_bind(struct dcesrv_call_state *dce_call, const struct dcesrv_interface *iface)
@@ -85,6 +78,35 @@ static void $name\__op_unbind(struct dcesrv_connection *dce_conn, const struct d
 #endif
 }
 
+static NTSTATUS $name\__op_ndr_pull(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx, struct ndr_pull *pull, void **r)
+{
+       NTSTATUS status;
+       uint16 opnum = dce_call->pkt.u.request.opnum;
+
+       dce_call->fault_code = 0;
+
+       if (opnum >= dcerpc_table_$name.num_calls) {
+               dce_call->fault_code = DCERPC_FAULT_OP_RNG_ERROR;
+               return NT_STATUS_NET_WRITE_FAULT;
+       }
+
+       *r = talloc(mem_ctx, dcerpc_table_$name.calls[opnum].struct_size);
+       if (!*r) {
+               return NT_STATUS_NO_MEMORY;
+       }
+
+        /* unravel the NDR for the packet */
+       status = dcerpc_table_$name.calls[opnum].ndr_pull(pull, NDR_IN, *r);
+       if (!NT_STATUS_IS_OK(status)) {
+               dcerpc_log_packet(&dcerpc_table_$name, opnum, NDR_IN,
+                                 &dce_call->pkt.u.request.stub_and_verifier);
+               dce_call->fault_code = DCERPC_FAULT_NDR;
+               return NT_STATUS_NET_WRITE_FAULT;
+       }
+
+       return NT_STATUS_OK;
+}
+
 static NTSTATUS $name\__op_dispatch(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx, void *r)
 {
        uint16 opnum = dce_call->pkt.u.request.opnum;
@@ -104,14 +126,33 @@ pidl "
        if (dce_call->fault_code != 0) {
                return NT_STATUS_NET_WRITE_FAULT;
        }
+
+       return NT_STATUS_OK;
+}
+
+static NTSTATUS $name\__op_ndr_push(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx, struct ndr_push *push, void *r)
+{
+       NTSTATUS status;
+       uint16 opnum = dce_call->pkt.u.request.opnum;
+
+       status = dcerpc_table_$name.calls[opnum].ndr_push(push, NDR_OUT, r);
+       if (!NT_STATUS_IS_OK(status)) {
+               dce_call->fault_code = DCERPC_FAULT_NDR;
+               return NT_STATUS_NET_WRITE_FAULT;
+       }
+
        return NT_STATUS_OK;
 }
 
 static const struct dcesrv_interface $name\_interface = {
-       &dcerpc_table_$name,
+       \"$name\",
+       $uuid,
+       $if_version,
        $name\__op_bind,
        $name\__op_unbind,
-       $name\__op_dispatch
+       $name\__op_ndr_pull,
+       $name\__op_dispatch,
+       $name\__op_ndr_push
 };
 
 ";
@@ -122,27 +163,17 @@ static const struct dcesrv_interface $name\_interface = {
 sub Boilerplate_Ep_Server($)
 {
        my($interface) = shift;
-       my($data) = $interface->{DATA};
-       my $count = 0;
        my $name = $interface->{NAME};
        my $uname = uc $name;
 
-       foreach my $d (@{$data}) {
-               if ($d->{TYPE} eq "FUNCTION") { $count++; }
-       }
-
-       if ($count == 0) {
-               return;
-       }
-
        pidl "
 static NTSTATUS $name\__op_init_server(struct dcesrv_context *dce_ctx, const struct dcesrv_endpoint_server *ep_server)
 {
        int i;
 
-       for (i=0;i<$name\_interface.ndr->endpoints->count;i++) {
+       for (i=0;i<dcerpc_table_$name.endpoints->count;i++) {
                NTSTATUS ret;
-               const char *name = $name\_interface.ndr->endpoints->names[i];
+               const char *name = dcerpc_table_$name.endpoints->names[i];
 
                ret = dcesrv_interface_register(dce_ctx, name, &$name\_interface, NULL);
                if (!NT_STATUS_IS_OK(ret)) {
@@ -156,8 +187,8 @@ static NTSTATUS $name\__op_init_server(struct dcesrv_context *dce_ctx, const str
 
 static BOOL $name\__op_interface_by_uuid(struct dcesrv_interface *iface, const char *uuid, uint32 if_version)
 {
-       if ($name\_interface.ndr->if_version == if_version &&
-               strcmp($name\_interface.ndr->uuid, uuid)==0) {
+       if ($name\_interface.if_version == if_version &&
+               strcmp($name\_interface.uuid, uuid)==0) {
                memcpy(iface,&$name\_interface, sizeof(*iface));
                return True;
        }
@@ -167,7 +198,7 @@ static BOOL $name\__op_interface_by_uuid(struct dcesrv_interface *iface, const c
 
 static BOOL $name\__op_interface_by_name(struct dcesrv_interface *iface, const char *name)
 {
-       if (strcmp($name\_interface.ndr->name, name)==0) {
+       if (strcmp($name\_interface.name, name)==0) {
                memcpy(iface,&$name\_interface, sizeof(*iface));
                return True;
        }
@@ -208,6 +239,27 @@ NTSTATUS dcerpc_server_$name\_init(void)
 sub ParseInterface($)
 {
        my($interface) = shift;
+       my($data) = $interface->{DATA};
+       my $count = 0;
+
+       $res = "";
+
+       if (!defined $interface->{PROPERTIES}->{uuid}) {
+               return $res;
+       }
+
+       if (!defined $interface->{PROPERTIES}->{version}) {
+               $interface->{PROPERTIES}->{version} = "0.0";
+       }
+
+       foreach my $d (@{$data}) {
+               if ($d->{TYPE} eq "FUNCTION") { $count++; }
+       }
+
+       if ($count == 0) {
+               return $res;
+       }
+
        $res = "/* dcerpc server boilerplate generated by pidl */\n\n";
        Boilerplate_Iface($interface);
        Boilerplate_Ep_Server($interface);
index fde239219ffb42f9ba519370ff421165ccffaa76..42c83a467e0e8e01f507b08999662be8a119f235 100644 (file)
@@ -60,14 +60,8 @@ sub Boilerplate_Iface($)
        my $count = 0;
        my $name = $interface->{NAME};
        my $uname = uc $name;
-
-       foreach my $d (@{$data}) {
-               if ($d->{TYPE} eq "FUNCTION") { $count++; }
-       }
-
-       if ($count == 0) {
-               return;
-       }
+       my $uuid = util::make_str($interface->{PROPERTIES}->{uuid});
+       my $if_version = $interface->{PROPERTIES}->{version};
 
        pidl "
 static NTSTATUS $name\__op_bind(struct dcesrv_call_state *dce_call, const struct dcesrv_interface *iface)
@@ -88,6 +82,35 @@ static void $name\__op_unbind(struct dcesrv_connection *dce_conn, const struct d
 #endif
 }
 
+static NTSTATUS $name\__op_ndr_pull(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx, struct ndr_pull *pull, void **r)
+{
+       NTSTATUS status;
+       uint16 opnum = dce_call->pkt.u.request.opnum;
+
+       dce_call->fault_code = 0;
+
+       if (opnum >= dcerpc_table_$name.num_calls) {
+               dce_call->fault_code = DCERPC_FAULT_OP_RNG_ERROR;
+               return NT_STATUS_NET_WRITE_FAULT;
+       }
+
+       *r = talloc(mem_ctx, dcerpc_table_$name.calls[opnum].struct_size);
+       if (!*r) {
+               return NT_STATUS_NO_MEMORY;
+       }
+
+       /* unravel the NDR for the packet */
+       status = dcerpc_table_$name.calls[opnum].ndr_pull(pull, NDR_IN, *r);
+       if (!NT_STATUS_IS_OK(status)) {
+               dcerpc_log_packet(&dcerpc_table_$name, opnum, NDR_IN,
+                                 &dce_call->pkt.u.request.stub_and_verifier);
+               dce_call->fault_code = DCERPC_FAULT_NDR;
+               return NT_STATUS_NET_WRITE_FAULT;
+       }
+
+       return NT_STATUS_OK;
+}
+
 static NTSTATUS $name\__op_dispatch(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx, void *r)
 {
        uint16 opnum = dce_call->pkt.u.request.opnum;
@@ -113,11 +136,29 @@ pidl "
        return NT_STATUS_OK;
 }
 
+static NTSTATUS $name\__op_ndr_push(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx, struct ndr_push *push, void *r)
+{
+       NTSTATUS status;
+       uint16 opnum = dce_call->pkt.u.request.opnum;
+
+       status = dcerpc_table_$name.calls[opnum].ndr_push(push, NDR_OUT, r);
+       if (!NT_STATUS_IS_OK(status)) {
+               dce_call->fault_code = DCERPC_FAULT_NDR;
+               return NT_STATUS_NET_WRITE_FAULT;
+       }
+
+       return NT_STATUS_OK;
+}
+
 static const struct dcesrv_interface $name\_interface = {
-       &dcerpc_table_$name,
+       \"$name\",
+       $uuid,
+       $if_version,
        $name\__op_bind,
        $name\__op_unbind,
-       $name\__op_dispatch
+       $name\__op_ndr_pull,
+       $name\__op_dispatch,
+       $name\__op_ndr_push
 };
 
 ";
@@ -128,27 +169,17 @@ static const struct dcesrv_interface $name\_interface = {
 sub Boilerplate_Ep_Server($)
 {
        my($interface) = shift;
-       my($data) = $interface->{DATA};
-       my $count = 0;
        my $name = $interface->{NAME};
        my $uname = uc $name;
 
-       foreach my $d (@{$data}) {
-               if ($d->{TYPE} eq "FUNCTION") { $count++; }
-       }
-
-       if ($count == 0) {
-               return;
-       }
-
        pidl "
 static NTSTATUS $name\__op_init_server(struct dcesrv_context *dce_ctx, const struct dcesrv_endpoint_server *ep_server)
 {
        int i;
 
-       for (i=0;i<$name\_interface.ndr->endpoints->count;i++) {
+       for (i=0;i<dcerpc_table_$name.endpoints->count;i++) {
                NTSTATUS ret;
-               const char *name = $name\_interface.ndr->endpoints->names[i];
+               const char *name = dcerpc_table_$name.endpoints->names[i];
 
                ret = dcesrv_interface_register(dce_ctx, name, &$name\_interface, NULL);
                if (!NT_STATUS_IS_OK(ret)) {
@@ -162,9 +193,9 @@ static NTSTATUS $name\__op_init_server(struct dcesrv_context *dce_ctx, const str
 
 static BOOL $name\__op_interface_by_uuid(struct dcesrv_interface *iface, const char *uuid, uint32 if_version)
 {
-       if ($name\_interface.ndr->if_version == if_version &&
-               strcmp($name\_interface.ndr->uuid, uuid)==0) {
-               memcpy(iface,&$name\_interface, sizeof(*iface));
+       if (dcerpc_table_$name.if_version == if_version &&
+               strcmp(dcerpc_table_$name.uuid, uuid)==0) {
+               memcpy(iface,&dcerpc_table_$name, sizeof(*iface));
                return True;
        }
 
@@ -173,8 +204,8 @@ static BOOL $name\__op_interface_by_uuid(struct dcesrv_interface *iface, const c
 
 static BOOL $name\__op_interface_by_name(struct dcesrv_interface *iface, const char *name)
 {
-       if (strcmp($name\_interface.ndr->name, name)==0) {
-               memcpy(iface,&$name\_interface, sizeof(*iface));
+       if (strcmp(dcerpc_table_$name.name, name)==0) {
+               memcpy(iface,&dcerpc_table_$name, sizeof(*iface));
                return True;
        }
 
@@ -196,7 +227,7 @@ NTSTATUS dcerpc_server_$name\_init(void)
        ep_server.interface_by_name = $name\__op_interface_by_name;
 
        /* register ourselves with the DCERPC subsystem. */
-    ret = dcerpc_register_ep_server(&ep_server);
+       ret = dcerpc_register_ep_server(&ep_server);
 
        if (!NT_STATUS_IS_OK(ret)) {
                DEBUG(0,(\"Failed to register \'$name\' endpoint server!\\n\"));
@@ -212,8 +243,28 @@ NTSTATUS dcerpc_server_$name\_init(void)
 sub ParseInterface($)
 {
        my($interface) = shift;
-       $res = "/* dcom interface stub generated by pidl */\n\n";
+               my($data) = $interface->{DATA};
+       my $count = 0;
+
+       $res = "";
+
+       if (!defined $interface->{PROPERTIES}->{uuid}) {
+               return $res;
+       }
+
+       if (!defined $interface->{PROPERTIES}->{version}) {
+               $interface->{PROPERTIES}->{version} = "0.0";
+       }
+
+       foreach my $d (@{$data}) {
+               if ($d->{TYPE} eq "FUNCTION") { $count++; }
+       }
 
+       if ($count == 0) {
+               return $res;
+       }
+
+       $res = "/* dcom interface stub generated by pidl */\n\n";
        Boilerplate_Iface($interface);
        Boilerplate_Ep_Server($interface);
 
index 6e608fd30b0c5ff0ff65c110d8e03039e03e6a86..231778247fdad27bcff3b056f562c24b0c71ab34 100644 (file)
@@ -69,11 +69,11 @@ static struct dcesrv_endpoint *find_endpoint(struct dcesrv_context *dce_ctx,
 static BOOL interface_match(const struct dcesrv_interface *if1,
                                                        const struct dcesrv_interface *if2)
 {
-       if (if1->ndr->if_version != if2->ndr->if_version) {
+       if (if1->if_version != if2->if_version) {
                return False;
        }
 
-       if (strcmp(if1->ndr->uuid, if2->ndr->uuid)==0) {
+       if (strcmp(if1->uuid, if2->uuid)==0) {
                return True;
        }                       
 
@@ -101,11 +101,11 @@ static const struct dcesrv_interface *find_interface(const struct dcesrv_endpoin
 static BOOL interface_match_by_uuid(const struct dcesrv_interface *iface,
                                    const char *uuid, uint32_t if_version)
 {
-       if (iface->ndr->if_version != if_version) {
+       if (iface->if_version != if_version) {
                return False;
        }
 
-       if (strcmp(iface->ndr->uuid, uuid)==0) {
+       if (strcmp(iface->uuid, uuid)==0) {
                return True;
        }                       
 
@@ -177,7 +177,7 @@ NTSTATUS dcesrv_interface_register(struct dcesrv_context *dce_ctx,
        /* see if the interface is already registered on te endpoint */
        if (find_interface(ep, iface)!=NULL) {
                DEBUG(0,("dcesrv_interface_register: interface '%s' already registered on endpoint '%s'\n",
-                       iface->ndr->name, ep_name));
+                       iface->name, ep_name));
                return NT_STATUS_OBJECT_NAME_COLLISION;
        }
 
@@ -208,7 +208,7 @@ NTSTATUS dcesrv_interface_register(struct dcesrv_context *dce_ctx,
                if (ep->sd != NULL) {
                        DEBUG(0,("dcesrv_interface_register: interface '%s' failed to setup a security descriptor\n"
                                 "                           on endpoint '%s'\n",
-                               iface->ndr->name, ep_name));
+                               iface->name, ep_name));
                        if (add_ep) free(ep);
                        free(ifl);
                        return NT_STATUS_OBJECT_NAME_COLLISION;
@@ -224,7 +224,7 @@ NTSTATUS dcesrv_interface_register(struct dcesrv_context *dce_ctx,
        }
 
        DEBUG(4,("dcesrv_interface_register: interface '%s' registered on endpoint '%s'\n",
-               iface->ndr->name, ep_name));
+               iface->name, ep_name));
 
        return NT_STATUS_OK;
 }
@@ -497,10 +497,10 @@ static NTSTATUS dcesrv_bind(struct dcesrv_call_state *call)
        pkt.u.bind_ack.max_xmit_frag = 0x2000;
        pkt.u.bind_ack.max_recv_frag = 0x2000;
        pkt.u.bind_ack.assoc_group_id = call->pkt.u.bind.assoc_group_id;
-       if (call->conn->iface && call->conn->iface->ndr) {
+       if (call->conn->iface) {
                /* FIXME: Use pipe name as specified by endpoint instead of interface name */
                pkt.u.bind_ack.secondary_address = talloc_asprintf(call, "\\PIPE\\%s", 
-                                                                  call->conn->iface->ndr->name);
+                                                                  call->conn->iface->name);
        } else {
                pkt.u.bind_ack.secondary_address = "";
        }
@@ -631,23 +631,17 @@ static NTSTATUS dcesrv_request(struct dcesrv_call_state *call)
 {
        struct ndr_pull *pull;
        struct ndr_push *push;
-       uint16_t opnum;
        void *r;
        NTSTATUS status;
        DATA_BLOB stub;
        uint32_t total_length;
 
+       call->fault_code = 0;
 
        if (!call->conn->iface) {
                return dcesrv_fault(call, DCERPC_FAULT_UNK_IF);
        }
 
-       opnum = call->pkt.u.request.opnum;
-
-       if (opnum >= call->conn->iface->ndr->num_calls) {
-               return dcesrv_fault(call, DCERPC_FAULT_OP_RNG_ERROR);
-       }
-
        pull = ndr_pull_init_blob(&call->pkt.u.request.stub_and_verifier, call);
        if (!pull) {
                return NT_STATUS_NO_MEMORY;
@@ -657,21 +651,14 @@ static NTSTATUS dcesrv_request(struct dcesrv_call_state *call)
                pull->flags |= LIBNDR_FLAG_OBJECT_PRESENT;
        }
 
-       r = talloc(call, call->conn->iface->ndr->calls[opnum].struct_size);
-       if (!r) {
-               return NT_STATUS_NO_MEMORY;
-       }
-
        if (!(call->pkt.drep[0] & DCERPC_DREP_LE)) {
                pull->flags |= LIBNDR_FLAG_BIGENDIAN;
        }
 
        /* unravel the NDR for the packet */
-       status = call->conn->iface->ndr->calls[opnum].ndr_pull(pull, NDR_IN, r);
+       status = call->conn->iface->ndr_pull(call, call, pull, &r);
        if (!NT_STATUS_IS_OK(status)) {
-               dcerpc_log_packet(call->conn->iface->ndr, opnum, NDR_IN, 
-                                 &call->pkt.u.request.stub_and_verifier);
-               return dcesrv_fault(call, DCERPC_FAULT_NDR);
+               return dcesrv_fault(call, call->fault_code);
        }
 
        if (pull->offset != pull->data_size) {
@@ -680,13 +667,9 @@ static NTSTATUS dcesrv_request(struct dcesrv_call_state *call)
                dump_data(10, pull->data+pull->offset, pull->data_size - pull->offset);
        }
 
-       call->fault_code = 0;
-
        /* call the dispatch function */
        status = call->conn->iface->dispatch(call, call, r);
        if (!NT_STATUS_IS_OK(status)) {
-               dcerpc_log_packet(call->conn->iface->ndr, opnum, NDR_IN, 
-                                 &call->pkt.u.request.stub_and_verifier);
                return dcesrv_fault(call, call->fault_code);
        }
 
@@ -705,9 +688,9 @@ static NTSTATUS dcesrv_request(struct dcesrv_call_state *call)
                push->flags |= LIBNDR_FLAG_BIGENDIAN;
        }
 
-       status = call->conn->iface->ndr->calls[opnum].ndr_push(push, NDR_OUT, r);
+       status = call->conn->iface->ndr_push(call, call, push, r);
        if (!NT_STATUS_IS_OK(status)) {
-               return dcesrv_fault(call, DCERPC_FAULT_NDR);
+               return dcesrv_fault(call, call->fault_code);
        }
 
        stub = ndr_push_blob(push);
index 12c93140ec01b6d95c23a203e198b0cb236d0ae2..c919476d1bdcecdfe61df62a9b82811fd2cf07bf 100644 (file)
@@ -35,12 +35,10 @@ struct dcesrv_connection;
 struct dcesrv_call_state;
 struct dcesrv_auth;
 
-/* the dispatch functions for an interface take this form */
-typedef NTSTATUS (*dcesrv_dispatch_fn_t)(struct dcesrv_call_state *, TALLOC_CTX *, void *);
-
 struct dcesrv_interface {
-       /* the ndr function table for the chosen interface */
-       const struct dcerpc_interface_table *ndr;
+       const char *name;
+       const char *uuid;
+       uint32_t if_version;
 
        /* this function is called when the client binds to this interface  */
        NTSTATUS (*bind)(struct dcesrv_call_state *, const struct dcesrv_interface *);
@@ -48,10 +46,22 @@ struct dcesrv_interface {
        /* this function is called when the client disconnects the endpoint */
        void (*unbind)(struct dcesrv_connection *, const struct dcesrv_interface *);
 
+
+       /* the ndr_pull function for the chosen interface.
+        */
+       NTSTATUS (*ndr_pull)(struct dcesrv_call_state *, TALLOC_CTX *, struct ndr_pull *, void **);;
+       
        /* the dispatch function for the chosen interface.
         */
-       dcesrv_dispatch_fn_t dispatch;
-}; 
+       NTSTATUS (*dispatch)(struct dcesrv_call_state *, TALLOC_CTX *, void *);
+
+       /* the ndr_push function for the chosen interface.
+        */
+       NTSTATUS (*ndr_push)(struct dcesrv_call_state *, TALLOC_CTX *, struct ndr_push *,void *);
+
+       /* for any private use by the interface code */
+       const void *private;
+};
 
 /* the state of an ongoing dcerpc call */
 struct dcesrv_call_state {
index 8f4450c2ef02189ef32618247fbdb0a8a326169e..8519f994866303788f09d94604180ba92a94c08d 100644 (file)
@@ -72,12 +72,10 @@ static uint32_t build_ep_list(TALLOC_CTX *mem_ctx,
                        if (!*eps) {
                                return 0;
                        }
-                       (*eps)[total].name = iface->iface.ndr->name;
+                       (*eps)[total].name = iface->iface.name;
                        (*eps)[total].ep_description = d->ep_description;
-                       GUID_from_string(iface->iface.ndr->uuid, 
-                                                        &(*eps)[total].ep_description.object);
-                       (*eps)[total].ep_description.object_version = 
-                                                                                       iface->iface.ndr->if_version;
+                       GUID_from_string(iface->iface.uuid, &(*eps)[total].ep_description.object);
+                       (*eps)[total].ep_description.object_version = iface->iface.if_version;
                        total++;
                }
        }
index ab09920b990e615bca4264498350032843962144..3bf917ac7182a704ab869cef62b34e89154d85e0 100644 (file)
@@ -24,7 +24,6 @@
 
 struct dcesrv_remote_private {
        struct dcerpc_pipe *c_pipe;
-       void *private;  
 };
 
 static NTSTATUS remote_op_bind(struct dcesrv_call_state *dce_call, const struct dcesrv_interface *iface)
@@ -34,7 +33,7 @@ static NTSTATUS remote_op_bind(struct dcesrv_call_state *dce_call, const struct
        const char *binding = lp_parm_string(-1, "dcerpc_remote", "binding");
 
        if (!binding) {
-               printf("You must specify a ncacn binding string\n");
+               DEBUG(0,("You must specify a ncacn binding string\n"));
                return NT_STATUS_INVALID_PARAMETER;
        }
 
@@ -43,10 +42,13 @@ static NTSTATUS remote_op_bind(struct dcesrv_call_state *dce_call, const struct
                return NT_STATUS_NO_MEMORY;     
        }
 
-       status = dcerpc_pipe_connect(&(private->c_pipe), binding, iface->ndr->uuid, iface->ndr->if_version,
+       status = dcerpc_pipe_connect(&(private->c_pipe), binding, iface->uuid, iface->if_version,
                                     lp_workgroup(), 
                                     lp_parm_string(-1, "dcerpc_remote", "username"),
                                     lp_parm_string(-1, "dcerpc_remote", "password"));
+       if (!NT_STATUS_IS_OK(status)) {
+               return status;
+       }
 
        dce_call->conn->private = private;
 
@@ -62,28 +64,53 @@ static void remote_op_unbind(struct dcesrv_connection *dce_conn, const struct dc
        return; 
 }
 
-static NTSTATUS remote_op_dispatch(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx, void *r)
+static NTSTATUS remote_op_ndr_pull(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx, struct ndr_pull *pull, void **r)
 {
-       struct dcesrv_remote_private *private = dce_call->conn->private;
+       NTSTATUS status;
+       const struct dcerpc_interface_table *table = dce_call->conn->iface->private;
        uint16_t opnum = dce_call->pkt.u.request.opnum;
-       const struct dcerpc_interface_call *call;
-       const char *name;
 
-       if (opnum >= dce_call->conn->iface->ndr->num_calls) {
+       dce_call->fault_code = 0;
+
+       if (opnum >= table->num_calls) {
                dce_call->fault_code = DCERPC_FAULT_OP_RNG_ERROR;
                return NT_STATUS_NET_WRITE_FAULT;
        }
 
-       name = dce_call->conn->iface->ndr->calls[opnum].name;
-       call = &dce_call->conn->iface->ndr->calls[opnum];
+       *r = talloc(mem_ctx, table->calls[opnum].struct_size);
+       if (!*r) {
+               return NT_STATUS_NO_MEMORY;
+       }
+
+        /* unravel the NDR for the packet */
+       status = table->calls[opnum].ndr_pull(pull, NDR_IN, *r);
+       if (!NT_STATUS_IS_OK(status)) {
+               dcerpc_log_packet(table, opnum, NDR_IN,
+                                 &dce_call->pkt.u.request.stub_and_verifier);
+               dce_call->fault_code = DCERPC_FAULT_NDR;
+               return NT_STATUS_NET_WRITE_FAULT;
+       }
+
+       return NT_STATUS_OK;
+}
+
+static NTSTATUS remote_op_dispatch(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx, void *r)
+{
+       struct dcesrv_remote_private *private = dce_call->conn->private;
+       uint16_t opnum = dce_call->pkt.u.request.opnum;
+       const struct dcerpc_interface_table *table = dce_call->conn->iface->private;
+       const struct dcerpc_interface_call *call;
+       const char *name;
+
+       name = table->calls[opnum].name;
+       call = &table->calls[opnum];
 
        if (private->c_pipe->flags & DCERPC_DEBUG_PRINT_IN) {
                ndr_print_function_debug(call->ndr_print, name, NDR_IN | NDR_SET_VALUES, r);            
        }
 
        /* we didn't use the return code of this function as we only check the last_fault_code */
-       dcerpc_ndr_request(private->c_pipe, NULL, dce_call->conn->iface->ndr,
-                                   opnum, mem_ctx,r);
+       dcerpc_ndr_request(private->c_pipe, NULL, table, opnum, mem_ctx,r);
 
        dce_call->fault_code = private->c_pipe->last_fault_code;
        if (dce_call->fault_code != 0) {
@@ -98,13 +125,30 @@ static NTSTATUS remote_op_dispatch(struct dcesrv_call_state *dce_call, TALLOC_CT
        return NT_STATUS_OK;
 }
 
+static NTSTATUS remote_op_ndr_push(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx, struct ndr_push *push, void *r)
+{
+       NTSTATUS status;
+       const struct dcerpc_interface_table *table = dce_call->conn->iface->private;
+       uint16_t opnum = dce_call->pkt.u.request.opnum;
+
+        /* unravel the NDR for the packet */
+       status = table->calls[opnum].ndr_push(push, NDR_OUT, r);
+       if (!NT_STATUS_IS_OK(status)) {
+               dce_call->fault_code = DCERPC_FAULT_NDR;
+               return NT_STATUS_NET_WRITE_FAULT;
+       }
+
+       return NT_STATUS_OK;
+}
+
 static NTSTATUS remote_register_one_iface(struct dcesrv_context *dce_ctx, const struct dcesrv_interface *iface)
 {
        int i;
+       const struct dcerpc_interface_table *table = iface->private;
 
-       for (i=0;i<iface->ndr->endpoints->count;i++) {
+       for (i=0;i<table->endpoints->count;i++) {
                NTSTATUS ret;
-               const char *name = iface->ndr->endpoints->names[i];
+               const char *name = table->endpoints->names[i];
 
                ret = dcesrv_interface_register(dce_ctx, name, iface, NULL);
                if (!NT_STATUS_IS_OK(ret)) {
@@ -150,11 +194,18 @@ static NTSTATUS remote_op_init_server(struct dcesrv_context *dce_ctx, const stru
 
 static BOOL remote_fill_interface(struct dcesrv_interface *iface, const struct dcerpc_interface_table *if_tabl)
 {
-       iface->ndr = if_tabl;
-
+       iface->name = if_tabl->name;
+       iface->uuid = if_tabl->uuid;
+       iface->if_version = if_tabl->if_version;
+       
        iface->bind = remote_op_bind;
        iface->unbind = remote_op_unbind;
+
+       iface->ndr_pull = remote_op_ndr_pull;
        iface->dispatch = remote_op_dispatch;
+       iface->ndr_push = remote_op_ndr_push;
+
+       iface->private = if_tabl;
 
        return True;
 }