1 /* 2 * CDDL HEADER START 3 * 4 * The contents of this file are subject to the terms of the 5 * Common Development and Distribution License (the "License"). 6 * You may not use this file except in compliance with the License. 7 * 8 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 9 * or http://www.opensolaris.org/os/licensing. 10 * See the License for the specific language governing permissions 11 * and limitations under the License. 12 * 13 * When distributing Covered Code, include this CDDL HEADER in each 14 * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 15 * If applicable, add the following below this CDDL HEADER, with the 16 * fields enclosed by brackets "[]" replaced with your own identifying 17 * information: Portions Copyright [yyyy] [name of copyright owner] 18 * 19 * CDDL HEADER END 20 */ 21 /* 22 * Copyright 2008 Sun Microsystems, Inc. All rights reserved. 23 * Use is subject to license terms. 24 */ 25 26 /* 27 * SMB: write_raw 28 * 5.27 WRITE_RAW: Write Raw Bytes 29 * 30 * The Write Block Raw protocol is used to maximize the performance of 31 * writing a large block of data from the client to the server. The Write 32 * Block Raw command's scope includes files, Named Pipes, and spooled 33 * output (can be used in place COM_WRITE_PRINT_FILE ). 34 * 35 * Client Request Description 36 * ========================== ========================================= 37 * 38 * UCHAR WordCount; Count of parameter words = 12 39 * USHORT Fid; File handle 40 * USHORT Count; Total bytes, including this buffer 41 * USHORT Reserved; 42 * ULONG Offset; Offset in file to begin write 43 * ULONG Timeout; 44 * USHORT WriteMode; Write mode: 45 * bit 0 - complete write to disk and send 46 * final result response 47 * bit 1 - return Remaining (pipe/dev) 48 * (see WriteAndX for #defines) 49 * ULONG Reserved2; 50 * USHORT DataLength; Number of data bytes this buffer 51 * USHORT DataOffset; Offset (from header start) to data 52 * USHORT ByteCount; Count of data bytes 53 * UCHAR Pad[]; Pad to SHORT or LONG 54 * UCHAR Data[]; Data (# = DataLength) 55 * 56 * First Server Response Description 57 * ============================== ===================================== 58 * 59 * UCHAR WordCount; Count of parameter words = 1 60 * USHORT Remaining; Bytes remaining to be read if pipe 61 * USHORT ByteCount; Count of data bytes = 0 62 * 63 * Final Server Response Description 64 * ================================== ================================= 65 * 66 * UCHAR Command (in SMB header) SMB_COM_WRITE_COMPLETE 67 * 68 * UCHAR WordCount; Count of parameter words = 1 69 * USHORT Count; Total number of bytes written 70 * USHORT ByteCount; Count of data bytes = 0 71 * 72 * The first response format will be that of the final server response in 73 * the case where the server gets an error while writing the data sent 74 * along with the request. Thus Count is the number of bytes which did get 75 * written any time an error is returned. If an error occurs after the 76 * first response has been sent allowing the client to send the remaining 77 * data, the final response should not be sent unless write through is set. 78 * Rather the server should return this "write behind" error on the next 79 * access to the Fid. 80 * 81 * The client must guarantee that there is (and will be) no other request 82 * on the connection for the duration of this request. The server will 83 * reserve enough resources to receive the data and respond with a response 84 * SMB as defined above. The client then sends the raw data in one send. 85 * Thus the server is able to receive up to 65,535 bytes of data directly 86 * into the server buffer. The amount of data transferred is expected to 87 * be larger than the negotiated buffer size for this protocol. 88 * 89 * The reason that no other requests can be active on the connection for 90 * the duration of the request is that if other receives are present on the 91 * connection, there is normally no way to guarantee that the data will be 92 * received into the correct server buffer, rather the data may fill one 93 * (or more) of the other buffers. Also if the client is sending other 94 * requests on the connection, a request may land in the buffer that the 95 * server has allocated for the this SMB's data. 96 * 97 * Whether or not SMB_COM_WRITE_RAW is supported is returned in the 98 * response to SMB_COM_NEGOTIATE. SMB_COM_WRITE_RAW is not supported for 99 * connectionless clients. 100 * 101 * When write through is not specified ((WriteMode & 01) == 0) this SMB is 102 * assumed to be a form of write behind. The transport layer guarantees 103 * delivery of all secondary requests from the client. Thus no "got the 104 * data you sent" SMB is needed. If an error should occur at the server 105 * end, all bytes must be received and thrown away. If an error occurs 106 * while writing data to disk such as disk full, the next access of the 107 * file handle (another write, close, read, etc.) will return the fact that 108 * the error occurred. 109 * 110 * If write through is specified ((WriteMode & 01) != 0), the server will 111 * receive the data, write it to disk and then send a final response 112 * indicating the result of the write. The total number of bytes written 113 * is also returned in this response in the Count field. 114 * 115 * The flow for the SMB_COM_WRITE_RAW SMB is: 116 * 117 * client -----> SMB_COM_WRITE_RAW request (optional data) >-------> server 118 * client <------------------< OK send (more) data <---------------- server 119 * client ----------------------> raw data >----------------------> server 120 * client <---< data on disk or error (write through only) <------- server 121 * 122 * This protocol is set up such that the SMB_COM_WRITE_RAW request may also 123 * carry data. This is an optimization in that up to the server's buffer 124 * size (MaxCount from SMB_COM_NEGOTIATE response), minus the size of the 125 * SMB_COM_WRITE_RAW SMB request, may be sent along with the request. Thus 126 * if the server is busy and unable to support the raw write of the 127 * remaining data, the data sent along with the request has been delivered 128 * and need not be sent again. The server will write any data sent in the 129 * request (and wait for it to be on the disk or device if write through is 130 * set), prior to sending the response. 131 * 132 * The specific responses error class ERRSRV, error codes ERRusempx and 133 * ERRusestd, indicate that the server is temporarily out of the resources 134 * 135 * needed to support the raw write of the remaining data, but that any data 136 * sent along with the request has been successfully written. The client 137 * should then write the remaining data using a different type of SMB write 138 * request, or delay and retry using SMB_COM_WRITE_RAW. If a write error 139 * occurs writing the initial data, it will be returned and the write raw 140 * request is implicitly denied. 141 * 142 * The return field Remaining is returned for named pipes only. It is used 143 * to return the number of bytes currently available in the pipe. This 144 * information can then be used by the client to know when a subsequent 145 * (non blocking) read of the pipe may return some data. Of course when 146 * the read request is actually received by the server there may be more or 147 * less actual data in the pipe (more data has been written to the pipe / 148 * device or another reader drained it). If the information is currently 149 * not available or the request is NOT for a pipe or the server does not 150 * support this feature, a -1 value should be returned. 151 * 152 * If the negotiated dialect is NT LM 0.12 or later, and the response to 153 * the SMB_COM_NEGOTIATE SMB has CAP_LARGE_FILES set in the Capabilities 154 * field, an additional request format is allowed which accommodates very 155 * large files having 64 bit offsets: 156 * 157 * Client Request Description 158 * ================================== ================================= 159 * UCHAR WordCount; Count of parameter words = 14 160 * USHORT Fid; File handle 161 * USHORT Count; Total bytes, including this 162 * buffer 163 * USHORT Reserved; 164 * ULONG Offset; Offset in file to begin write 165 * ULONG Timeout; 166 * USHORT WriteMode; Write mode: 167 * bit 0 - complete write to disk 168 * and send final result response 169 * bit 1 - return Remaining 170 * (pipe/dev) 171 * ULONG Reserved2; 172 * USHORT DataLength; Number of data bytes this buffer 173 * USHORT DataOffset; Offset (from header start) to 174 * data 175 * ULONG OffsetHigh; Upper 32 bits of offset 176 * USHORT ByteCount; Count of data bytes 177 * UCHAR Pad[]; Pad to SHORT or LONG 178 * UCHAR Data[]; Data (# = DataLength) 179 * 180 * In this case the final offset in the file is formed by combining 181 * OffsetHigh and Offset, the resulting offset must not be negative. 182 */ 183 184 #include <sys/sdt.h> 185 #include <smbsrv/smb_incl.h> 186 #include <smbsrv/smb_fsops.h> 187 #include <smbsrv/mbuf.h> 188 #include <smbsrv/netbios.h> 189 190 extern uint32_t smb_keep_alive; 191 192 static int smb_write_raw_helper(smb_request_t *, struct uio *, int, 193 offset_t *, uint32_t *); 194 static int smb_transfer_write_raw_data(smb_request_t *, uint16_t); 195 196 #define WR_MODE_WR_THRU 1 197 198 smb_sdrc_t 199 smb_pre_write_raw(smb_request_t *sr) 200 { 201 int rc = 0; 202 203 DTRACE_SMB_2(op__WriteRaw__start, smb_request_t *, sr, 204 smb_rw_param_t *, sr->arg.rw); 205 206 return ((rc == 0) ? SDRC_SUCCESS : SDRC_ERROR); 207 } 208 209 void 210 smb_post_write_raw(smb_request_t *sr) 211 { 212 DTRACE_SMB_2(op__WriteRaw__done, smb_request_t *, sr, 213 smb_rw_param_t *, sr->arg.rw); 214 } 215 216 smb_sdrc_t 217 smb_com_write_raw(struct smb_request *sr) 218 { 219 int rc = 0; 220 int session_send_rc = 0; 221 unsigned short addl_xfer_count; 222 unsigned short count; 223 unsigned short write_mode, data_offset, data_length; 224 offset_t off; 225 uint32_t off_low, off_high, timeout; 226 uint32_t lcount = 0; 227 uint32_t addl_lcount = 0; 228 struct uio uio; 229 iovec_t iovec; 230 int stability; 231 struct mbuf_chain reply; 232 smb_node_t *fnode; 233 smb_error_t err; 234 235 if (sr->session->s_state != SMB_SESSION_STATE_WRITE_RAW_ACTIVE) 236 return (SDRC_DROP_VC); 237 238 if (sr->smb_wct == 12) { 239 off_high = 0; 240 rc = smbsr_decode_vwv(sr, "ww2.llw4.ww", &sr->smb_fid, &count, 241 &off_low, &timeout, &write_mode, &data_length, 242 &data_offset); 243 data_offset -= 59; 244 } else { 245 rc = smbsr_decode_vwv(sr, "ww2.llw4.wwl", &sr->smb_fid, &count, 246 &off_low, &timeout, &write_mode, &data_length, 247 &data_offset, &off_high); 248 data_offset -= 63; 249 } 250 251 if (rc != 0) 252 return (SDRC_ERROR); 253 254 off = ((offset_t)off_high << 32) | off_low; 255 addl_xfer_count = count - data_length; 256 257 sr->fid_ofile = smb_ofile_lookup_by_fid(sr->tid_tree, sr->smb_fid); 258 if (sr->fid_ofile == NULL) { 259 smbsr_error(sr, NT_STATUS_INVALID_HANDLE, ERRDOS, ERRbadfid); 260 return (SDRC_ERROR); 261 } 262 263 sr->user_cr = smb_ofile_getcred(sr->fid_ofile); 264 265 fnode = sr->fid_ofile->f_node; 266 stability = ((write_mode & WR_MODE_WR_THRU) || 267 (fnode->flags & NODE_FLAGS_WRITE_THROUGH)) ? FSYNC : 0; 268 269 if (STYPE_ISDSK(sr->tid_tree->t_res_type)) { 270 /* 271 * See comments in smb_write.c 272 */ 273 if (fnode->attr.sa_vattr.va_type != VDIR) { 274 rc = smb_lock_range_access(sr, fnode, off, 275 count, B_TRUE); 276 if (rc != NT_STATUS_SUCCESS) { 277 smbsr_error(sr, rc, ERRSRV, ERRaccess); 278 return (SDRC_ERROR); 279 } 280 } 281 } 282 283 /* 284 * Make sure any raw write data that is supposed to be 285 * contained in this SMB is actually present. 286 */ 287 if (sr->smb_data.chain_offset + data_offset + data_length > 288 sr->smb_data.max_bytes) { 289 /* Error handling code will wake up the session daemon */ 290 return (SDRC_ERROR); 291 } 292 293 /* 294 * Init uio (resid will get filled in later) 295 */ 296 uio.uio_iov = &iovec; 297 uio.uio_iovcnt = 1; 298 uio.uio_segflg = UIO_SYSSPACE; 299 uio.uio_loffset = off; 300 301 /* 302 * Send response if there is additional data to transfer. This 303 * will prompt the client to send the remaining data. 304 */ 305 if (addl_xfer_count != 0) { 306 MBC_INIT(&reply, MLEN); 307 (void) smb_mbc_encodef(&reply, SMB_HEADER_ED_FMT "bww", 308 sr->first_smb_com, 309 sr->smb_rcls, 310 sr->smb_reh, 311 sr->smb_err, 312 sr->smb_flg | SMB_FLAGS_REPLY, 313 sr->smb_flg2, 314 sr->smb_pid_high, 315 sr->smb_sig, 316 sr->smb_tid, 317 sr->smb_pid, 318 sr->smb_uid, 319 sr->smb_mid, 1, -1, 0); 320 321 if (sr->session->signing.flags & SMB_SIGNING_ENABLED) 322 smb_sign_reply(sr, &reply); 323 324 session_send_rc = smb_session_send(sr->session, 0, &reply); 325 326 /* 327 * If the session response failed we're not going to 328 * return an error just yet -- we can still write the 329 * data we received along with the SMB even if the 330 * response failed. If it failed, we need to force the 331 * stability level to "write-through". 332 */ 333 stability = (session_send_rc == 0) ? stability : FSYNC; 334 } 335 336 /* 337 * While the response is in flight (and the data begins to arrive) 338 * write out the first data segment. Start by setting up the 339 * iovec list for the first transfer. 340 */ 341 iovec.iov_base = sr->smb_data.chain->m_data + 342 sr->smb_data.chain_offset + data_offset; 343 iovec.iov_len = data_length; 344 uio.uio_resid = data_length; 345 346 /* 347 * smb_write_raw_helper will call smb_opipe_write or 348 * smb_fsop_write as appropriate, handle the NODE_FLAGS_SET_SIZE 349 * flag (if set) and update the other f_node fields. It's possible 350 * that data_length may be 0 for this transfer but we still want 351 * process it since it will update the file state (seek position, 352 * file size (possibly), etc). 353 */ 354 rc = smb_write_raw_helper(sr, &uio, stability, &off, &lcount); 355 356 /* 357 * If our initial session response failed then we're done. Return 358 * failure. The client will know we wrote some of the data because 359 * of the transfer count (count - lcount) in the response. 360 */ 361 if (session_send_rc != 0) { 362 sr->smb_rcls = ERRSRV; 363 sr->smb_err = ERRusestd; 364 goto write_raw_transfer_failed; 365 } 366 367 /* 368 * If we have more data to read then go get it 369 */ 370 if (addl_xfer_count) { 371 /* 372 * This is the only place where a worker thread should 373 * directly read from the session socket. If the data 374 * is read successfully then the buffer (sr->sr_raw_data_buf) 375 * will need to be freed after the data is written. 376 */ 377 if (smb_transfer_write_raw_data(sr, addl_xfer_count) != 0) { 378 /* 379 * Raw data transfer failed 380 */ 381 goto write_raw_transfer_failed; 382 } 383 384 /* 385 * Fill in next iov entry 386 */ 387 iovec.iov_base = sr->sr_raw_data_buf; 388 iovec.iov_len = addl_xfer_count; 389 uio.uio_resid = addl_xfer_count; 390 } 391 392 /* 393 * Wake up session daemon since we now have all of our data and 394 * it's safe for the session daemon to resume processing SMB's. 395 */ 396 sr->session->s_write_raw_status = 0; 397 sr->session->s_state = SMB_SESSION_STATE_NEGOTIATED; 398 399 /* 400 * If we didn't write all the data from the first segment then 401 * there's not much point in continuing (we still wanted to 402 * read any additional data above since we don't necessarily 403 * want to drop the connection and we need to read through 404 * to the next SMB). 405 */ 406 if ((rc != 0) || (lcount != data_length)) { 407 goto notify_write_raw_complete; 408 } 409 410 /* 411 * Write any additional data 412 */ 413 if (addl_xfer_count) { 414 rc = smb_write_raw_helper(sr, &uio, stability, &off, 415 &addl_lcount); 416 } 417 418 /* 419 * If we were called in "Write-behind" mode ((write_mode & 1) == 0) 420 * and the transfer was successful then we don't need to send 421 * any further response. If we were called in "Write-Through" mode 422 * ((write_mode & 1) == 1) or if the transfer failed we need to 423 * send a completion notification. The "count" value will indicate 424 * whether the transfer was successful. 425 */ 426 if ((rc != 0) || (write_mode & WR_MODE_WR_THRU) || 427 (lcount + addl_lcount != count)) { 428 goto notify_write_raw_complete; 429 } 430 431 /* 432 * Free raw write buffer (allocated in smb_transfer_write_raw_data) 433 */ 434 kmem_free(sr->sr_raw_data_buf, sr->sr_raw_data_length); 435 436 (void) smb_session_send(sr->session, SESSION_KEEP_ALIVE, NULL); 437 return (SDRC_NO_REPLY); 438 439 write_raw_transfer_failed: 440 /* 441 * Raw data transfer failed, wake up session 442 * daemon 443 */ 444 sr->session->s_write_raw_status = 20; 445 sr->session->s_state = SMB_SESSION_STATE_NEGOTIATED; 446 447 notify_write_raw_complete: 448 /* 449 * If we had an error fill in the appropriate error code 450 */ 451 if (rc != 0) { 452 smbsr_map_errno(rc, &err); 453 smbsr_set_error(sr, &err); 454 } 455 456 /* 457 * Free raw write buffer if present (from smb_transfer_write_raw_data) 458 */ 459 if (sr->sr_raw_data_buf != NULL) { 460 kmem_free(sr->sr_raw_data_buf, sr->sr_raw_data_length); 461 } 462 /* Write complete notification */ 463 sr->first_smb_com = SMB_COM_WRITE_COMPLETE; 464 rc = smbsr_encode_result(sr, 1, 0, "bww", 1, 465 count - (lcount + addl_lcount), 0); 466 return ((rc == 0) ? SDRC_SUCCESS : SDRC_ERROR); 467 } 468 469 470 471 /* 472 * smb_write_raw_helper 473 * 474 * This function will call smb_opipe_write or smb_fsop_write as appropriate, 475 * handle the NODE_FLAGS_SET_SIZE flag (if set) and update the other f_node 476 * fields. It's possible that data_length may be 0 for this transfer but 477 * we still want process it since it will update the file state (seek 478 * position, file size (possibly), etc). 479 * 480 * Returns 0 for success, non-zero for failure 481 */ 482 static int 483 smb_write_raw_helper(struct smb_request *sr, struct uio *uiop, 484 int stability, offset_t *offp, uint32_t *lcountp) 485 { 486 smb_node_t *fnode; 487 int rc = 0; 488 489 if (STYPE_ISIPC(sr->tid_tree->t_res_type)) { 490 *lcountp = uiop->uio_resid; 491 492 if ((rc = smb_opipe_write(sr, uiop)) != 0) 493 *lcountp = 0; 494 } else { 495 fnode = sr->fid_ofile->f_node; 496 rc = smb_fsop_write(sr, sr->user_cr, fnode, 497 uiop, lcountp, &fnode->attr, stability); 498 499 if (rc == 0) { 500 501 fnode->flags |= NODE_FLAGS_SYNCATIME; 502 503 if (fnode->flags & NODE_FLAGS_SET_SIZE) { 504 if ((*offp + *lcountp) >= fnode->n_size) { 505 fnode->flags &= ~NODE_FLAGS_SET_SIZE; 506 fnode->n_size = *offp + *lcountp; 507 } 508 } 509 } 510 } 511 512 *offp += *lcountp; 513 mutex_enter(&sr->fid_ofile->f_mutex); 514 sr->fid_ofile->f_seek_pos = *offp; 515 mutex_exit(&sr->fid_ofile->f_mutex); 516 517 return (rc); 518 } 519 520 521 /* 522 * smb_handle_write_raw 523 * 524 * Called from smb_session_daemon() when the SMB command is SMB_COM_WRITE_RAW. 525 * Dispatches the command to the worker thread and waits until the worker 526 * has completed processing the command. 527 * 528 * Returns 0 for success, non-zero for failure 529 */ 530 int 531 smb_handle_write_raw(smb_session_t *session, smb_request_t *sr) 532 { 533 int drop_reason = 0; 534 535 /* 536 * Set flag to indicate that we are waiting for raw data. The 537 * worker thread will actually retrieve the raw data directly 538 * from the socket. This should be the only case when a worker 539 * thread reads from the session socket. When the data is read 540 * the worker will clear the flag. 541 */ 542 smb_rwx_rwenter(&session->s_lock, RW_WRITER); 543 switch (session->s_state) { 544 case SMB_SESSION_STATE_NEGOTIATED: 545 case SMB_SESSION_STATE_OPLOCK_BREAKING: 546 session->s_state = SMB_SESSION_STATE_WRITE_RAW_ACTIVE; 547 smb_rwx_rwexit(&session->s_lock); 548 sr->sr_state = SMB_REQ_STATE_SUBMITTED; 549 (void) taskq_dispatch(session->s_server->sv_thread_pool, 550 smb_session_worker, sr, TQ_SLEEP); 551 smb_rwx_rwenter(&session->s_lock, RW_READER); 552 while (session->s_state == SMB_SESSION_STATE_WRITE_RAW_ACTIVE) { 553 (void) smb_rwx_rwwait(&session->s_lock, -1); 554 } 555 drop_reason = session->s_write_raw_status; 556 break; 557 default: 558 drop_reason = 21; 559 break; 560 } 561 smb_rwx_rwexit(&session->s_lock); 562 return (drop_reason); 563 } 564 565 /* 566 * smb_transfer_write_raw_data 567 * 568 * Handles the second transfer phase of SMB_COM_WRITE_RAW. smb_com_write_raw() 569 * will process the parameters and data from the SMB and send the initial 570 * SMB response. This function reads the remaining data from the socket 571 * as it arrives from the client. 572 * 573 * Clients may send KEEP_ALIVE messages (when using NBT) between the first 574 * and second parts of write raw requests. The only session transport 575 * types accepted here are SESSION_MESSAGE or SESSION_KEEP_ALIVE. 576 * 577 * Returns 0 for success, non-zero for failure 578 */ 579 int 580 smb_transfer_write_raw_data(smb_request_t *sr, uint16_t addl_xfer_count) 581 { 582 smb_session_t *session = sr->session; 583 smb_xprt_t hdr; 584 uint8_t *data_buf; 585 586 do { 587 if (smb_session_xprt_gethdr(session, &hdr) != 0) 588 return (-1); 589 590 if ((hdr.xh_type == SESSION_MESSAGE) || 591 (hdr.xh_type == SESSION_KEEP_ALIVE)) { 592 session->keep_alive = smb_keep_alive; 593 } else { 594 return (-1); 595 } 596 } while (hdr.xh_type == SESSION_KEEP_ALIVE); 597 598 if (hdr.xh_length < addl_xfer_count) { 599 /* 600 * Less data than we were expecting. 601 */ 602 return (-1); 603 } 604 605 data_buf = kmem_alloc(hdr.xh_length, KM_SLEEP); 606 607 if (smb_sorecv(session->sock, data_buf, hdr.xh_length) != 0) { 608 kmem_free(data_buf, hdr.xh_length); 609 sr->sr_raw_data_buf = NULL; 610 sr->sr_raw_data_length = 0; 611 return (-1); 612 } 613 614 sr->sr_raw_data_buf = data_buf; 615 sr->sr_raw_data_length = hdr.xh_length; 616 return (0); 617 } 618