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 (c) 2007, 2010, Oracle and/or its affiliates. All rights reserved. 23 */ 24 25/* 26 * SMB: write_raw 27 * 5.27 WRITE_RAW: Write Raw Bytes 28 * 29 * The Write Block Raw protocol is used to maximize the performance of 30 * writing a large block of data from the client to the server. The Write 31 * Block Raw command's scope includes files, Named Pipes, and spooled 32 * output (can be used in place COM_WRITE_PRINT_FILE ). 33 * 34 * Client Request Description 35 * ========================== ========================================= 36 * 37 * UCHAR WordCount; Count of parameter words = 12 38 * USHORT Fid; File handle 39 * USHORT Count; Total bytes, including this buffer 40 * USHORT Reserved; 41 * ULONG Offset; Offset in file to begin write 42 * ULONG Timeout; 43 * USHORT WriteMode; Write mode: 44 * bit 0 - complete write to disk and send 45 * final result response 46 * bit 1 - return Remaining (pipe/dev) 47 * (see WriteAndX for #defines) 48 * ULONG Reserved2; 49 * USHORT DataLength; Number of data bytes this buffer 50 * USHORT DataOffset; Offset (from header start) to data 51 * USHORT ByteCount; Count of data bytes 52 * UCHAR Pad[]; Pad to SHORT or LONG 53 * UCHAR Data[]; Data (# = DataLength) 54 * 55 * First Server Response Description 56 * ============================== ===================================== 57 * 58 * UCHAR WordCount; Count of parameter words = 1 59 * USHORT Remaining; Bytes remaining to be read if pipe 60 * USHORT ByteCount; Count of data bytes = 0 61 * 62 * Final Server Response Description 63 * ================================== ================================= 64 * 65 * UCHAR Command (in SMB header) SMB_COM_WRITE_COMPLETE 66 * 67 * UCHAR WordCount; Count of parameter words = 1 68 * USHORT Count; Total number of bytes written 69 * USHORT ByteCount; Count of data bytes = 0 70 * 71 * The first response format will be that of the final server response in 72 * the case where the server gets an error while writing the data sent 73 * along with the request. Thus Count is the number of bytes which did get 74 * written any time an error is returned. If an error occurs after the 75 * first response has been sent allowing the client to send the remaining 76 * data, the final response should not be sent unless write through is set. 77 * Rather the server should return this "write behind" error on the next 78 * access to the Fid. 79 * 80 * The client must guarantee that there is (and will be) no other request 81 * on the connection for the duration of this request. The server will 82 * reserve enough resources to receive the data and respond with a response 83 * SMB as defined above. The client then sends the raw data in one send. 84 * Thus the server is able to receive up to 65,535 bytes of data directly 85 * into the server buffer. The amount of data transferred is expected to 86 * be larger than the negotiated buffer size for this protocol. 87 * 88 * The reason that no other requests can be active on the connection for 89 * the duration of the request is that if other receives are present on the 90 * connection, there is normally no way to guarantee that the data will be 91 * received into the correct server buffer, rather the data may fill one 92 * (or more) of the other buffers. Also if the client is sending other 93 * requests on the connection, a request may land in the buffer that the 94 * server has allocated for the this SMB's data. 95 * 96 * Whether or not SMB_COM_WRITE_RAW is supported is returned in the 97 * response to SMB_COM_NEGOTIATE. SMB_COM_WRITE_RAW is not supported for 98 * connectionless clients. 99 * 100 * When write through is not specified ((WriteMode & 01) == 0) this SMB is 101 * assumed to be a form of write behind. The transport layer guarantees 102 * delivery of all secondary requests from the client. Thus no "got the 103 * data you sent" SMB is needed. If an error should occur at the server 104 * end, all bytes must be received and thrown away. If an error occurs 105 * while writing data to disk such as disk full, the next access of the 106 * file handle (another write, close, read, etc.) will return the fact that 107 * the error occurred. 108 * 109 * If write through is specified ((WriteMode & 01) != 0), the server will 110 * receive the data, write it to disk and then send a final response 111 * indicating the result of the write. The total number of bytes written 112 * is also returned in this response in the Count field. 113 * 114 * The flow for the SMB_COM_WRITE_RAW SMB is: 115 * 116 * client -----> SMB_COM_WRITE_RAW request (optional data) >-------> server 117 * client <------------------< OK send (more) data <---------------- server 118 * client ----------------------> raw data >----------------------> server 119 * client <---< data on disk or error (write through only) <------- server 120 * 121 * This protocol is set up such that the SMB_COM_WRITE_RAW request may also 122 * carry data. This is an optimization in that up to the server's buffer 123 * size (MaxCount from SMB_COM_NEGOTIATE response), minus the size of the 124 * SMB_COM_WRITE_RAW SMB request, may be sent along with the request. Thus 125 * if the server is busy and unable to support the raw write of the 126 * remaining data, the data sent along with the request has been delivered 127 * and need not be sent again. The server will write any data sent in the 128 * request (and wait for it to be on the disk or device if write through is 129 * set), prior to sending the response. 130 * 131 * The specific responses error class ERRSRV, error codes ERRusempx and 132 * ERRusestd, indicate that the server is temporarily out of the resources 133 * 134 * needed to support the raw write of the remaining data, but that any data 135 * sent along with the request has been successfully written. The client 136 * should then write the remaining data using a different type of SMB write 137 * request, or delay and retry using SMB_COM_WRITE_RAW. If a write error 138 * occurs writing the initial data, it will be returned and the write raw 139 * request is implicitly denied. 140 * 141 * The return field Remaining is returned for named pipes only. It is used 142 * to return the number of bytes currently available in the pipe. This 143 * information can then be used by the client to know when a subsequent 144 * (non blocking) read of the pipe may return some data. Of course when 145 * the read request is actually received by the server there may be more or 146 * less actual data in the pipe (more data has been written to the pipe / 147 * device or another reader drained it). If the information is currently 148 * not available or the request is NOT for a pipe or the server does not 149 * support this feature, a -1 value should be returned. 150 * 151 * If the negotiated dialect is NT LM 0.12 or later, and the response to 152 * the SMB_COM_NEGOTIATE SMB has CAP_LARGE_FILES set in the Capabilities 153 * field, an additional request format is allowed which accommodates very 154 * large files having 64 bit offsets: 155 * 156 * Client Request Description 157 * ================================== ================================= 158 * UCHAR WordCount; Count of parameter words = 14 159 * USHORT Fid; File handle 160 * USHORT Count; Total bytes, including this 161 * buffer 162 * USHORT Reserved; 163 * ULONG Offset; Offset in file to begin write 164 * ULONG Timeout; 165 * USHORT WriteMode; Write mode: 166 * bit 0 - complete write to disk 167 * and send final result response 168 * bit 1 - return Remaining 169 * (pipe/dev) 170 * ULONG Reserved2; 171 * USHORT DataLength; Number of data bytes this buffer 172 * USHORT DataOffset; Offset (from header start) to 173 * data 174 * ULONG OffsetHigh; Upper 32 bits of offset 175 * USHORT ByteCount; Count of data bytes 176 * UCHAR Pad[]; Pad to SHORT or LONG 177 * UCHAR Data[]; Data (# = DataLength) 178 * 179 * In this case the final offset in the file is formed by combining 180 * OffsetHigh and Offset, the resulting offset must not be negative. 181 */ 182 183#include <sys/sdt.h> 184#include <smbsrv/smb_kproto.h> 185#include <smbsrv/smb_fsops.h> 186#include <smbsrv/netbios.h> 187 188extern uint32_t smb_keep_alive; 189 190static int smb_transfer_write_raw_data(smb_request_t *, smb_rw_param_t *); 191 192smb_sdrc_t 193smb_pre_write_raw(smb_request_t *sr) 194{ 195 smb_rw_param_t *param; 196 uint32_t off_low; 197 uint32_t timeout; 198 uint32_t off_high; 199 uint16_t datalen; 200 uint16_t total; 201 int rc; 202 203 param = smb_srm_zalloc(sr, sizeof (smb_rw_param_t)); 204 sr->arg.rw = param; 205 param->rw_magic = SMB_RW_MAGIC; 206 207 if (sr->smb_wct == 12) { 208 rc = smbsr_decode_vwv(sr, "ww2.llw4.ww", &sr->smb_fid, &total, 209 &off_low, &timeout, ¶m->rw_mode, &datalen, 210 ¶m->rw_dsoff); 211 212 param->rw_offset = (uint64_t)off_low; 213 param->rw_dsoff -= 59; 214 } else { 215 rc = smbsr_decode_vwv(sr, "ww2.llw4.wwl", &sr->smb_fid, &total, 216 &off_low, &timeout, ¶m->rw_mode, &datalen, 217 ¶m->rw_dsoff, &off_high); 218 219 param->rw_offset = ((uint64_t)off_high << 32) | off_low; 220 param->rw_dsoff -= 63; 221 } 222 223 param->rw_count = (uint32_t)datalen; 224 param->rw_total = (uint32_t)total; 225 param->rw_vdb.vdb_uio.uio_loffset = (offset_t)param->rw_offset; 226 227 DTRACE_SMB_2(op__WriteRaw__start, smb_request_t *, sr, 228 smb_rw_param_t *, sr->arg.rw); 229 230 smb_rwx_rwenter(&sr->session->s_lock, RW_WRITER); 231 232 return ((rc == 0) ? SDRC_SUCCESS : SDRC_ERROR); 233} 234 235void 236smb_post_write_raw(smb_request_t *sr) 237{ 238 DTRACE_SMB_2(op__WriteRaw__done, smb_request_t *, sr, 239 smb_rw_param_t *, sr->arg.rw); 240 241 smb_rwx_rwexit(&sr->session->s_lock); 242} 243 244smb_sdrc_t 245smb_com_write_raw(struct smb_request *sr) 246{ 247 smb_rw_param_t *param = sr->arg.rw; 248 int rc = 0; 249 int session_send_rc = 0; 250 uint16_t addl_xfer_count; 251 offset_t addl_xfer_offset; 252 struct mbuf_chain reply; 253 smb_error_t err; 254 255 if (sr->session->s_state != SMB_SESSION_STATE_WRITE_RAW_ACTIVE) 256 return (SDRC_DROP_VC); 257 258 if (!smb_raw_mode) { 259 smbsr_error(sr, NT_STATUS_NOT_SUPPORTED, ERRDOS, 260 ERROR_NOT_SUPPORTED); 261 return (SDRC_ERROR); 262 } 263 264 smbsr_lookup_file(sr); 265 if (sr->fid_ofile == NULL) { 266 smbsr_error(sr, NT_STATUS_INVALID_HANDLE, ERRDOS, ERRbadfid); 267 return (SDRC_ERROR); 268 } 269 270 sr->user_cr = smb_ofile_getcred(sr->fid_ofile); 271 272 /* 273 * Send response if there is additional data to transfer. 274 * This will prompt the client to send the remaining data. 275 */ 276 addl_xfer_count = param->rw_total - param->rw_count; 277 addl_xfer_offset = param->rw_count; 278 279 if (addl_xfer_count != 0) { 280 MBC_INIT(&reply, MLEN); 281 (void) smb_mbc_encodef(&reply, SMB_HEADER_ED_FMT "bww", 282 sr->first_smb_com, 283 sr->smb_rcls, 284 sr->smb_reh, 285 sr->smb_err, 286 sr->smb_flg | SMB_FLAGS_REPLY, 287 sr->smb_flg2, 288 sr->smb_pid_high, 289 sr->smb_sig, 290 sr->smb_tid, 291 sr->smb_pid, 292 sr->smb_uid, 293 sr->smb_mid, 1, -1, 0); 294 295 if (sr->session->signing.flags & SMB_SIGNING_ENABLED) 296 smb_sign_reply(sr, &reply); 297 298 session_send_rc = smb_session_send(sr->session, 0, &reply); 299 300 /* 301 * If the response failed, force write-through and 302 * complete the write before dealing with the error. 303 */ 304 if (session_send_rc != 0) 305 param->rw_mode = SMB_WRMODE_WRITE_THRU; 306 } 307 308 /* 309 * While the response is in flight (and the data begins to arrive) 310 * write out the first data segment. 311 */ 312 if (smbsr_decode_data(sr, "#.#B", param->rw_dsoff, param->rw_count, 313 ¶m->rw_vdb) != 0) 314 return (SDRC_ERROR); 315 316 if (param->rw_count > 0) 317 rc = smb_common_write(sr, param); 318 319 if (session_send_rc != 0) { 320 sr->smb_rcls = ERRSRV; 321 sr->smb_err = ERRusestd; 322 goto write_raw_transfer_failed; 323 } 324 325 /* 326 * If we have more data to read then go get it 327 */ 328 if (addl_xfer_count > 0) { 329 /* 330 * This is the only place where a worker thread should 331 * directly read from the session socket. If the data 332 * is read successfully then the buffer (sr->sr_raw_data_buf) 333 * will need to be freed after the data is written. 334 */ 335 param->rw_offset += addl_xfer_offset; 336 param->rw_vdb.vdb_uio.uio_loffset = param->rw_offset; 337 param->rw_vdb.vdb_iovec[0].iov_len = addl_xfer_count; 338 param->rw_vdb.vdb_uio.uio_resid = addl_xfer_count; 339 if (smb_transfer_write_raw_data(sr, param) != 0) 340 goto write_raw_transfer_failed; 341 } 342 343 /* 344 * Wake up session daemon since we now have all of our data and 345 * it's safe for the session daemon to resume processing SMB's. 346 */ 347 sr->session->s_write_raw_status = 0; 348 sr->session->s_state = SMB_SESSION_STATE_NEGOTIATED; 349 350 /* 351 * If we didn't write all the data from the first segment then 352 * there's not much point in continuing (we still wanted to 353 * read any additional data above since we don't necessarily 354 * want to drop the connection and we need to read through 355 * to the next SMB). 356 */ 357 if (rc != 0) 358 goto notify_write_raw_complete; 359 360 /* 361 * Write any additional data 362 */ 363 if (addl_xfer_count > 0) { 364 rc = smb_common_write(sr, param); 365 addl_xfer_offset += param->rw_count; 366 } 367 368 /* 369 * If we were called in "Write-behind" mode and the transfer was 370 * successful then we don't need to send any further response. 371 * If we were called in "Write-Through" mode or if the transfer 372 * failed we need to send a completion notification. The "count" 373 * value will indicate whether the transfer was successful. 374 */ 375 if ((rc != 0) || SMB_WRMODE_IS_STABLE(param->rw_mode)) 376 goto notify_write_raw_complete; 377 378 (void) smb_session_send(sr->session, SESSION_KEEP_ALIVE, NULL); 379 return (SDRC_NO_REPLY); 380 381write_raw_transfer_failed: 382 /* 383 * Raw data transfer failed, wake up session daemon 384 */ 385 sr->session->s_write_raw_status = 20; 386 sr->session->s_state = SMB_SESSION_STATE_NEGOTIATED; 387 388notify_write_raw_complete: 389 /* 390 * If we had an error fill in the appropriate error code 391 */ 392 if (rc != 0) { 393 smbsr_map_errno(rc, &err); 394 smbsr_set_error(sr, &err); 395 } 396 397 sr->first_smb_com = SMB_COM_WRITE_COMPLETE; 398 rc = smbsr_encode_result(sr, 1, 0, "bww", 1, addl_xfer_offset, 0); 399 return ((rc == 0) ? SDRC_SUCCESS : SDRC_ERROR); 400} 401 402/* 403 * smb_handle_write_raw 404 * 405 * Called from smb_session_daemon() when the SMB command is SMB_COM_WRITE_RAW. 406 * Dispatches the command to the worker thread and waits until the worker 407 * has completed processing the command. 408 * 409 * Returns 0 for success, non-zero for failure 410 */ 411int 412smb_handle_write_raw(smb_session_t *session, smb_request_t *sr) 413{ 414 int drop_reason = 0; 415 416 /* 417 * Set flag to indicate that we are waiting for raw data. The 418 * worker thread will actually retrieve the raw data directly 419 * from the socket. This should be the only case when a worker 420 * thread reads from the session socket. When the data is read 421 * the worker will clear the flag. 422 */ 423 smb_rwx_rwenter(&session->s_lock, RW_WRITER); 424 switch (session->s_state) { 425 case SMB_SESSION_STATE_NEGOTIATED: 426 case SMB_SESSION_STATE_OPLOCK_BREAKING: 427 session->s_state = SMB_SESSION_STATE_WRITE_RAW_ACTIVE; 428 smb_rwx_rwexit(&session->s_lock); 429 smb_srqueue_waitq_enter(session->s_srqueue); 430 sr->sr_state = SMB_REQ_STATE_SUBMITTED; 431 (void) taskq_dispatch(session->s_server->sv_worker_pool, 432 smb_session_worker, sr, TQ_SLEEP); 433 smb_rwx_rwenter(&session->s_lock, RW_READER); 434 while (session->s_state == SMB_SESSION_STATE_WRITE_RAW_ACTIVE) { 435 (void) smb_rwx_rwwait(&session->s_lock, -1); 436 } 437 drop_reason = session->s_write_raw_status; 438 break; 439 default: 440 drop_reason = 21; 441 break; 442 } 443 smb_rwx_rwexit(&session->s_lock); 444 return (drop_reason); 445} 446 447/* 448 * smb_transfer_write_raw_data 449 * 450 * Handles the second transfer phase of SMB_COM_WRITE_RAW. smb_com_write_raw() 451 * will process the parameters and data from the SMB and send the initial 452 * SMB response. This function reads the remaining data from the socket 453 * as it arrives from the client. 454 * 455 * Clients may send KEEP_ALIVE messages (when using NBT) between the first 456 * and second parts of write raw requests. The only session transport 457 * types accepted here are SESSION_MESSAGE or SESSION_KEEP_ALIVE. 458 * 459 * Returns 0 for success, non-zero for failure 460 */ 461int 462smb_transfer_write_raw_data(smb_request_t *sr, smb_rw_param_t *param) 463{ 464 smb_session_t *session = sr->session; 465 smb_xprt_t hdr; 466 void *pbuf; 467 468 do { 469 if (smb_session_xprt_gethdr(session, &hdr) != 0) 470 return (-1); 471 472 if ((hdr.xh_type == SESSION_MESSAGE) || 473 (hdr.xh_type == SESSION_KEEP_ALIVE)) { 474 session->keep_alive = smb_keep_alive; 475 } else { 476 return (-1); 477 } 478 } while (hdr.xh_type == SESSION_KEEP_ALIVE); 479 480 if (hdr.xh_length < param->rw_vdb.vdb_uio.uio_resid) 481 return (-1); /* Less data than we were expecting. */ 482 483 pbuf = smb_srm_alloc(sr, hdr.xh_length); 484 if (smb_sorecv(session->sock, pbuf, hdr.xh_length) != 0) 485 return (-1); 486 487 param->rw_vdb.vdb_iovec[0].iov_base = pbuf; 488 param->rw_vdb.vdb_uio.uio_iovcnt = 1; 489 param->rw_vdb.vdb_uio.uio_segflg = UIO_SYSSPACE; 490 param->rw_vdb.vdb_uio.uio_extflg = UIO_COPY_DEFAULT; 491 return (0); 492} 493