const struct GUID *object;
uint16_t opnum;
DATA_BLOB request_data;
- bool request_data_allocated;
+ bool request_data_can_append;
struct tevent_req *stub_subreq;
bool ignore_timeout;
bool wait_for_sync;
}
struct dcerpc_bh_raw_call_in_state {
-
+ uint8_t dummy;
};
static struct tevent_req *dcerpc_bh_raw_call_in_send(TALLOC_CTX *mem_ctx,
struct dcerpc_bh_raw_call_state *raw_call_state = NULL;
struct tevent_req *req;
struct dcerpc_bh_raw_call_in_state *state;
+ struct rpc_request *rpcreq = NULL;
+ DATA_BLOB *b = NULL;
+ bool ok;
req = tevent_req_create(mem_ctx, &state,
struct dcerpc_bh_raw_call_in_state);
raw_call_state = tevent_req_data(raw_call_req,
struct dcerpc_bh_raw_call_state);
-
- struct rpc_request *subreq;
-
- return req;
+ if (raw_call_state->subreq == NULL) {
+ tevent_req_nterror(req, NT_STATUS_RPC_CALL_FAILED);
+ return tevent_req_post(req, ev);
+ }
+
+ rpcreq = raw_call_state->subreq;
+
+ if (rpcreq->state != RPC_REQUEST_QUEUED) {
+ tevent_req_nterror(req, NT_STATUS_RPC_INVALID_PIPE_OPERATION);
+ return tevent_req_post(req, ev);
+ }
+
+ if (!(in_flags & LIBNDR_FLAG_INCOMPLETE_BUFFER)) {
+ rpcreq->incomplete_request_data = false;
+ }
+
+ b = &rpcreq->request_data;
+
+ if (in_length == 0) {
+ if (in_flags & LIBNDR_FLAG_INCOMPLETE_BUFFER) {
+ /*
+ * with LIBNDR_FLAG_INCOMPLETE_BUFFER
+ * we need to make sure we make any progress...
+ */
+ tevent_req_nterror(req, NT_STATUS_RPC_INVALID_PIPE_OPERATION);
+ return tevent_req_post(req, ev);
+ }
+
+ /*
+ * nothing to add
+ */
+ } else if (rpcreq->request_data_can_append) {
+ ok = data_blob_append(rpcreq, b, in_data, in_length);
+ if (!ok) {
+ tevent_req_nomem(NULL, req);
+ return tevent_req_post(req, ev);
+ }
+ } else {
+ *b = data_blob_talloc(rpcreq, b->data, b->length);
+ if (tevent_req_nomem(b->data, req)) {
+ return tevent_req_post(req, ev);
+ }
+ rpcreq->request_data_can_append = true;
+ ok = data_blob_append(rpcreq, b, in_data, in_length);
+ if (!ok) {
+ tevent_req_nomem(NULL, req);
+ return tevent_req_post(req, ev);
+ }
+ }
+
+ dcerpc_schedule_io_trigger(rpcreq->p->conn);
+
+ if (b->length > (rpcreq->p->conn->srv_max_xmit_frag * 10)) {
+ rpcreq->stub_subreq = req;
+ //TODO
+ return req;
+ }
+
+ tevent_req_done(req);
+ return tevent_req_post(req, ev);
}
-static NTSTATUS dcerpc_bh_raw_call_in__recv(struct tevent_req *req)
+static NTSTATUS dcerpc_bh_raw_call_in_recv(struct tevent_req *req)
{
-
+ return tevent_req_simple_recv_ntstatus(req);
}
struct dcerpc_bh_disconnect_state {
goto req_done;
}
- if (pkt->pfc_flags & DCERPC_PFC_FLAG_FIRST)) {
+ if (pkt->pfc_flags & DCERPC_PFC_FLAG_FIRST) {
if (req->first_pdu_done) {
req->status = NT_STATUS_RPC_PROTOCOL_ERROR;
goto req_done;
}
req->opnum = opnum;
- req->request_data.length = stub_data->length;
- req->request_data.data = stub_data->data;
+
+ if (stub_data->length > 0) {
+ req->request_data.length = stub_data->length;
+ req->request_data.data = stub_data->data;
+ } else {
+ req->request_data_can_append = true;
+ }
status = dcerpc_request_prepare_vt(req);
if (!NT_STATUS_IS_OK(status)) {
size_t sig_size = 0;
bool need_async = false;
bool can_async = true;
+ bool current_pdus_done = false;
req = c->request_queue;
if (req == NULL) {
need_async = true;
}
+ remaining = stub_data->length;
+
+ if ((remaining == 0) && req->incomplete_request_data) {
+ /*
+ * we're waiting for more data
+ */
+ return;
+ }
+
if (c->security_state.auth_level >= DCERPC_AUTH_LEVEL_PACKET) {
can_async = gensec_have_feature(c->security_state.generic_state,
GENSEC_FEATURE_ASYNC_REPLIES);
init_ncacn_hdr(p->conn, &pkt);
- remaining = stub_data->length;
-
/* we can write a full max_recv_frag size, minus the dcerpc
request header size */
chunk_size = p->conn->srv_max_recv_frag;
}
/* we send a series of pdus without waiting for a reply */
- while (remaining > 0 || !req->first_pdu_done) {
+ while (!current_pdus_done) {
uint32_t chunk = MIN(chunk_size, remaining);
bool last_frag = false;
bool do_trans = false;
}
remaining -= chunk;
+ if (remaining == 0) {
+ current_pdus_done = true;
+ }
req->last_pdu_done = last_frag;
}
- if (req->request_data_allocated) {
+ if (req->request_data_can_append) {
+ /*
+ * request_data_can_append means the blob
+ * is a talloc child of req
+ */
data_blob_free(&req->request_data);
}
- req->request_data_allocated = false;
+ req->request_data_can_append = true;
req->request_data = data_blob_null;
if (req->last_pdu_done) {
req->last_pdu_done = false;
}
- if (req->stub_subreq == NULL) {
+ if (req->stub_subreq != NULL) {
+ struct tevent_req *stub_subreq = req->stub_subreq;
+
+ req->stub_subreq = NULL;
+
+ tevent_req_done(stub_subreq);
return;
}
- tevent_req_done(req->stub_subreq);
return;
}