added support for fragmented sends
authorAndrew Tridgell <tridge@samba.org>
Tue, 4 Nov 2003 03:38:46 +0000 (03:38 +0000)
committerAndrew Tridgell <tridge@samba.org>
Tue, 4 Nov 2003 03:38:46 +0000 (03:38 +0000)
(This used to be commit f51a216136b7cc7d4d07d4acb80e0a710d82841a)

source4/libcli/raw/rawdcerpc.c
source4/libcli/rpc/dcerpc.c
source4/libcli/rpc/dcerpc.h
source4/torture/rpc/echo.c
source4/torture/torture.c

index d548129ab17acf745336a6ce6b89bd9c60a8be07..a6cd75eeaa71eb9ddca8b2fd5d13eb20a6869785 100644 (file)
@@ -218,3 +218,35 @@ NTSTATUS dcerpc_raw_packet_secondary(struct dcerpc_pipe *p,
 
        return status;
 }
+
+
+/* 
+   send an initial pdu in a multi-pdu sequence
+*/
+NTSTATUS dcerpc_raw_packet_initial(struct dcerpc_pipe *p, 
+                                  TALLOC_CTX *mem_ctx,
+                                  DATA_BLOB *blob)
+{
+       union smb_write io;
+       NTSTATUS status;
+
+       io.generic.level = RAW_WRITE_WRITEX;
+       io.writex.in.fnum = p->fnum;
+       io.writex.in.offset = 0;
+       io.writex.in.wmode = PIPE_START_MESSAGE;
+       io.writex.in.remaining = blob->length;
+       io.writex.in.count = blob->length;
+       io.writex.in.data = blob->data;
+
+       status = smb_raw_write(p->tree, &io);
+       if (NT_STATUS_IS_OK(status)) {
+               return status;
+       }
+
+       /* make sure it accepted it all */
+       if (io.writex.out.nwritten != blob->length) {
+               return NT_STATUS_UNSUCCESSFUL;
+       }
+
+       return status;
+}
index d4f21f969ad13277ea291e9280ba4e8e050ed12f..7d6888dde7072c7c85d4ad4bfdd26b6d26ca519f 100644 (file)
@@ -186,11 +186,11 @@ static NTSTATUS dcerpc_pull_response(DATA_BLOB *blob, TALLOC_CTX *mem_ctx,
                                     struct dcerpc_hdr *hdr,
                                     struct dcerpc_response *pkt)
 {
-       uint32 alloc_hint, stub_len;
+       uint32 stub_len;
        
        BLOB_CHECK_BOUNDS(blob, *offset, 8);
 
-       alloc_hint        = IVAL(blob->data, (*offset) + 0);
+       pkt->alloc_hint   = IVAL(blob->data, (*offset) + 0);
        pkt->context_id   = SVAL(blob->data, (*offset) + 4);
        pkt->cancel_count = CVAL(blob->data, (*offset) + 6);
 
@@ -382,9 +382,7 @@ static NTSTATUS dcerpc_push_request(DATA_BLOB *blob, uint32 *offset,
                                    struct dcerpc_hdr *hdr,
                                    struct dcerpc_request *pkt)
 {
-       uint32 alloc_hint = 8 + pkt->stub_data.length + pkt->auth_verifier.length;
-
-       SIVAL(blob->data, (*offset) + 0, alloc_hint);
+       SIVAL(blob->data, (*offset) + 0, pkt->alloc_hint);
        SSVAL(blob->data, (*offset) + 4, pkt->context_id);
        SSVAL(blob->data, (*offset) + 6, pkt->opnum);
 
@@ -621,24 +619,67 @@ NTSTATUS cli_dcerpc_request(struct dcerpc_pipe *p,
        struct dcerpc_packet pkt;
        NTSTATUS status;
        DATA_BLOB blob_in, blob_out, payload;
+       uint32 remaining, chunk_size;
 
        init_dcerpc_hdr(&pkt.hdr);
 
+       remaining = stub_data_in->length;
+
+       /* we can write a full max_recv_frag size, minus the dcerpc
+          request header size */
+       chunk_size = p->srv_max_recv_frag - 24;
+
        pkt.hdr.ptype = DCERPC_PKT_REQUEST;
-       pkt.hdr.pfc_flags = DCERPC_PFC_FLAG_FIRST | DCERPC_PFC_FLAG_LAST;
        pkt.hdr.call_id = p->call_id++;
        pkt.hdr.auth_length = 0;
-
+       pkt.in.request.alloc_hint = remaining;
        pkt.in.request.context_id = 0;
        pkt.in.request.opnum = opnum;
-       pkt.in.request.stub_data = *stub_data_in;
        pkt.in.request.auth_verifier = data_blob(NULL, 0);
 
+       /* we send a series of pdus without waiting for a reply until
+          the last pdu */
+       while (remaining > chunk_size) {
+               if (remaining == stub_data_in->length) {
+                       pkt.hdr.pfc_flags = DCERPC_PFC_FLAG_FIRST;
+               } else {
+                       pkt.hdr.pfc_flags = 0;
+               }
+
+               pkt.in.request.stub_data.data = stub_data_in->data + 
+                       (stub_data_in->length - remaining);
+               pkt.in.request.stub_data.length = chunk_size;
+
+               status = dcerpc_push(&blob_in, mem_ctx, &pkt);
+               if (!NT_STATUS_IS_OK(status)) {
+                       return status;
+               }
+               
+               status = dcerpc_raw_packet_initial(p, mem_ctx, &blob_in);
+               if (!NT_STATUS_IS_OK(status)) {
+                       return status;
+               }               
+
+               remaining -= chunk_size;
+       }
+
+       /* now we send a pdu with LAST_FRAG sent and get the first
+          part of the reply */
+       if (remaining == stub_data_in->length) {
+               pkt.hdr.pfc_flags = DCERPC_PFC_FLAG_FIRST | DCERPC_PFC_FLAG_LAST;
+       } else {
+               pkt.hdr.pfc_flags = DCERPC_PFC_FLAG_LAST;
+       }
+       pkt.in.request.stub_data.data = stub_data_in->data + 
+               (stub_data_in->length - remaining);
+       pkt.in.request.stub_data.length = remaining;
+       
        status = dcerpc_push(&blob_in, mem_ctx, &pkt);
        if (!NT_STATUS_IS_OK(status)) {
                return status;
        }
 
+       /* send the pdu and get the initial response pdu */
        status = dcerpc_raw_packet(p, mem_ctx, &blob_in, &blob_out);
 
        status = dcerpc_pull(&blob_out, mem_ctx, &pkt);
index 7f24f46b91c8ec033ed044edeccb08ef03b51a28..09ddc3625c86cd669c75679a1ae563327cc733b7 100644 (file)
@@ -86,6 +86,7 @@ struct dcerpc_packet {
                } bind;
 
                struct dcerpc_request {
+                       uint32 alloc_hint;
                        uint16 context_id;
                        uint16 opnum;
                        DATA_BLOB stub_data;
@@ -114,6 +115,7 @@ struct dcerpc_packet {
                } bind_nak;
 
                struct dcerpc_response {
+                       uint32 alloc_hint;
                        uint16 context_id;
                        uint8 cancel_count;
                        DATA_BLOB stub_data;
index 834eb1f67813e9a66a6ac8452d8ccdec8f8245c1..1d034c48df604a334922e06a88d3ff9e2e423fa4 100644 (file)
@@ -126,7 +126,7 @@ static BOOL test_sinkdata(struct dcerpc_pipe *p, TALLOC_CTX *mem_ctx)
        int i;
        NTSTATUS status;
        char *data_in;
-       int len = 100;
+       int len = 200000;
 
        printf("\nTesting SinkData\n");
 
@@ -160,11 +160,6 @@ BOOL torture_rpc_echo(int dummy)
                return False;
        }
 
-       if (!test_sourcedata(p, mem_ctx)) {
-               ret = False;
-       }
-       return ret;
-
        if (!test_addone(p, mem_ctx)) {
                ret = False;
        }
index 8dc82242a22e9fe423ed4153b799f9bede9d01b8..bb5741c54f4ecbdb0f2d6bf68e4fd04010d0b03c 100644 (file)
@@ -157,7 +157,8 @@ NTSTATUS torture_rpc_connection(struct dcerpc_pipe **p, const char *pipe_name)
                STD_RIGHT_READ_CONTROL_ACCESS | 
                SA_RIGHT_FILE_WRITE_ATTRIBUTES | 
                SA_RIGHT_FILE_WRITE_EA | 
-               GENERIC_RIGHTS_FILE_READ;
+               GENERIC_RIGHTS_FILE_READ |
+               GENERIC_RIGHTS_FILE_WRITE;
        open_parms.ntcreatex.in.file_attr = 0;
        open_parms.ntcreatex.in.alloc_size = 0;
        open_parms.ntcreatex.in.share_access =