summaryrefslogtreecommitdiffstats
path: root/source4
diff options
context:
space:
mode:
authorAndrew Tridgell <tridge@samba.org>2003-12-12 05:01:41 +0000
committerAndrew Tridgell <tridge@samba.org>2003-12-12 05:01:41 +0000
commitdab0deae833d1180f61e7d4112966990d4c19600 (patch)
treea0d396b8c8687c085271bd5eeeca13c89e3d33ea /source4
parent869df3adbd02f8a151e54c3216155163979b99fe (diff)
added handling of fragmented requests in the rpc server
now we just need to handle fragmented replies .... (This used to be commit 14005c95d7c6c68f7da0f1ad7b7d7952a04a125b)
Diffstat (limited to 'source4')
-rw-r--r--source4/rpc_server/dcerpc_server.c71
-rw-r--r--source4/rpc_server/rpc_echo.c4
2 files changed, 67 insertions, 8 deletions
diff --git a/source4/rpc_server/dcerpc_server.c b/source4/rpc_server/dcerpc_server.c
index f5e7ff858e..0ee5fad3fc 100644
--- a/source4/rpc_server/dcerpc_server.c
+++ b/source4/rpc_server/dcerpc_server.c
@@ -37,6 +37,19 @@ static const struct dcesrv_endpoint_ops *find_endpoint(struct server_context *sm
return NULL;
}
+/*
+ find a call that is pending in our call list
+*/
+static struct dcesrv_call_state *dcesrv_find_call(struct dcesrv_state *dce, uint16 call_id)
+{
+ struct dcesrv_call_state *c;
+ for (c=dce->call_list;c;c=c->next) {
+ if (c->pkt.call_id == call_id) {
+ return c;
+ }
+ }
+ return NULL;
+}
/*
register an endpoint server
@@ -248,11 +261,6 @@ static NTSTATUS dcesrv_request(struct dcesrv_call_state *call)
DATA_BLOB stub;
struct dcerpc_packet pkt;
- if (call->pkt.pfc_flags != (DCERPC_PFC_FLAG_FIRST | DCERPC_PFC_FLAG_LAST)) {
- /* we don't do fragments in the server yet */
- return dcesrv_fault(call, DCERPC_FAULT_TODO);
- }
-
opnum = call->pkt.u.request.opnum;
if (opnum >= call->dce->ndr->num_calls) {
@@ -349,6 +357,7 @@ NTSTATUS dcesrv_input(struct dcesrv_state *dce, const DATA_BLOB *data)
}
call->mem_ctx = mem_ctx;
call->dce = dce;
+ call->data = data_blob(NULL, 0);
ndr = ndr_pull_init_blob(data, mem_ctx);
if (!ndr) {
@@ -362,10 +371,56 @@ NTSTATUS dcesrv_input(struct dcesrv_state *dce, const DATA_BLOB *data)
return status;
}
- /* TODO: at this point we should see if the packet is a
- continuation of an existing call, but I'm too lazy for that
- right now ... maybe tomorrow */
+ /* see if this is a continued packet */
+ if (!(call->pkt.pfc_flags & DCERPC_PFC_FLAG_FIRST)) {
+ struct dcesrv_call_state *call2 = call;
+ uint32 alloc_size;
+
+ /* we only allow fragmented requests, no other packet types */
+ if (call->pkt.ptype != DCERPC_PKT_REQUEST) {
+ return dcesrv_fault(call2, DCERPC_FAULT_TODO);
+ }
+
+ /* this is a continuation of an existing call - find the call then
+ tack it on the end */
+ call = dcesrv_find_call(dce, call2->pkt.call_id);
+ if (!call) {
+ return dcesrv_fault(call2, DCERPC_FAULT_TODO);
+ }
+
+ if (call->pkt.ptype != call2->pkt.ptype) {
+ /* trying to play silly buggers are we? */
+ return dcesrv_fault(call2, DCERPC_FAULT_TODO);
+ }
+
+ alloc_size = call->pkt.u.request.stub_and_verifier.length +
+ call2->pkt.u.request.stub_and_verifier.length;
+ if (call->pkt.u.request.alloc_hint > alloc_size) {
+ alloc_size = call->pkt.u.request.alloc_hint;
+ }
+
+ call->pkt.u.request.stub_and_verifier.data =
+ talloc_realloc(call->mem_ctx,
+ call->pkt.u.request.stub_and_verifier.data, alloc_size);
+ if (!call->pkt.u.request.stub_and_verifier.data) {
+ return dcesrv_fault(call2, DCERPC_FAULT_TODO);
+ }
+ memcpy(call->pkt.u.request.stub_and_verifier.data +
+ call->pkt.u.request.stub_and_verifier.length,
+ call2->pkt.u.request.stub_and_verifier.data,
+ call2->pkt.u.request.stub_and_verifier.length);
+ call->pkt.u.request.stub_and_verifier.length +=
+ call2->pkt.u.request.stub_and_verifier.length;
+
+ call->pkt.pfc_flags |= (call2->pkt.pfc_flags & DCERPC_PFC_FLAG_LAST);
+ }
+ /* this may not be the last pdu in the chain - if its isn't then
+ just put it on the call_list and wait for the rest */
+ if (!(call->pkt.pfc_flags & DCERPC_PFC_FLAG_LAST)) {
+ DLIST_ADD_END(dce->call_list, call, struct dcesrv_call_state *);
+ return NT_STATUS_OK;
+ }
switch (call->pkt.ptype) {
case DCERPC_PKT_BIND:
diff --git a/source4/rpc_server/rpc_echo.c b/source4/rpc_server/rpc_echo.c
index d003f34ce4..37e7dd5bb8 100644
--- a/source4/rpc_server/rpc_echo.c
+++ b/source4/rpc_server/rpc_echo.c
@@ -31,6 +31,10 @@ static NTSTATUS echo_AddOne(struct dcesrv_state *dce, TALLOC_CTX *mem_ctx, struc
static NTSTATUS echo_EchoData(struct dcesrv_state *dce, TALLOC_CTX *mem_ctx, struct echo_EchoData *r)
{
+ r->out.out_data = talloc(mem_ctx, r->in.len);
+ if (!r->out.out_data) {
+ return NT_STATUS_NO_MEMORY;
+ }
memcpy(r->out.out_data, r->in.in_data, r->in.len);
return NT_STATUS_OK;