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, &param->rw_mode, &datalen,
210		    &param->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, &param->rw_mode, &datalen,
217		    &param->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	    &param->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