21
21
#include "includes.h"
22
#include "smbd/smbd.h"
22
23
#include "smbd/globals.h"
23
24
#include "../libcli/smb/smb_common.h"
25
#include "../lib/util/tevent_ntstatus.h"
26
#include "rpc_server/srv_pipe_hnd.h"
25
28
static struct tevent_req *smbd_smb2_write_send(TALLOC_CTX *mem_ctx,
26
29
struct tevent_context *ev,
52
54
struct tevent_req *subreq;
56
status = smbd_smb2_request_verify_sizes(req, 0x31);
57
if (!NT_STATUS_IS_OK(status)) {
58
return smbd_smb2_request_error(req, status);
54
60
inhdr = (const uint8_t *)req->in.vector[i+0].iov_base;
55
if (req->in.vector[i+1].iov_len != (expected_body_size & 0xFFFFFFFE)) {
56
return smbd_smb2_request_error(req, NT_STATUS_INVALID_PARAMETER);
59
61
inbody = (const uint8_t *)req->in.vector[i+1].iov_base;
61
body_size = SVAL(inbody, 0x00);
62
if (body_size != expected_body_size) {
63
return smbd_smb2_request_error(req, NT_STATUS_INVALID_PARAMETER);
66
63
in_smbpid = IVAL(inhdr, SMB2_HDR_PID);
68
65
in_data_offset = SVAL(inbody, 0x02);
72
69
in_file_id_volatile = BVAL(inbody, 0x18);
73
70
in_flags = IVAL(inbody, 0x2C);
75
if (in_data_offset != (SMB2_HDR_BODY + (body_size & 0xFFFFFFFE))) {
72
if (in_data_offset != (SMB2_HDR_BODY + req->in.vector[i+1].iov_len)) {
76
73
return smbd_smb2_request_error(req, NT_STATUS_INVALID_PARAMETER);
83
80
/* check the max write size */
84
if (in_data_length > 0x00010000) {
85
DEBUG(0,("here:%s: 0x%08X: 0x%08X\n",
86
__location__, in_data_length, 0x00010000));
81
if (in_data_length > req->sconn->smb2.max_write) {
82
DEBUG(2,("smbd_smb2_request_process_write : "
83
"client ignored max write :%s: 0x%08X: 0x%08X\n",
84
__location__, in_data_length, req->sconn->smb2.max_write));
87
85
return smbd_smb2_request_error(req, NT_STATUS_INVALID_PARAMETER);
168
166
struct smbd_smb2_write_state {
169
167
struct smbd_smb2_request *smb2req;
170
170
uint32_t in_length;
171
172
uint32_t out_count;
174
175
static void smbd_smb2_write_pipe_done(struct tevent_req *subreq);
177
NTSTATUS smb2_write_complete(struct tevent_req *req, ssize_t nwritten, int err)
180
struct smbd_smb2_write_state *state = tevent_req_data(req,
181
struct smbd_smb2_write_state);
182
files_struct *fsp = state->fsp;
184
DEBUG(3,("smb2: fnum=[%d/%s] "
185
"length=%lu offset=%lu wrote=%lu\n",
188
(unsigned long)state->in_length,
189
(unsigned long)state->in_offset,
190
(unsigned long)nwritten));
192
if (nwritten == -1) {
193
return map_nt_error_from_unix(err);
196
if ((nwritten == 0) && (state->in_length != 0)) {
197
DEBUG(5,("smb2: write [%s] disk full\n",
199
return NT_STATUS_DISK_FULL;
202
status = sync_file(fsp->conn, fsp, state->write_through);
203
if (!NT_STATUS_IS_OK(status)) {
204
DEBUG(5,("smb2: sync_file for %s returned %s\n",
210
state->out_count = nwritten;
176
215
static struct tevent_req *smbd_smb2_write_send(TALLOC_CTX *mem_ctx,
177
216
struct tevent_context *ev,
178
217
struct smbd_smb2_request *smb2req,
183
222
uint32_t in_flags)
186
struct tevent_req *req;
187
struct smbd_smb2_write_state *state;
188
struct smb_request *smbreq;
225
struct tevent_req *req = NULL;
226
struct smbd_smb2_write_state *state = NULL;
227
struct smb_request *smbreq = NULL;
189
228
connection_struct *conn = smb2req->tcon->compat_conn;
229
files_struct *fsp = NULL;
191
230
ssize_t nwritten;
192
bool write_through = false;
193
231
struct lock_struct lock;
195
233
req = tevent_req_create(mem_ctx, &state,
223
264
return tevent_req_post(req, ev);
226
269
if (IS_IPC(smbreq->conn)) {
227
struct tevent_req *subreq;
270
struct tevent_req *subreq = NULL;
229
272
if (!fsp_is_np(fsp)) {
230
273
tevent_req_nterror(req, NT_STATUS_FILE_CLOSED);
249
292
return tevent_req_post(req, ev);
295
/* Try and do an asynchronous write. */
296
status = schedule_aio_smb2_write(conn,
301
state->write_through);
303
if (NT_STATUS_IS_OK(status)) {
305
* Doing an async write. Don't
306
* send a "gone async" message
307
* as we expect this to be less
308
* than the client timeout period.
309
* JRA. FIXME for offline files..
310
* FIXME - add cancel code..
312
smb2req->async = true;
316
if (!NT_STATUS_EQUAL(status, NT_STATUS_RETRY)) {
317
/* Real error in setting up aio. Fail. */
318
tevent_req_nterror(req, NT_STATUS_FILE_CLOSED);
319
return tevent_req_post(req, ev);
322
/* Fallback to synchronous. */
252
323
init_strict_lock_struct(fsp,
269
if (((nwritten == 0) && (in_data.length != 0)) || (nwritten < 0)) {
270
DEBUG(5,("smbd_smb2_write: write_file[%s] disk full\n",
272
SMB_VFS_STRICT_UNLOCK(conn, fsp, &lock);
273
tevent_req_nterror(req, NT_STATUS_DISK_FULL);
274
return tevent_req_post(req, ev);
277
DEBUG(3,("smbd_smb2_write: fnum=[%d/%s] length=%d offset=%d wrote=%d\n",
278
fsp->fnum, fsp_str_dbg(fsp), (int)in_data.length,
279
(int)in_offset, (int)nwritten));
281
if (in_flags & 0x00000001) {
282
write_through = true;
285
status = sync_file(conn, fsp, write_through);
286
if (!NT_STATUS_IS_OK(status)) {
287
DEBUG(5,("smbd_smb2_write: sync_file for %s returned %s\n",
288
fsp_str_dbg(fsp), nt_errstr(status)));
289
SMB_VFS_STRICT_UNLOCK(conn, fsp, &lock);
290
tevent_req_nterror(req, status);
291
return tevent_req_post(req, ev);
340
status = smb2_write_complete(req, nwritten, errno);
294
342
SMB_VFS_STRICT_UNLOCK(conn, fsp, &lock);
296
state->out_count = nwritten;
298
tevent_req_done(req);
344
DEBUG(10,("smb2: write on "
345
"file %s, offset %.0f, requested %u, written = %u\n",
348
(unsigned int)in_data.length,
349
(unsigned int)nwritten ));
351
if (!NT_STATUS_IS_OK(status)) {
352
tevent_req_nterror(req, status);
355
tevent_req_done(req);
299
358
return tevent_req_post(req, ev);