r4637: log packets when the server code returns an DCERPC_FAULT
[samba.git] / source4 / build / pidl / stub.pm
index 2bcece841682bd3a10abae00703cb4b7aa1d8aa8..8546bbf30761faa5e3ef8bedf1e536fbccebc142 100644 (file)
@@ -27,7 +27,9 @@ sub gen_dispatch_switch($)
                next if ($d->{TYPE} ne "FUNCTION");
 
                pidl "\tcase $count: {\n";
-               pidl "\t\tNTSTATUS result;\n";
+               if ($d->{RETURN_TYPE} && $d->{RETURN_TYPE} ne "void") {
+                       pidl "\t\tNTSTATUS result;\n";
+               }
                pidl "\t\tstruct $d->{NAME} *r2 = r;\n";
                pidl "\t\tif (DEBUGLEVEL > 10) {\n";
                pidl "\t\t\tNDR_PRINT_FUNCTION_DEBUG($d->{NAME}, NDR_IN, r2);\n";
@@ -58,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)
@@ -86,11 +82,40 @@ 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_size(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;
        struct GUID ipid = dce_call->pkt.u.request.object.object;
-       struct dcom_interface_p *iface = dcom_get_iface_p(&ipid);
+       struct dcom_interface_p *iface = dcom_get_local_iface_p(&ipid);
        const struct dcom_$name\_vtable *vtable = iface->vtable;
 
        dce_call->fault_code = 0;
@@ -106,16 +131,37 @@ pidl "
        }
 
        if (dce_call->fault_code != 0) {
+               dcerpc_log_packet(&dcerpc_table_$name, opnum, NDR_IN,
+                                 &dce_call->pkt.u.request.stub_and_verifier);
+               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
 };
 
 ";
@@ -126,27 +172,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)) {
@@ -160,9 +196,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;
        }
 
@@ -171,8 +207,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;
        }
 
@@ -194,7 +230,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\"));
@@ -210,8 +246,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);