void named_pipe_packet_process(struct tevent_req *subreq) { struct named_pipe_client *npc = tevent_req_callback_data(subreq, struct named_pipe_client); struct _output_data *out = &npc->p->out_data; DATA_BLOB recv_buffer = data_blob_null; struct ncacn_packet *pkt; NTSTATUS status; uint32_t to_send; size_t i; bool ok; status = dcerpc_read_ncacn_packet_recv(subreq, npc, &pkt, &recv_buffer); TALLOC_FREE(subreq); if (!NT_STATUS_IS_OK(status)) { goto fail; } /* dcerpc_read_ncacn_packet_recv() returns a full PDU */ npc->p->in_data.pdu_needed_len = 0; npc->p->in_data.pdu = recv_buffer; if (dcerpc_get_endian_flag(&recv_buffer) & DCERPC_DREP_LE) { npc->p->endian = RPC_LITTLE_ENDIAN; } else { npc->p->endian = RPC_BIG_ENDIAN; } DEBUG(10, ("PDU is in %s Endian format!\n", npc->p->endian ? "Big" : "Little")); process_complete_pdu(npc->p, pkt); /* reset pipe state and free PDU */ npc->p->in_data.pdu.length = 0; talloc_free(recv_buffer.data); talloc_free(pkt); /* this is needed because of the way DCERPC Binds work in * the RPC marshalling code */ to_send = out->frag.length - out->current_pdu_sent; if (to_send > 0) { npc->iov = talloc_zero(npc, struct iovec); if (!npc->iov) { status = NT_STATUS_NO_MEMORY; goto fail; } npc->count = 1; npc->iov[0].iov_base = out->frag.data + out->current_pdu_sent; npc->iov[0].iov_len = to_send; out->current_pdu_sent += to_send; }
ssize_t process_incoming_data(struct pipes_struct *p, char *data, size_t n) { size_t data_to_copy = MIN(n, RPC_MAX_PDU_FRAG_LEN - p->in_data.pdu.length); DEBUG(10, ("process_incoming_data: Start: pdu.length = %u, " "pdu_needed_len = %u, incoming data = %u\n", (unsigned int)p->in_data.pdu.length, (unsigned int)p->in_data.pdu_needed_len, (unsigned int)n )); if(data_to_copy == 0) { /* * This is an error - data is being received and there is no * space in the PDU. Free the received data and go into the * fault state. */ DEBUG(0, ("process_incoming_data: " "No space in incoming pdu buffer. " "Current size = %u incoming data size = %u\n", (unsigned int)p->in_data.pdu.length, (unsigned int)n)); set_incoming_fault(p); return -1; } /* * If we have no data already, wait until we get at least * a RPC_HEADER_LEN * number of bytes before we can do anything. */ if ((p->in_data.pdu_needed_len == 0) && (p->in_data.pdu.length < RPC_HEADER_LEN)) { /* * Always return here. If we have more data then the RPC_HEADER * will be processed the next time around the loop. */ return fill_rpc_header(p, data, data_to_copy); } /* * At this point we know we have at least an RPC_HEADER_LEN amount of * data stored in p->in_data.pdu. */ /* * If pdu_needed_len is zero this is a new pdu. * Check how much more data we need, then loop again. */ if (p->in_data.pdu_needed_len == 0) { bool ok = get_pdu_size(p); if (!ok) { return -1; } if (p->in_data.pdu_needed_len > 0) { return 0; } /* If rret == 0 and pdu_needed_len == 0 here we have a PDU * that consists of an RPC_HEADER only. This is a * DCERPC_PKT_SHUTDOWN, DCERPC_PKT_CO_CANCEL or * DCERPC_PKT_ORPHANED pdu type. * Deal with this in process_complete_pdu(). */ } /* * Ok - at this point we have a valid RPC_HEADER. * Keep reading until we have a full pdu. */ data_to_copy = MIN(data_to_copy, p->in_data.pdu_needed_len); /* * Copy as much of the data as we need into the p->in_data.pdu buffer. * pdu_needed_len becomes zero when we have a complete pdu. */ memcpy((char *)&p->in_data.pdu.data[p->in_data.pdu.length], data, data_to_copy); p->in_data.pdu.length += data_to_copy; p->in_data.pdu_needed_len -= data_to_copy; /* * Do we have a complete PDU ? * (return the number of bytes handled in the call) */ if(p->in_data.pdu_needed_len == 0) { process_complete_pdu(p); return data_to_copy; } DEBUG(10, ("process_incoming_data: not a complete PDU yet. " "pdu.length = %u, pdu_needed_len = %u\n", (unsigned int)p->in_data.pdu.length, (unsigned int)p->in_data.pdu_needed_len)); return (ssize_t)data_to_copy; }