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