diff --git a/source3/smbd/globals.h b/source3/smbd/globals.h index 5809ad76f1e..e2c763bafd3 100644 --- a/source3/smbd/globals.h +++ b/source3/smbd/globals.h @@ -470,6 +470,7 @@ NTSTATUS smbXsrv_open_cleanup(uint64_t persistent_id); struct smbd_smb2_send_queue { struct smbd_smb2_send_queue *prev, *next; + DATA_BLOB *sendfile_header; struct iovec *vector; int count; diff --git a/source3/smbd/smb2_read.c b/source3/smbd/smb2_read.c index 41adb034083..d6d3d908787 100644 --- a/source3/smbd/smb2_read.c +++ b/source3/smbd/smb2_read.c @@ -166,6 +166,7 @@ struct smbd_smb2_read_state { uint32_t in_length; uint64_t in_offset; uint32_t in_minimum; + DATA_BLOB out_headers; DATA_BLOB out_data; uint32_t out_remaining; }; @@ -180,10 +181,10 @@ static int smb2_sendfile_send_data(struct smbd_smb2_read_state *state) ssize_t nread; nread = SMB_VFS_SENDFILE(fsp->conn->sconn->sock, - fsp, - NULL, - in_offset, - in_length); + fsp, + state->smb2req->queue_entry.sendfile_header, + in_offset, + in_length); DEBUG(10,("smb2_sendfile_send_data: SMB_VFS_SENDFILE returned %d on file %s\n", (int)nread, fsp_str_dbg(fsp) )); @@ -301,6 +302,7 @@ static NTSTATUS schedule_smb2_sendfile_read(struct smbd_smb2_request *smb2req, } *state_copy = *state; talloc_set_destructor(state_copy, smb2_sendfile_send_data); + state->smb2req->queue_entry.sendfile_header = &state_copy->out_headers; return NT_STATUS_OK; } diff --git a/source3/smbd/smb2_server.c b/source3/smbd/smb2_server.c index ee5747d227e..a3ed09bbb21 100644 --- a/source3/smbd/smb2_server.c +++ b/source3/smbd/smb2_server.c @@ -2680,7 +2680,7 @@ NTSTATUS smbd_smb2_send_oplock_break(struct smbd_server_connection *sconn, do_encryption = true; } - state = talloc(sconn, struct smbd_smb2_send_oplock_break_state); + state = talloc_zero(sconn, struct smbd_smb2_send_oplock_break_state); if (state == NULL) { return NT_STATUS_NO_MEMORY; } @@ -2983,6 +2983,38 @@ static NTSTATUS smbd_smb2_flush_send_queue(struct smbd_server_connection *sconn) while (sconn->smb2.send_queue != NULL) { struct smbd_smb2_send_queue *e = sconn->smb2.send_queue; + if (e->sendfile_header != NULL) { + size_t size = 0; + size_t i = 0; + uint8_t *buf; + + for (i=0; i < e->count; i++) { + size += e->vector[i].iov_len; + } + + buf = talloc_array(e->mem_ctx, uint8_t, size); + if (buf == NULL) { + return NT_STATUS_NO_MEMORY; + } + + size = 0; + for (i=0; i < e->count; i++) { + memcpy(buf+size, + e->vector[i].iov_base, + e->vector[i].iov_len); + size += e->vector[i].iov_len; + } + + e->sendfile_header->data = buf; + e->sendfile_header->length = size; + e->count = 0; + + sconn->smb2.send_queue_len--; + DLIST_REMOVE(sconn->smb2.send_queue, e); + talloc_free(e->mem_ctx); + continue; + } + ret = writev(sconn->sock, e->vector, e->count); if (ret == 0) { /* propagate end of file */