diff options
Diffstat (limited to 'source3')
-rw-r--r-- | source3/smbd/process.c | 74 |
1 files changed, 68 insertions, 6 deletions
diff --git a/source3/smbd/process.c b/source3/smbd/process.c index 5fd3e93325..38682ff2ce 100644 --- a/source3/smbd/process.c +++ b/source3/smbd/process.c @@ -2595,7 +2595,6 @@ struct smbd_echo_state { struct tevent_fd *parent_fde; - struct tevent_fd *read_fde; struct tevent_req *write_req; }; @@ -2828,10 +2827,13 @@ static void smbd_echo_reader(struct tevent_context *ev, smbd_echo_activate_writer(state); } +static void smbd_echo_got_packet(struct tevent_req *req); + static void smbd_echo_loop(struct smbd_server_connection *sconn, int parent_pipe) { struct smbd_echo_state *state; + struct tevent_req *read_req; state = talloc_zero(sconn, struct smbd_echo_state); if (state == NULL) { @@ -2854,14 +2856,14 @@ static void smbd_echo_loop(struct smbd_server_connection *sconn, TALLOC_FREE(state); return; } - state->read_fde = tevent_add_fd(state->ev, state, sconn->sock, - TEVENT_FD_READ, smbd_echo_reader, - state); - if (state->read_fde == NULL) { - DEBUG(1, ("tevent_add_fd failed\n")); + + read_req = smbd_echo_read_send(state, state->ev, sconn); + if (read_req == NULL) { + DEBUG(1, ("smbd_echo_read_send failed\n")); TALLOC_FREE(state); return; } + tevent_req_set_callback(read_req, smbd_echo_got_packet, state); while (true) { if (tevent_loop_once(state->ev) == -1) { @@ -2873,6 +2875,66 @@ static void smbd_echo_loop(struct smbd_server_connection *sconn, TALLOC_FREE(state); } +static void smbd_echo_got_packet(struct tevent_req *req) +{ + struct smbd_echo_state *state = tevent_req_callback_data( + req, struct smbd_echo_state); + NTSTATUS status; + char *buf = NULL; + size_t buflen = 0; + uint32_t seqnum = 0; + bool reply; + + status = smbd_echo_read_recv(req, state, &buf, &buflen, &seqnum); + TALLOC_FREE(req); + if (!NT_STATUS_IS_OK(status)) { + DEBUG(1, ("smbd_echo_read_recv returned %s\n", + nt_errstr(status))); + exit(1); + } + + reply = smbd_echo_reply((uint8_t *)buf, buflen, seqnum); + if (!reply) { + size_t num_pending; + struct iovec *tmp; + struct iovec *iov; + + num_pending = talloc_array_length(state->pending); + tmp = talloc_realloc(state, state->pending, struct iovec, + num_pending+1); + if (tmp == NULL) { + DEBUG(1, ("talloc_realloc failed\n")); + exit(1); + } + state->pending = tmp; + + if (buflen >= smb_size) { + /* + * place the seqnum in the packet so that the main process + * can reply with signing + */ + SIVAL(buf, smb_ss_field, seqnum); + SIVAL(buf, smb_ss_field+4, NT_STATUS_V(NT_STATUS_OK)); + } + + iov = &state->pending[num_pending]; + iov->iov_base = buf; + iov->iov_len = buflen; + + DEBUG(10,("echo_handler[%d]: forward to main\n", + (int)sys_getpid())); + smbd_echo_activate_writer(state); + } + + req = smbd_echo_read_send(state, state->ev, state->sconn); + if (req == NULL) { + DEBUG(1, ("smbd_echo_read_send failed\n")); + exit(1); + } + tevent_req_set_callback(req, smbd_echo_got_packet, state); +} + + /* * Handle SMBecho requests in a forked child process */ |