44 * server encountered a resource issue.
45 */
46 smb_sdrc_t
47 smb_pre_write(smb_request_t *sr)
48 {
49 smb_rw_param_t *param;
50 uint32_t off;
51 uint16_t count;
52 int rc;
53
54 param = kmem_zalloc(sizeof (smb_rw_param_t), KM_SLEEP);
55 sr->arg.rw = param;
56 param->rw_magic = SMB_RW_MAGIC;
57
58 rc = smbsr_decode_vwv(sr, "wwl", &sr->smb_fid, &count, &off);
59
60 param->rw_count = (uint32_t)count;
61 param->rw_offset = (uint64_t)off;
62 param->rw_vdb.vdb_uio.uio_loffset = (offset_t)param->rw_offset;
63
64 DTRACE_SMB_2(op__Write__start, smb_request_t *, sr,
65 smb_rw_param_t *, param);
66
67 return ((rc == 0) ? SDRC_SUCCESS : SDRC_ERROR);
68 }
69
70 void
71 smb_post_write(smb_request_t *sr)
72 {
73 DTRACE_SMB_2(op__Write__done, smb_request_t *, sr,
74 smb_rw_param_t *, sr->arg.rw);
75
76 kmem_free(sr->arg.rw, sizeof (smb_rw_param_t));
77 }
78
79 smb_sdrc_t
80 smb_com_write(smb_request_t *sr)
81 {
82 smb_rw_param_t *param = sr->arg.rw;
83 int rc;
84
85 smbsr_lookup_file(sr);
86 if (sr->fid_ofile == NULL) {
87 smbsr_error(sr, NT_STATUS_INVALID_HANDLE, ERRDOS, ERRbadfid);
88 return (SDRC_ERROR);
89 }
90
91 sr->user_cr = smb_ofile_getcred(sr->fid_ofile);
92
93 if (param->rw_count == 0) {
94 rc = smb_write_truncate(sr, param);
134 smb_rw_param_t *param;
135 uint32_t off;
136 uint16_t count;
137 int rc;
138
139 param = kmem_zalloc(sizeof (smb_rw_param_t), KM_SLEEP);
140 sr->arg.rw = param;
141 param->rw_magic = SMB_RW_MAGIC;
142
143 if (sr->smb_wct == 12) {
144 rc = smbsr_decode_vwv(sr, "wwll12.", &sr->smb_fid,
145 &count, &off, ¶m->rw_last_write);
146 } else {
147 rc = smbsr_decode_vwv(sr, "wwll", &sr->smb_fid,
148 &count, &off, ¶m->rw_last_write);
149 }
150
151 param->rw_count = (uint32_t)count;
152 param->rw_offset = (uint64_t)off;
153
154 DTRACE_SMB_2(op__WriteAndClose__start, smb_request_t *, sr,
155 smb_rw_param_t *, param);
156
157 return ((rc == 0) ? SDRC_SUCCESS : SDRC_ERROR);
158 }
159
160 void
161 smb_post_write_and_close(smb_request_t *sr)
162 {
163 DTRACE_SMB_2(op__WriteAndClose__done, smb_request_t *, sr,
164 smb_rw_param_t *, sr->arg.rw);
165
166 kmem_free(sr->arg.rw, sizeof (smb_rw_param_t));
167 }
168
169 smb_sdrc_t
170 smb_com_write_and_close(smb_request_t *sr)
171 {
172 smb_rw_param_t *param = sr->arg.rw;
173 uint16_t count;
174 int rc = 0;
175
176 smbsr_lookup_file(sr);
177 if (sr->fid_ofile == NULL) {
178 smbsr_error(sr, NT_STATUS_INVALID_HANDLE, ERRDOS, ERRbadfid);
179 return (SDRC_ERROR);
180 }
181
182 sr->user_cr = smb_ofile_getcred(sr->fid_ofile);
183
184 if (param->rw_count == 0) {
232 * server encountered a resource issue.
233 */
234 smb_sdrc_t
235 smb_pre_write_and_unlock(smb_request_t *sr)
236 {
237 smb_rw_param_t *param;
238 uint32_t off;
239 uint16_t count;
240 uint16_t remcnt;
241 int rc;
242
243 param = kmem_zalloc(sizeof (smb_rw_param_t), KM_SLEEP);
244 sr->arg.rw = param;
245 param->rw_magic = SMB_RW_MAGIC;
246
247 rc = smbsr_decode_vwv(sr, "wwlw", &sr->smb_fid, &count, &off, &remcnt);
248
249 param->rw_count = (uint32_t)count;
250 param->rw_offset = (uint64_t)off;
251
252 DTRACE_SMB_2(op__WriteAndUnlock__start, smb_request_t *, sr,
253 smb_rw_param_t *, param);
254
255 return ((rc == 0) ? SDRC_SUCCESS : SDRC_ERROR);
256 }
257
258 void
259 smb_post_write_and_unlock(smb_request_t *sr)
260 {
261 DTRACE_SMB_2(op__WriteAndUnlock__done, smb_request_t *, sr,
262 smb_rw_param_t *, sr->arg.rw);
263
264 kmem_free(sr->arg.rw, sizeof (smb_rw_param_t));
265 }
266
267 smb_sdrc_t
268 smb_com_write_and_unlock(smb_request_t *sr)
269 {
270 smb_rw_param_t *param = sr->arg.rw;
271 uint32_t lk_pid;
272 uint32_t status;
273 int rc = 0;
274
275 if (STYPE_ISDSK(sr->tid_tree->t_res_type) == 0) {
276 smbsr_error(sr, NT_STATUS_ACCESS_DENIED, ERRDOS, ERRnoaccess);
277 return (SDRC_ERROR);
278 }
279
280 smbsr_lookup_file(sr);
281 if (sr->fid_ofile == NULL) {
282 smbsr_error(sr, NT_STATUS_INVALID_HANDLE, ERRDOS, ERRbadfid);
308 }
309
310
311 /* Note: SMB1 locking uses 16-bit PIDs. */
312 lk_pid = sr->smb_pid & 0xFFFF;
313
314 status = smb_unlock_range(sr, param->rw_offset,
315 (uint64_t)param->rw_count, lk_pid);
316 if (status != NT_STATUS_SUCCESS) {
317 smbsr_error(sr, NT_STATUS_RANGE_NOT_LOCKED,
318 ERRDOS, ERROR_NOT_LOCKED);
319 return (SDRC_ERROR);
320 }
321
322 rc = smbsr_encode_result(sr, 1, 0, "bww", 1,
323 (uint16_t)param->rw_count, 0);
324 return ((rc == 0) ? SDRC_SUCCESS : SDRC_ERROR);
325 }
326
327 /*
328 * Write bytes to a file (SMB Core). This request was extended in
329 * LM 0.12 to support 64-bit offsets, indicated by sending a wct of
330 * 14, instead of 12, and including additional offset information.
331 *
332 * A ByteCount of 0 does not truncate the file - use SMB_COM_WRITE
333 * to truncate a file. A zero length merely transfers zero bytes.
334 *
335 * If bit 0 of WriteMode is set, Fid must refer to a disk file and
336 * the data must be on stable storage before responding.
337 *
338 * MS-SMB 3.3.5.8 update to LM 0.12 4.2.5:
339 * If CAP_LARGE_WRITEX is set, the byte count may be larger than the
340 * negotiated buffer size and the server is expected to write the
341 * number of bytes specified.
342 */
343 smb_sdrc_t
344 smb_pre_write_andx(smb_request_t *sr)
345 {
346 smb_rw_param_t *param;
347 uint32_t off_low;
370
371 if (param->rw_dsoff >= 59)
372 param->rw_dsoff -= 59;
373 param->rw_offset = (uint64_t)off_low;
374 /* off_high not present */
375 } else {
376 rc = -1;
377 }
378
379 param->rw_count = (uint32_t)datalen_low;
380
381 /*
382 * Work-around a Win7 bug, where it fails to set the
383 * CAP_LARGE_WRITEX flag during session setup. Assume
384 * a large write if the data remaining is >= 64k.
385 */
386 if ((sr->session->capabilities & CAP_LARGE_WRITEX) != 0 ||
387 (sr->smb_data.max_bytes > (sr->smb_data.chain_offset + 0xFFFF)))
388 param->rw_count |= ((uint32_t)datalen_high << 16);
389
390 DTRACE_SMB_2(op__WriteX__start, smb_request_t *, sr,
391 smb_rw_param_t *, param);
392
393 return ((rc == 0) ? SDRC_SUCCESS : SDRC_ERROR);
394 }
395
396 void
397 smb_post_write_andx(smb_request_t *sr)
398 {
399 DTRACE_SMB_2(op__WriteX__done, smb_request_t *, sr,
400 smb_rw_param_t *, sr->arg.rw);
401
402 kmem_free(sr->arg.rw, sizeof (smb_rw_param_t));
403 }
404
405 smb_sdrc_t
406 smb_com_write_andx(smb_request_t *sr)
407 {
408 smb_rw_param_t *param = sr->arg.rw;
409 uint16_t count_high;
410 uint16_t count_low;
411 int rc;
412
413 ASSERT(param);
414 ASSERT(param->rw_magic == SMB_RW_MAGIC);
415
416 smbsr_lookup_file(sr);
417 if (sr->fid_ofile == NULL) {
418 smbsr_error(sr, NT_STATUS_INVALID_HANDLE, ERRDOS, ERRbadfid);
419 return (SDRC_ERROR);
420 }
|
44 * server encountered a resource issue.
45 */
46 smb_sdrc_t
47 smb_pre_write(smb_request_t *sr)
48 {
49 smb_rw_param_t *param;
50 uint32_t off;
51 uint16_t count;
52 int rc;
53
54 param = kmem_zalloc(sizeof (smb_rw_param_t), KM_SLEEP);
55 sr->arg.rw = param;
56 param->rw_magic = SMB_RW_MAGIC;
57
58 rc = smbsr_decode_vwv(sr, "wwl", &sr->smb_fid, &count, &off);
59
60 param->rw_count = (uint32_t)count;
61 param->rw_offset = (uint64_t)off;
62 param->rw_vdb.vdb_uio.uio_loffset = (offset_t)param->rw_offset;
63
64 DTRACE_SMB_1(op__Write__start, smb_request_t *, sr); /* arg.rw */
65
66 return ((rc == 0) ? SDRC_SUCCESS : SDRC_ERROR);
67 }
68
69 void
70 smb_post_write(smb_request_t *sr)
71 {
72 DTRACE_SMB_1(op__Write__done, smb_request_t *, sr); /* arg.rw */
73
74 kmem_free(sr->arg.rw, sizeof (smb_rw_param_t));
75 }
76
77 smb_sdrc_t
78 smb_com_write(smb_request_t *sr)
79 {
80 smb_rw_param_t *param = sr->arg.rw;
81 int rc;
82
83 smbsr_lookup_file(sr);
84 if (sr->fid_ofile == NULL) {
85 smbsr_error(sr, NT_STATUS_INVALID_HANDLE, ERRDOS, ERRbadfid);
86 return (SDRC_ERROR);
87 }
88
89 sr->user_cr = smb_ofile_getcred(sr->fid_ofile);
90
91 if (param->rw_count == 0) {
92 rc = smb_write_truncate(sr, param);
132 smb_rw_param_t *param;
133 uint32_t off;
134 uint16_t count;
135 int rc;
136
137 param = kmem_zalloc(sizeof (smb_rw_param_t), KM_SLEEP);
138 sr->arg.rw = param;
139 param->rw_magic = SMB_RW_MAGIC;
140
141 if (sr->smb_wct == 12) {
142 rc = smbsr_decode_vwv(sr, "wwll12.", &sr->smb_fid,
143 &count, &off, ¶m->rw_last_write);
144 } else {
145 rc = smbsr_decode_vwv(sr, "wwll", &sr->smb_fid,
146 &count, &off, ¶m->rw_last_write);
147 }
148
149 param->rw_count = (uint32_t)count;
150 param->rw_offset = (uint64_t)off;
151
152 DTRACE_SMB_1(op__WriteAndClose__start, smb_request_t *, sr); /* arg.rw */
153
154 return ((rc == 0) ? SDRC_SUCCESS : SDRC_ERROR);
155 }
156
157 void
158 smb_post_write_and_close(smb_request_t *sr)
159 {
160 DTRACE_SMB_1(op__WriteAndClose__done, smb_request_t *, sr); /* arg.rw */
161
162 kmem_free(sr->arg.rw, sizeof (smb_rw_param_t));
163 }
164
165 smb_sdrc_t
166 smb_com_write_and_close(smb_request_t *sr)
167 {
168 smb_rw_param_t *param = sr->arg.rw;
169 uint16_t count;
170 int rc = 0;
171
172 smbsr_lookup_file(sr);
173 if (sr->fid_ofile == NULL) {
174 smbsr_error(sr, NT_STATUS_INVALID_HANDLE, ERRDOS, ERRbadfid);
175 return (SDRC_ERROR);
176 }
177
178 sr->user_cr = smb_ofile_getcred(sr->fid_ofile);
179
180 if (param->rw_count == 0) {
228 * server encountered a resource issue.
229 */
230 smb_sdrc_t
231 smb_pre_write_and_unlock(smb_request_t *sr)
232 {
233 smb_rw_param_t *param;
234 uint32_t off;
235 uint16_t count;
236 uint16_t remcnt;
237 int rc;
238
239 param = kmem_zalloc(sizeof (smb_rw_param_t), KM_SLEEP);
240 sr->arg.rw = param;
241 param->rw_magic = SMB_RW_MAGIC;
242
243 rc = smbsr_decode_vwv(sr, "wwlw", &sr->smb_fid, &count, &off, &remcnt);
244
245 param->rw_count = (uint32_t)count;
246 param->rw_offset = (uint64_t)off;
247
248 DTRACE_SMB_1(op__WriteAndUnlock__start, smb_request_t *, sr); /* arg.rw */
249
250 return ((rc == 0) ? SDRC_SUCCESS : SDRC_ERROR);
251 }
252
253 void
254 smb_post_write_and_unlock(smb_request_t *sr)
255 {
256 DTRACE_SMB_1(op__WriteAndUnlock__done, smb_request_t *, sr); /* arg.rw */
257
258 kmem_free(sr->arg.rw, sizeof (smb_rw_param_t));
259 }
260
261 smb_sdrc_t
262 smb_com_write_and_unlock(smb_request_t *sr)
263 {
264 smb_rw_param_t *param = sr->arg.rw;
265 uint32_t lk_pid;
266 uint32_t status;
267 int rc = 0;
268
269 if (STYPE_ISDSK(sr->tid_tree->t_res_type) == 0) {
270 smbsr_error(sr, NT_STATUS_ACCESS_DENIED, ERRDOS, ERRnoaccess);
271 return (SDRC_ERROR);
272 }
273
274 smbsr_lookup_file(sr);
275 if (sr->fid_ofile == NULL) {
276 smbsr_error(sr, NT_STATUS_INVALID_HANDLE, ERRDOS, ERRbadfid);
302 }
303
304
305 /* Note: SMB1 locking uses 16-bit PIDs. */
306 lk_pid = sr->smb_pid & 0xFFFF;
307
308 status = smb_unlock_range(sr, param->rw_offset,
309 (uint64_t)param->rw_count, lk_pid);
310 if (status != NT_STATUS_SUCCESS) {
311 smbsr_error(sr, NT_STATUS_RANGE_NOT_LOCKED,
312 ERRDOS, ERROR_NOT_LOCKED);
313 return (SDRC_ERROR);
314 }
315
316 rc = smbsr_encode_result(sr, 1, 0, "bww", 1,
317 (uint16_t)param->rw_count, 0);
318 return ((rc == 0) ? SDRC_SUCCESS : SDRC_ERROR);
319 }
320
321 /*
322 * The SMB_COM_WRITE_RAW protocol was a negotiated option introduced in
323 * SMB Core Plus to maximize performance when writing a large block
324 * of data to a server. It's obsolete and no longer supported.
325 *
326 * We keep a handler for it so the dtrace provider can see if
327 * the client tried to use this command.
328 */
329 smb_sdrc_t
330 smb_pre_write_raw(smb_request_t *sr)
331 {
332 smb_rw_param_t *param;
333 uint32_t off_low;
334 uint32_t timeout;
335 uint32_t off_high;
336 uint16_t datalen;
337 uint16_t total;
338 int rc;
339
340 param = kmem_zalloc(sizeof (smb_rw_param_t), KM_SLEEP);
341 sr->arg.rw = param;
342
343 if (sr->smb_wct == 12) {
344 rc = smbsr_decode_vwv(sr, "ww2.llw4.ww", &sr->smb_fid, &total,
345 &off_low, &timeout, ¶m->rw_mode, &datalen,
346 ¶m->rw_dsoff);
347
348 param->rw_offset = (uint64_t)off_low;
349 } else {
350 rc = smbsr_decode_vwv(sr, "ww2.llw4.wwl", &sr->smb_fid, &total,
351 &off_low, &timeout, ¶m->rw_mode, &datalen,
352 ¶m->rw_dsoff, &off_high);
353
354 param->rw_offset = ((uint64_t)off_high << 32) | off_low;
355 }
356
357 param->rw_count = (uint32_t)datalen;
358 param->rw_total = (uint32_t)total;
359
360 DTRACE_SMB_1(op__WriteRaw__start, smb_request_t *, sr); /* arg.rw */
361
362 return ((rc == 0) ? SDRC_SUCCESS : SDRC_ERROR);
363 }
364
365 void
366 smb_post_write_raw(smb_request_t *sr)
367 {
368 DTRACE_SMB_1(op__WriteRaw__done, smb_request_t *, sr); /* arg.rw */
369
370 kmem_free(sr->arg.rw, sizeof (smb_rw_param_t));
371 }
372
373 smb_sdrc_t
374 smb_com_write_raw(struct smb_request *sr)
375 {
376 smbsr_error(sr, NT_STATUS_NOT_SUPPORTED, ERRDOS,
377 ERROR_NOT_SUPPORTED);
378 return (SDRC_ERROR);
379 }
380
381 /*
382 * Write bytes to a file (SMB Core). This request was extended in
383 * LM 0.12 to support 64-bit offsets, indicated by sending a wct of
384 * 14, instead of 12, and including additional offset information.
385 *
386 * A ByteCount of 0 does not truncate the file - use SMB_COM_WRITE
387 * to truncate a file. A zero length merely transfers zero bytes.
388 *
389 * If bit 0 of WriteMode is set, Fid must refer to a disk file and
390 * the data must be on stable storage before responding.
391 *
392 * MS-SMB 3.3.5.8 update to LM 0.12 4.2.5:
393 * If CAP_LARGE_WRITEX is set, the byte count may be larger than the
394 * negotiated buffer size and the server is expected to write the
395 * number of bytes specified.
396 */
397 smb_sdrc_t
398 smb_pre_write_andx(smb_request_t *sr)
399 {
400 smb_rw_param_t *param;
401 uint32_t off_low;
424
425 if (param->rw_dsoff >= 59)
426 param->rw_dsoff -= 59;
427 param->rw_offset = (uint64_t)off_low;
428 /* off_high not present */
429 } else {
430 rc = -1;
431 }
432
433 param->rw_count = (uint32_t)datalen_low;
434
435 /*
436 * Work-around a Win7 bug, where it fails to set the
437 * CAP_LARGE_WRITEX flag during session setup. Assume
438 * a large write if the data remaining is >= 64k.
439 */
440 if ((sr->session->capabilities & CAP_LARGE_WRITEX) != 0 ||
441 (sr->smb_data.max_bytes > (sr->smb_data.chain_offset + 0xFFFF)))
442 param->rw_count |= ((uint32_t)datalen_high << 16);
443
444 DTRACE_SMB_1(op__WriteX__start, smb_request_t *, sr); /* arg.rw */
445
446 return ((rc == 0) ? SDRC_SUCCESS : SDRC_ERROR);
447 }
448
449 void
450 smb_post_write_andx(smb_request_t *sr)
451 {
452 DTRACE_SMB_1(op__WriteX__done, smb_request_t *, sr); /* arg.rw */
453
454 kmem_free(sr->arg.rw, sizeof (smb_rw_param_t));
455 }
456
457 smb_sdrc_t
458 smb_com_write_andx(smb_request_t *sr)
459 {
460 smb_rw_param_t *param = sr->arg.rw;
461 uint16_t count_high;
462 uint16_t count_low;
463 int rc;
464
465 ASSERT(param);
466 ASSERT(param->rw_magic == SMB_RW_MAGIC);
467
468 smbsr_lookup_file(sr);
469 if (sr->fid_ofile == NULL) {
470 smbsr_error(sr, NT_STATUS_INVALID_HANDLE, ERRDOS, ERRbadfid);
471 return (SDRC_ERROR);
472 }
|