xref: /illumos-gate/usr/src/uts/common/fs/smbsrv/smb_session.c (revision 80bd8a585c4ef2f19c09c9c4379635e411c91fe6)
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  * Copyright 2018 Nexenta Systems, Inc.  All rights reserved.
24  */
25 
26 #include <sys/atomic.h>
27 #include <sys/synch.h>
28 #include <sys/types.h>
29 #include <sys/sdt.h>
30 #include <sys/random.h>
31 #include <smbsrv/netbios.h>
32 #include <smbsrv/smb2_kproto.h>
33 #include <smbsrv/string.h>
34 #include <netinet/tcp.h>
35 
36 /* How many iovec we'll handle as a local array (no allocation) */
37 #define	SMB_LOCAL_IOV_MAX	16
38 
39 #define	SMB_NEW_KID()	atomic_inc_64_nv(&smb_kids)
40 
41 static volatile uint64_t smb_kids;
42 
43 /*
44  * We track the keepalive in minutes, but this constant
45  * specifies it in seconds, so convert to minutes.
46  */
47 uint32_t smb_keep_alive = SMB_PI_KEEP_ALIVE_MIN / 60;
48 
49 /*
50  * There are many smbtorture test cases that send
51  * racing requests, and where the tests fail if we
52  * don't execute them in exactly the order sent.
53  * These are test bugs.  The protocol makes no
54  * guarantees about execution order of requests
55  * that are concurrently active.
56  *
57  * Nonetheless, smbtorture has many useful tests,
58  * so we have this work-around we can enable to
59  * basically force sequential execution.  When
60  * enabled, insert a delay after each request is
61  * issued a taskq job.  Enable this with mdb by
62  * setting smb_reader_delay to 10.  Don't make it
63  * more than 500 or so or the server will appear
64  * to be so slow that tests may time out.
65  */
66 int smb_reader_delay = 0;  /* mSec. */
67 
68 static int  smbsr_newrq_initial(smb_request_t *);
69 
70 static void smb_session_cancel(smb_session_t *);
71 static int smb_session_reader(smb_session_t *);
72 static int smb_session_xprt_puthdr(smb_session_t *,
73     uint8_t msg_type, uint32_t msg_len,
74     uint8_t *dst, size_t dstlen);
75 static smb_tree_t *smb_session_get_tree(smb_session_t *, smb_tree_t *);
76 static void smb_session_logoff(smb_session_t *);
77 static void smb_request_init_command_mbuf(smb_request_t *sr);
78 static void smb_session_genkey(smb_session_t *);
79 
80 void
81 smb_session_timers(smb_llist_t *ll)
82 {
83 	smb_session_t	*session;
84 
85 	smb_llist_enter(ll, RW_READER);
86 	session = smb_llist_head(ll);
87 	while (session != NULL) {
88 		/*
89 		 * Walk through the table and decrement each keep_alive
90 		 * timer that has not timed out yet. (keepalive > 0)
91 		 */
92 		SMB_SESSION_VALID(session);
93 		if (session->keep_alive &&
94 		    (session->keep_alive != (uint32_t)-1))
95 			session->keep_alive--;
96 		session = smb_llist_next(ll, session);
97 	}
98 	smb_llist_exit(ll);
99 }
100 
101 void
102 smb_session_correct_keep_alive_values(smb_llist_t *ll, uint32_t new_keep_alive)
103 {
104 	smb_session_t		*sn;
105 
106 	/*
107 	 * Caller specifies seconds, but we track in minutes, so
108 	 * convert to minutes (rounded up).
109 	 */
110 	new_keep_alive = (new_keep_alive + 59) / 60;
111 
112 	if (new_keep_alive == smb_keep_alive)
113 		return;
114 	/*
115 	 * keep alive == 0 means do not drop connection if it's idle
116 	 */
117 	smb_keep_alive = (new_keep_alive) ? new_keep_alive : -1;
118 
119 	/*
120 	 * Walk through the table and set each session to the new keep_alive
121 	 * value if they have not already timed out.  Block clock interrupts.
122 	 */
123 	smb_llist_enter(ll, RW_READER);
124 	sn = smb_llist_head(ll);
125 	while (sn != NULL) {
126 		SMB_SESSION_VALID(sn);
127 		if (sn->keep_alive != 0)
128 			sn->keep_alive = new_keep_alive;
129 		sn = smb_llist_next(ll, sn);
130 	}
131 	smb_llist_exit(ll);
132 }
133 
134 /*
135  * Send a session message - supports SMB-over-NBT and SMB-over-TCP.
136  * If an mbuf chain is provided (optional), it will be freed and
137  * set to NULL -- unconditionally!  (error or not)
138  *
139  * Builds a I/O vector (uio/iov) to do the send from mbufs, plus one
140  * segment for the 4-byte NBT header.
141  */
142 int
143 smb_session_send(smb_session_t *session, uint8_t nbt_type, mbuf_chain_t *mbc)
144 {
145 	uio_t		uio;
146 	iovec_t		local_iov[SMB_LOCAL_IOV_MAX];
147 	iovec_t		*alloc_iov = NULL;
148 	int		alloc_sz = 0;
149 	mbuf_t		*m;
150 	uint8_t		nbt_hdr[NETBIOS_HDR_SZ];
151 	uint32_t	nbt_len;
152 	int		i, nseg;
153 	int		rc;
154 
155 	switch (session->s_state) {
156 	case SMB_SESSION_STATE_DISCONNECTED:
157 	case SMB_SESSION_STATE_TERMINATED:
158 		rc = ENOTCONN;
159 		goto out;
160 	default:
161 		break;
162 	}
163 
164 	/*
165 	 * Setup the IOV.  First, count the number of IOV segments
166 	 * (plus one for the NBT header) and decide whether we
167 	 * need to allocate an iovec or can use local_iov;
168 	 */
169 	bzero(&uio, sizeof (uio));
170 	nseg = 1;
171 	m = (mbc != NULL) ? mbc->chain : NULL;
172 	while (m != NULL) {
173 		nseg++;
174 		m = m->m_next;
175 	}
176 	if (nseg <= SMB_LOCAL_IOV_MAX) {
177 		uio.uio_iov = local_iov;
178 	} else {
179 		alloc_sz = nseg * sizeof (iovec_t);
180 		alloc_iov = kmem_alloc(alloc_sz, KM_SLEEP);
181 		uio.uio_iov = alloc_iov;
182 	}
183 	uio.uio_iovcnt = nseg;
184 	uio.uio_segflg = UIO_SYSSPACE;
185 	uio.uio_extflg = UIO_COPY_DEFAULT;
186 
187 	/*
188 	 * Build the iov list, meanwhile computing the length of
189 	 * the SMB payload (to put in the NBT header).
190 	 */
191 	uio.uio_iov[0].iov_base = (void *)nbt_hdr;
192 	uio.uio_iov[0].iov_len = sizeof (nbt_hdr);
193 	i = 1;
194 	nbt_len = 0;
195 	m = (mbc != NULL) ? mbc->chain : NULL;
196 	while (m != NULL) {
197 		uio.uio_iov[i].iov_base = m->m_data;
198 		uio.uio_iov[i++].iov_len = m->m_len;
199 		nbt_len += m->m_len;
200 		m = m->m_next;
201 	}
202 	ASSERT3S(i, ==, nseg);
203 
204 	/*
205 	 * Set the NBT header, set uio_resid
206 	 */
207 	uio.uio_resid = nbt_len + NETBIOS_HDR_SZ;
208 	rc = smb_session_xprt_puthdr(session, nbt_type, nbt_len,
209 	    nbt_hdr, NETBIOS_HDR_SZ);
210 	if (rc != 0)
211 		goto out;
212 
213 	smb_server_add_txb(session->s_server, (int64_t)uio.uio_resid);
214 	rc = smb_net_send_uio(session, &uio);
215 
216 out:
217 	if (alloc_iov != NULL)
218 		kmem_free(alloc_iov, alloc_sz);
219 	if ((mbc != NULL) && (mbc->chain != NULL)) {
220 		m_freem(mbc->chain);
221 		mbc->chain = NULL;
222 		mbc->flags = 0;
223 	}
224 	return (rc);
225 }
226 
227 /*
228  * Read, process and respond to a NetBIOS session request.
229  *
230  * A NetBIOS session must be established for SMB-over-NetBIOS.  Validate
231  * the calling and called name format and save the client NetBIOS name,
232  * which is used when a NetBIOS session is established to check for and
233  * cleanup leftover state from a previous session.
234  *
235  * Session requests are not valid for SMB-over-TCP, which is unfortunate
236  * because without the client name leftover state cannot be cleaned up
237  * if the client is behind a NAT server.
238  */
239 static int
240 smb_netbios_session_request(struct smb_session *session)
241 {
242 	int			rc;
243 	char			*calling_name;
244 	char			*called_name;
245 	char 			client_name[NETBIOS_NAME_SZ];
246 	struct mbuf_chain 	mbc;
247 	char 			*names = NULL;
248 	smb_wchar_t		*wbuf = NULL;
249 	smb_xprt_t		hdr;
250 	char *p;
251 	int rc1, rc2;
252 
253 	session->keep_alive = smb_keep_alive;
254 
255 	if ((rc = smb_session_xprt_gethdr(session, &hdr)) != 0)
256 		return (rc);
257 
258 	DTRACE_PROBE2(receive__session__req__xprthdr, struct session *, session,
259 	    smb_xprt_t *, &hdr);
260 
261 	if ((hdr.xh_type != SESSION_REQUEST) ||
262 	    (hdr.xh_length != NETBIOS_SESSION_REQUEST_DATA_LENGTH)) {
263 		DTRACE_PROBE1(receive__session__req__failed,
264 		    struct session *, session);
265 		return (EINVAL);
266 	}
267 
268 	names = kmem_alloc(hdr.xh_length, KM_SLEEP);
269 
270 	if ((rc = smb_sorecv(session->sock, names, hdr.xh_length)) != 0) {
271 		kmem_free(names, hdr.xh_length);
272 		DTRACE_PROBE1(receive__session__req__failed,
273 		    struct session *, session);
274 		return (rc);
275 	}
276 
277 	DTRACE_PROBE3(receive__session__req__data, struct session *, session,
278 	    char *, names, uint32_t, hdr.xh_length);
279 
280 	called_name = &names[0];
281 	calling_name = &names[NETBIOS_ENCODED_NAME_SZ + 2];
282 
283 	rc1 = netbios_name_isvalid(called_name, 0);
284 	rc2 = netbios_name_isvalid(calling_name, client_name);
285 
286 	if (rc1 == 0 || rc2 == 0) {
287 
288 		DTRACE_PROBE3(receive__invalid__session__req,
289 		    struct session *, session, char *, names,
290 		    uint32_t, hdr.xh_length);
291 
292 		kmem_free(names, hdr.xh_length);
293 		MBC_INIT(&mbc, MAX_DATAGRAM_LENGTH);
294 		(void) smb_mbc_encodef(&mbc, "b",
295 		    DATAGRAM_INVALID_SOURCE_NAME_FORMAT);
296 		(void) smb_session_send(session, NEGATIVE_SESSION_RESPONSE,
297 		    &mbc);
298 		return (EINVAL);
299 	}
300 
301 	DTRACE_PROBE3(receive__session__req__calling__decoded,
302 	    struct session *, session,
303 	    char *, calling_name, char *, client_name);
304 
305 	/*
306 	 * The client NetBIOS name is in oem codepage format.
307 	 * We need to convert it to unicode and store it in
308 	 * multi-byte format.  We also need to strip off any
309 	 * spaces added as part of the NetBIOS name encoding.
310 	 */
311 	wbuf = kmem_alloc((SMB_PI_MAX_HOST * sizeof (smb_wchar_t)), KM_SLEEP);
312 	(void) oemtoucs(wbuf, client_name, SMB_PI_MAX_HOST, OEM_CPG_850);
313 	(void) smb_wcstombs(session->workstation, wbuf, SMB_PI_MAX_HOST);
314 	kmem_free(wbuf, (SMB_PI_MAX_HOST * sizeof (smb_wchar_t)));
315 
316 	if ((p = strchr(session->workstation, ' ')) != 0)
317 		*p = '\0';
318 
319 	kmem_free(names, hdr.xh_length);
320 	return (smb_session_send(session, POSITIVE_SESSION_RESPONSE, NULL));
321 }
322 
323 /*
324  * Read 4-byte header from the session socket and build an in-memory
325  * session transport header.  See smb_xprt_t definition for header
326  * format information.
327  *
328  * Direct hosted NetBIOS-less SMB (SMB-over-TCP) uses port 445.  The
329  * first byte of the four-byte header must be 0 and the next three
330  * bytes contain the length of the remaining data.
331  */
332 int
333 smb_session_xprt_gethdr(smb_session_t *session, smb_xprt_t *ret_hdr)
334 {
335 	int		rc;
336 	unsigned char	buf[NETBIOS_HDR_SZ];
337 
338 	if ((rc = smb_sorecv(session->sock, buf, NETBIOS_HDR_SZ)) != 0)
339 		return (rc);
340 
341 	switch (session->s_local_port) {
342 	case IPPORT_NETBIOS_SSN:
343 		ret_hdr->xh_type = buf[0];
344 		ret_hdr->xh_length = (((uint32_t)buf[1] & 1) << 16) |
345 		    ((uint32_t)buf[2] << 8) |
346 		    ((uint32_t)buf[3]);
347 		break;
348 
349 	case IPPORT_SMB:
350 		ret_hdr->xh_type = buf[0];
351 
352 		if (ret_hdr->xh_type != 0) {
353 			cmn_err(CE_WARN, "invalid NBT type (%u) from %s",
354 			    ret_hdr->xh_type, session->ip_addr_str);
355 			return (EPROTO);
356 		}
357 
358 		ret_hdr->xh_length = ((uint32_t)buf[1] << 16) |
359 		    ((uint32_t)buf[2] << 8) |
360 		    ((uint32_t)buf[3]);
361 		break;
362 
363 	default:
364 		cmn_err(CE_WARN, "invalid port %u", session->s_local_port);
365 		return (EPROTO);
366 	}
367 
368 	return (0);
369 }
370 
371 /*
372  * Encode a transport session packet header into a 4-byte buffer.
373  */
374 static int
375 smb_session_xprt_puthdr(smb_session_t *session,
376     uint8_t msg_type, uint32_t msg_length,
377     uint8_t *buf, size_t buflen)
378 {
379 	if (buf == NULL || buflen < NETBIOS_HDR_SZ) {
380 		return (-1);
381 	}
382 
383 	switch (session->s_local_port) {
384 	case IPPORT_NETBIOS_SSN:
385 		/* Per RFC 1001, 1002: msg. len < 128KB */
386 		if (msg_length >= (1 << 17))
387 			return (-1);
388 		buf[0] = msg_type;
389 		buf[1] = ((msg_length >> 16) & 1);
390 		buf[2] = (msg_length >> 8) & 0xff;
391 		buf[3] = msg_length & 0xff;
392 		break;
393 
394 	case IPPORT_SMB:
395 		/*
396 		 * SMB over TCP is like NetBIOS but the one byte
397 		 * message type is always zero, and the length
398 		 * part is three bytes.  It could actually use
399 		 * longer messages, but this is conservative.
400 		 */
401 		if (msg_length >= (1 << 24))
402 			return (-1);
403 		buf[0] = msg_type;
404 		buf[1] = (msg_length >> 16) & 0xff;
405 		buf[2] = (msg_length >> 8) & 0xff;
406 		buf[3] = msg_length & 0xff;
407 		break;
408 
409 	default:
410 		cmn_err(CE_WARN, "invalid port %u", session->s_local_port);
411 		return (-1);
412 	}
413 
414 	return (0);
415 }
416 
417 static void
418 smb_request_init_command_mbuf(smb_request_t *sr)
419 {
420 
421 	/*
422 	 * Setup mbuf using the buffer we allocated.
423 	 */
424 	MBC_ATTACH_BUF(&sr->command, sr->sr_request_buf, sr->sr_req_length);
425 
426 	sr->command.flags = 0;
427 	sr->command.shadow_of = NULL;
428 }
429 
430 /*
431  * smb_request_cancel
432  *
433  * Handle a cancel for a request properly depending on the current request
434  * state.
435  */
436 void
437 smb_request_cancel(smb_request_t *sr)
438 {
439 	void (*cancel_method)(smb_request_t *) = NULL;
440 
441 	mutex_enter(&sr->sr_mutex);
442 	switch (sr->sr_state) {
443 
444 	case SMB_REQ_STATE_INITIALIZING:
445 	case SMB_REQ_STATE_SUBMITTED:
446 	case SMB_REQ_STATE_ACTIVE:
447 	case SMB_REQ_STATE_CLEANED_UP:
448 		sr->sr_state = SMB_REQ_STATE_CANCELLED;
449 		break;
450 
451 	case SMB_REQ_STATE_WAITING_AUTH:
452 	case SMB_REQ_STATE_WAITING_FCN1:
453 	case SMB_REQ_STATE_WAITING_LOCK:
454 	case SMB_REQ_STATE_WAITING_PIPE:
455 		/*
456 		 * These are states that have a cancel_method.
457 		 * Make the state change now, to ensure that
458 		 * we call cancel_method exactly once.  Do the
459 		 * method call below, after we drop sr_mutex.
460 		 * When the cancelled request thread resumes,
461 		 * it should re-take sr_mutex and set sr_state
462 		 * to CANCELLED, then return STATUS_CANCELLED.
463 		 */
464 		sr->sr_state = SMB_REQ_STATE_CANCEL_PENDING;
465 		cancel_method = sr->cancel_method;
466 		VERIFY(cancel_method != NULL);
467 		break;
468 
469 	case SMB_REQ_STATE_WAITING_FCN2:
470 	case SMB_REQ_STATE_COMPLETED:
471 	case SMB_REQ_STATE_CANCEL_PENDING:
472 	case SMB_REQ_STATE_CANCELLED:
473 		/*
474 		 * No action required for these states since the request
475 		 * is completing.
476 		 */
477 		break;
478 
479 	case SMB_REQ_STATE_FREE:
480 	default:
481 		SMB_PANIC();
482 	}
483 	mutex_exit(&sr->sr_mutex);
484 
485 	if (cancel_method != NULL) {
486 		cancel_method(sr);
487 	}
488 }
489 
490 /*
491  * smb_session_receiver
492  *
493  * Receives request from the network and dispatches them to a worker.
494  */
495 void
496 smb_session_receiver(smb_session_t *session)
497 {
498 	int	rc = 0;
499 
500 	SMB_SESSION_VALID(session);
501 
502 	session->s_thread = curthread;
503 
504 	if (session->s_local_port == IPPORT_NETBIOS_SSN) {
505 		rc = smb_netbios_session_request(session);
506 		if (rc != 0) {
507 			smb_rwx_rwenter(&session->s_lock, RW_WRITER);
508 			session->s_state = SMB_SESSION_STATE_DISCONNECTED;
509 			smb_rwx_rwexit(&session->s_lock);
510 			return;
511 		}
512 	}
513 
514 	smb_rwx_rwenter(&session->s_lock, RW_WRITER);
515 	session->s_state = SMB_SESSION_STATE_ESTABLISHED;
516 	smb_rwx_rwexit(&session->s_lock);
517 
518 	(void) smb_session_reader(session);
519 
520 	smb_rwx_rwenter(&session->s_lock, RW_WRITER);
521 	session->s_state = SMB_SESSION_STATE_DISCONNECTED;
522 	smb_rwx_rwexit(&session->s_lock);
523 
524 	smb_soshutdown(session->sock);
525 
526 	DTRACE_PROBE2(session__drop, struct session *, session, int, rc);
527 
528 	smb_session_cancel(session);
529 	/*
530 	 * At this point everything related to the session should have been
531 	 * cleaned up and we expect that nothing will attempt to use the
532 	 * socket.
533 	 */
534 }
535 
536 /*
537  * smb_session_disconnect
538  *
539  * Disconnects the session passed in.
540  */
541 void
542 smb_session_disconnect(smb_session_t *session)
543 {
544 	SMB_SESSION_VALID(session);
545 
546 	smb_rwx_rwenter(&session->s_lock, RW_WRITER);
547 	switch (session->s_state) {
548 	case SMB_SESSION_STATE_INITIALIZED:
549 	case SMB_SESSION_STATE_CONNECTED:
550 	case SMB_SESSION_STATE_ESTABLISHED:
551 	case SMB_SESSION_STATE_NEGOTIATED:
552 		smb_soshutdown(session->sock);
553 		session->s_state = SMB_SESSION_STATE_DISCONNECTED;
554 		_NOTE(FALLTHRU)
555 	case SMB_SESSION_STATE_DISCONNECTED:
556 	case SMB_SESSION_STATE_TERMINATED:
557 		break;
558 	}
559 	smb_rwx_rwexit(&session->s_lock);
560 }
561 
562 /*
563  * Read and process SMB requests.
564  *
565  * Returns:
566  *	0	Success
567  *	1	Unable to read transport header
568  *	2	Invalid transport header type
569  *	3	Invalid SMB length (too small)
570  *	4	Unable to read SMB header
571  *	5	Invalid SMB header (bad magic number)
572  *	6	Unable to read SMB data
573  */
574 static int
575 smb_session_reader(smb_session_t *session)
576 {
577 	smb_server_t	*sv;
578 	smb_request_t	*sr = NULL;
579 	smb_xprt_t	hdr;
580 	uint8_t		*req_buf;
581 	uint32_t	resid;
582 	int		rc;
583 
584 	sv = session->s_server;
585 
586 	for (;;) {
587 
588 		rc = smb_session_xprt_gethdr(session, &hdr);
589 		if (rc)
590 			return (rc);
591 
592 		DTRACE_PROBE2(session__receive__xprthdr, session_t *, session,
593 		    smb_xprt_t *, &hdr);
594 
595 		if (hdr.xh_type != SESSION_MESSAGE) {
596 			/*
597 			 * Anything other than SESSION_MESSAGE or
598 			 * SESSION_KEEP_ALIVE is an error.  A SESSION_REQUEST
599 			 * may indicate a new session request but we need to
600 			 * close this session and we can treat it as an error
601 			 * here.
602 			 */
603 			if (hdr.xh_type == SESSION_KEEP_ALIVE) {
604 				session->keep_alive = smb_keep_alive;
605 				continue;
606 			}
607 			return (EPROTO);
608 		}
609 
610 		if (hdr.xh_length == 0) {
611 			/* zero length is another form of keep alive */
612 			session->keep_alive = smb_keep_alive;
613 			continue;
614 		}
615 
616 		if (hdr.xh_length < SMB_HEADER_LEN)
617 			return (EPROTO);
618 		if (hdr.xh_length > session->cmd_max_bytes)
619 			return (EPROTO);
620 
621 		session->keep_alive = smb_keep_alive;
622 
623 		/*
624 		 * Allocate a request context, read the whole message.
625 		 * If the request alloc fails, we've disconnected and
626 		 * won't be able to send the reply anyway, so bail now.
627 		 */
628 		if ((sr = smb_request_alloc(session, hdr.xh_length)) == NULL)
629 			break;
630 
631 		req_buf = (uint8_t *)sr->sr_request_buf;
632 		resid = hdr.xh_length;
633 
634 		rc = smb_sorecv(session->sock, req_buf, resid);
635 		if (rc) {
636 			smb_request_free(sr);
637 			break;
638 		}
639 
640 		/* accounting: received bytes */
641 		smb_server_add_rxb(sv,
642 		    (int64_t)(hdr.xh_length + NETBIOS_HDR_SZ));
643 
644 		/*
645 		 * Initialize command MBC to represent the received data.
646 		 */
647 		smb_request_init_command_mbuf(sr);
648 
649 		DTRACE_PROBE1(session__receive__smb, smb_request_t *, sr);
650 
651 		rc = session->newrq_func(sr);
652 		sr = NULL;	/* enqueued or freed */
653 		if (rc != 0)
654 			break;
655 
656 		/* See notes where this is defined (above). */
657 		if (smb_reader_delay) {
658 			delay(MSEC_TO_TICK(smb_reader_delay));
659 		}
660 	}
661 	return (rc);
662 }
663 
664 /*
665  * This is the initial handler for new smb requests, called from
666  * from smb_session_reader when we have not yet seen any requests.
667  * The first SMB request must be "negotiate", which determines
668  * which protocol and dialect we'll be using.  That's the ONLY
669  * request type handled here, because with all later requests,
670  * we know the protocol and handle those with either the SMB1 or
671  * SMB2 handlers:  smb1sr_post() or smb2sr_post().
672  * Those do NOT allow SMB negotiate, because that's only allowed
673  * as the first request on new session.
674  *
675  * This and other "post a request" handlers must either enqueue
676  * the new request for the session taskq, or smb_request_free it
677  * (in case we've decided to drop this connection).  In this
678  * (special) new request handler, we always free the request.
679  */
680 static int
681 smbsr_newrq_initial(smb_request_t *sr)
682 {
683 	uint32_t magic;
684 	int rc = EPROTO;
685 
686 	mutex_enter(&sr->sr_mutex);
687 	sr->sr_state = SMB_REQ_STATE_ACTIVE;
688 	mutex_exit(&sr->sr_mutex);
689 
690 	magic = SMB_READ_PROTOCOL(sr->sr_request_buf);
691 	if (magic == SMB_PROTOCOL_MAGIC)
692 		rc = smb1_newrq_negotiate(sr);
693 	if (magic == SMB2_PROTOCOL_MAGIC)
694 		rc = smb2_newrq_negotiate(sr);
695 
696 	mutex_enter(&sr->sr_mutex);
697 	sr->sr_state = SMB_REQ_STATE_COMPLETED;
698 	mutex_exit(&sr->sr_mutex);
699 
700 	smb_request_free(sr);
701 	return (rc);
702 }
703 
704 /*
705  * Port will be IPPORT_NETBIOS_SSN or IPPORT_SMB.
706  */
707 smb_session_t *
708 smb_session_create(ksocket_t new_so, uint16_t port, smb_server_t *sv,
709     int family)
710 {
711 	struct sockaddr_in	sin;
712 	socklen_t		slen;
713 	struct sockaddr_in6	sin6;
714 	smb_session_t		*session;
715 	int64_t			now;
716 	uint16_t		rport;
717 
718 	session = kmem_cache_alloc(smb_cache_session, KM_SLEEP);
719 	bzero(session, sizeof (smb_session_t));
720 
721 	if (smb_idpool_constructor(&session->s_uid_pool)) {
722 		kmem_cache_free(smb_cache_session, session);
723 		return (NULL);
724 	}
725 	if (smb_idpool_constructor(&session->s_tid_pool)) {
726 		smb_idpool_destructor(&session->s_uid_pool);
727 		kmem_cache_free(smb_cache_session, session);
728 		return (NULL);
729 	}
730 
731 	now = ddi_get_lbolt64();
732 
733 	session->s_kid = SMB_NEW_KID();
734 	session->s_state = SMB_SESSION_STATE_INITIALIZED;
735 	session->native_os = NATIVE_OS_UNKNOWN;
736 	session->opentime = now;
737 	session->keep_alive = smb_keep_alive;
738 	session->activity_timestamp = now;
739 
740 	smb_session_genkey(session);
741 
742 	mutex_init(&session->s_credits_mutex, NULL, MUTEX_DEFAULT, NULL);
743 
744 	smb_slist_constructor(&session->s_req_list, sizeof (smb_request_t),
745 	    offsetof(smb_request_t, sr_session_lnd));
746 
747 	smb_llist_constructor(&session->s_user_list, sizeof (smb_user_t),
748 	    offsetof(smb_user_t, u_lnd));
749 
750 	smb_llist_constructor(&session->s_tree_list, sizeof (smb_tree_t),
751 	    offsetof(smb_tree_t, t_lnd));
752 
753 	smb_llist_constructor(&session->s_xa_list, sizeof (smb_xa_t),
754 	    offsetof(smb_xa_t, xa_lnd));
755 
756 	smb_net_txl_constructor(&session->s_txlst);
757 
758 	smb_rwx_init(&session->s_lock);
759 
760 	if (new_so != NULL) {
761 		if (family == AF_INET) {
762 			slen = sizeof (sin);
763 			(void) ksocket_getsockname(new_so,
764 			    (struct sockaddr *)&sin, &slen, CRED());
765 			bcopy(&sin.sin_addr,
766 			    &session->local_ipaddr.au_addr.au_ipv4,
767 			    sizeof (in_addr_t));
768 			slen = sizeof (sin);
769 			(void) ksocket_getpeername(new_so,
770 			    (struct sockaddr *)&sin, &slen, CRED());
771 			bcopy(&sin.sin_addr,
772 			    &session->ipaddr.au_addr.au_ipv4,
773 			    sizeof (in_addr_t));
774 			rport = sin.sin_port;
775 		} else {
776 			slen = sizeof (sin6);
777 			(void) ksocket_getsockname(new_so,
778 			    (struct sockaddr *)&sin6, &slen, CRED());
779 			bcopy(&sin6.sin6_addr,
780 			    &session->local_ipaddr.au_addr.au_ipv6,
781 			    sizeof (in6_addr_t));
782 			slen = sizeof (sin6);
783 			(void) ksocket_getpeername(new_so,
784 			    (struct sockaddr *)&sin6, &slen, CRED());
785 			bcopy(&sin6.sin6_addr,
786 			    &session->ipaddr.au_addr.au_ipv6,
787 			    sizeof (in6_addr_t));
788 			rport = sin6.sin6_port;
789 		}
790 		session->ipaddr.a_family = family;
791 		session->local_ipaddr.a_family = family;
792 		session->s_local_port = port;
793 		session->s_remote_port = ntohs(rport);
794 		session->sock = new_so;
795 		(void) smb_inet_ntop(&session->ipaddr,
796 		    session->ip_addr_str, INET6_ADDRSTRLEN);
797 		if (port == IPPORT_NETBIOS_SSN)
798 			smb_server_inc_nbt_sess(sv);
799 		else
800 			smb_server_inc_tcp_sess(sv);
801 	}
802 	session->s_server = sv;
803 	smb_server_get_cfg(sv, &session->s_cfg);
804 	session->s_srqueue = &sv->sv_srqueue;
805 
806 	/*
807 	 * The initial new request handler is special,
808 	 * and only accepts negotiation requests.
809 	 */
810 	session->newrq_func = smbsr_newrq_initial;
811 
812 	/* These may increase in SMB2 negotiate. */
813 	session->cmd_max_bytes = SMB_REQ_MAX_SIZE;
814 	session->reply_max_bytes = SMB_REQ_MAX_SIZE;
815 
816 	session->s_magic = SMB_SESSION_MAGIC;
817 	return (session);
818 }
819 
820 void
821 smb_session_delete(smb_session_t *session)
822 {
823 
824 	ASSERT(session->s_magic == SMB_SESSION_MAGIC);
825 
826 	if (session->sign_fini != NULL)
827 		session->sign_fini(session);
828 
829 	if (session->signing.mackey != NULL) {
830 		kmem_free(session->signing.mackey,
831 		    session->signing.mackey_len);
832 	}
833 
834 	session->s_magic = 0;
835 
836 	smb_rwx_destroy(&session->s_lock);
837 	smb_net_txl_destructor(&session->s_txlst);
838 
839 	mutex_destroy(&session->s_credits_mutex);
840 
841 	smb_slist_destructor(&session->s_req_list);
842 	smb_llist_destructor(&session->s_tree_list);
843 	smb_llist_destructor(&session->s_user_list);
844 	smb_llist_destructor(&session->s_xa_list);
845 
846 	ASSERT(session->s_tree_cnt == 0);
847 	ASSERT(session->s_file_cnt == 0);
848 	ASSERT(session->s_dir_cnt == 0);
849 
850 	smb_idpool_destructor(&session->s_tid_pool);
851 	smb_idpool_destructor(&session->s_uid_pool);
852 	if (session->sock != NULL) {
853 		if (session->s_local_port == IPPORT_NETBIOS_SSN)
854 			smb_server_dec_nbt_sess(session->s_server);
855 		else
856 			smb_server_dec_tcp_sess(session->s_server);
857 		smb_sodestroy(session->sock);
858 	}
859 	kmem_cache_free(smb_cache_session, session);
860 }
861 
862 static void
863 smb_session_cancel(smb_session_t *session)
864 {
865 	smb_xa_t	*xa, *nextxa;
866 
867 	/* All the request currently being treated must be canceled. */
868 	smb_session_cancel_requests(session, NULL, NULL);
869 
870 	/*
871 	 * We wait for the completion of all the requests associated with
872 	 * this session.
873 	 */
874 	smb_slist_wait_for_empty(&session->s_req_list);
875 
876 	/*
877 	 * At this point the reference count of the users, trees, files,
878 	 * directories should be zero. It should be possible to destroy them
879 	 * without any problem.
880 	 */
881 	xa = smb_llist_head(&session->s_xa_list);
882 	while (xa) {
883 		nextxa = smb_llist_next(&session->s_xa_list, xa);
884 		smb_xa_close(xa);
885 		xa = nextxa;
886 	}
887 
888 	smb_session_logoff(session);
889 }
890 
891 /*
892  * Cancel requests.  If a non-null tree is specified, only requests specific
893  * to that tree will be cancelled.  If a non-null sr is specified, that sr
894  * will be not be cancelled - this would typically be the caller's sr.
895  */
896 void
897 smb_session_cancel_requests(
898     smb_session_t	*session,
899     smb_tree_t		*tree,
900     smb_request_t	*exclude_sr)
901 {
902 	smb_request_t	*sr;
903 
904 	smb_slist_enter(&session->s_req_list);
905 	sr = smb_slist_head(&session->s_req_list);
906 
907 	while (sr) {
908 		ASSERT(sr->sr_magic == SMB_REQ_MAGIC);
909 		if ((sr != exclude_sr) &&
910 		    (tree == NULL || sr->tid_tree == tree))
911 			smb_request_cancel(sr);
912 
913 		sr = smb_slist_next(&session->s_req_list, sr);
914 	}
915 
916 	smb_slist_exit(&session->s_req_list);
917 }
918 
919 /*
920  * Find a user on the specified session by SMB UID.
921  */
922 smb_user_t *
923 smb_session_lookup_uid(smb_session_t *session, uint16_t uid)
924 {
925 	return (smb_session_lookup_uid_st(session, uid,
926 	    SMB_USER_STATE_LOGGED_ON));
927 }
928 
929 smb_user_t *
930 smb_session_lookup_uid_st(smb_session_t *session, uint16_t uid,
931     smb_user_state_t st)
932 {
933 	smb_user_t	*user;
934 	smb_llist_t	*user_list;
935 
936 	SMB_SESSION_VALID(session);
937 
938 	user_list = &session->s_user_list;
939 	smb_llist_enter(user_list, RW_READER);
940 
941 	user = smb_llist_head(user_list);
942 	while (user) {
943 		SMB_USER_VALID(user);
944 		ASSERT(user->u_session == session);
945 
946 		if (user->u_uid == uid && user->u_state == st) {
947 			smb_user_hold_internal(user);
948 			break;
949 		}
950 
951 		user = smb_llist_next(user_list, user);
952 	}
953 
954 	smb_llist_exit(user_list);
955 	return (user);
956 }
957 
958 void
959 smb_session_post_user(smb_session_t *session, smb_user_t *user)
960 {
961 	SMB_USER_VALID(user);
962 	ASSERT(user->u_refcnt == 0);
963 	ASSERT(user->u_state == SMB_USER_STATE_LOGGED_OFF);
964 	ASSERT(user->u_session == session);
965 
966 	smb_llist_post(&session->s_user_list, user, smb_user_delete);
967 }
968 
969 /*
970  * Find a tree by tree-id.
971  */
972 smb_tree_t *
973 smb_session_lookup_tree(
974     smb_session_t	*session,
975     uint16_t		tid)
976 
977 {
978 	smb_tree_t	*tree;
979 
980 	SMB_SESSION_VALID(session);
981 
982 	smb_llist_enter(&session->s_tree_list, RW_READER);
983 	tree = smb_llist_head(&session->s_tree_list);
984 
985 	while (tree) {
986 		ASSERT3U(tree->t_magic, ==, SMB_TREE_MAGIC);
987 		ASSERT(tree->t_session == session);
988 
989 		if (tree->t_tid == tid) {
990 			if (smb_tree_hold(tree)) {
991 				smb_llist_exit(&session->s_tree_list);
992 				return (tree);
993 			} else {
994 				smb_llist_exit(&session->s_tree_list);
995 				return (NULL);
996 			}
997 		}
998 
999 		tree = smb_llist_next(&session->s_tree_list, tree);
1000 	}
1001 
1002 	smb_llist_exit(&session->s_tree_list);
1003 	return (NULL);
1004 }
1005 
1006 /*
1007  * Find the first connected tree that matches the specified sharename.
1008  * If the specified tree is NULL the search starts from the beginning of
1009  * the user's tree list.  If a tree is provided the search starts just
1010  * after that tree.
1011  */
1012 smb_tree_t *
1013 smb_session_lookup_share(
1014     smb_session_t	*session,
1015     const char		*sharename,
1016     smb_tree_t		*tree)
1017 {
1018 	SMB_SESSION_VALID(session);
1019 	ASSERT(sharename);
1020 
1021 	smb_llist_enter(&session->s_tree_list, RW_READER);
1022 
1023 	if (tree) {
1024 		ASSERT3U(tree->t_magic, ==, SMB_TREE_MAGIC);
1025 		ASSERT(tree->t_session == session);
1026 		tree = smb_llist_next(&session->s_tree_list, tree);
1027 	} else {
1028 		tree = smb_llist_head(&session->s_tree_list);
1029 	}
1030 
1031 	while (tree) {
1032 		ASSERT3U(tree->t_magic, ==, SMB_TREE_MAGIC);
1033 		ASSERT(tree->t_session == session);
1034 		if (smb_strcasecmp(tree->t_sharename, sharename, 0) == 0) {
1035 			if (smb_tree_hold(tree)) {
1036 				smb_llist_exit(&session->s_tree_list);
1037 				return (tree);
1038 			}
1039 		}
1040 		tree = smb_llist_next(&session->s_tree_list, tree);
1041 	}
1042 
1043 	smb_llist_exit(&session->s_tree_list);
1044 	return (NULL);
1045 }
1046 
1047 /*
1048  * Find the first connected tree that matches the specified volume name.
1049  * If the specified tree is NULL the search starts from the beginning of
1050  * the user's tree list.  If a tree is provided the search starts just
1051  * after that tree.
1052  */
1053 smb_tree_t *
1054 smb_session_lookup_volume(
1055     smb_session_t	*session,
1056     const char		*name,
1057     smb_tree_t		*tree)
1058 {
1059 	SMB_SESSION_VALID(session);
1060 	ASSERT(name);
1061 
1062 	smb_llist_enter(&session->s_tree_list, RW_READER);
1063 
1064 	if (tree) {
1065 		ASSERT3U(tree->t_magic, ==, SMB_TREE_MAGIC);
1066 		ASSERT(tree->t_session == session);
1067 		tree = smb_llist_next(&session->s_tree_list, tree);
1068 	} else {
1069 		tree = smb_llist_head(&session->s_tree_list);
1070 	}
1071 
1072 	while (tree) {
1073 		ASSERT3U(tree->t_magic, ==, SMB_TREE_MAGIC);
1074 		ASSERT(tree->t_session == session);
1075 
1076 		if (smb_strcasecmp(tree->t_volume, name, 0) == 0) {
1077 			if (smb_tree_hold(tree)) {
1078 				smb_llist_exit(&session->s_tree_list);
1079 				return (tree);
1080 			}
1081 		}
1082 
1083 		tree = smb_llist_next(&session->s_tree_list, tree);
1084 	}
1085 
1086 	smb_llist_exit(&session->s_tree_list);
1087 	return (NULL);
1088 }
1089 
1090 /*
1091  * Disconnect all trees that match the specified client process-id.
1092  */
1093 void
1094 smb_session_close_pid(
1095     smb_session_t	*session,
1096     uint32_t		pid)
1097 {
1098 	smb_tree_t	*tree;
1099 
1100 	SMB_SESSION_VALID(session);
1101 
1102 	tree = smb_session_get_tree(session, NULL);
1103 	while (tree) {
1104 		smb_tree_t *next;
1105 		ASSERT3U(tree->t_magic, ==, SMB_TREE_MAGIC);
1106 		ASSERT(tree->t_session == session);
1107 		smb_tree_close_pid(tree, pid);
1108 		next = smb_session_get_tree(session, tree);
1109 		smb_tree_release(tree);
1110 		tree = next;
1111 	}
1112 }
1113 
1114 static void
1115 smb_session_tree_dtor(void *t)
1116 {
1117 	smb_tree_t	*tree = (smb_tree_t *)t;
1118 
1119 	smb_tree_disconnect(tree, B_TRUE);
1120 	/* release the ref acquired during the traversal loop */
1121 	smb_tree_release(tree);
1122 }
1123 
1124 
1125 /*
1126  * Disconnect all trees that this user has connected.
1127  */
1128 void
1129 smb_session_disconnect_owned_trees(
1130     smb_session_t	*session,
1131     smb_user_t		*owner)
1132 {
1133 	smb_tree_t	*tree;
1134 	smb_llist_t	*tree_list = &session->s_tree_list;
1135 
1136 	SMB_SESSION_VALID(session);
1137 	SMB_USER_VALID(owner);
1138 
1139 	smb_llist_enter(tree_list, RW_READER);
1140 
1141 	tree = smb_llist_head(tree_list);
1142 	while (tree) {
1143 		if ((tree->t_owner == owner) &&
1144 		    smb_tree_hold(tree)) {
1145 			/*
1146 			 * smb_tree_hold() succeeded, hence we are in state
1147 			 * SMB_TREE_STATE_CONNECTED; schedule this tree
1148 			 * for asynchronous disconnect, which will fire
1149 			 * after we drop the llist traversal lock.
1150 			 */
1151 			smb_llist_post(tree_list, tree, smb_session_tree_dtor);
1152 		}
1153 		tree = smb_llist_next(tree_list, tree);
1154 	}
1155 
1156 	/* drop the lock and flush the dtor queue */
1157 	smb_llist_exit(tree_list);
1158 }
1159 
1160 /*
1161  * Disconnect all trees that this user has connected.
1162  */
1163 void
1164 smb_session_disconnect_trees(
1165     smb_session_t	*session)
1166 {
1167 	smb_tree_t	*tree;
1168 
1169 	SMB_SESSION_VALID(session);
1170 
1171 	tree = smb_session_get_tree(session, NULL);
1172 	while (tree) {
1173 		ASSERT3U(tree->t_magic, ==, SMB_TREE_MAGIC);
1174 		ASSERT(tree->t_session == session);
1175 		smb_tree_disconnect(tree, B_TRUE);
1176 		smb_tree_release(tree);
1177 		tree = smb_session_get_tree(session, NULL);
1178 	}
1179 }
1180 
1181 /*
1182  * Disconnect all trees that match the specified share name.
1183  */
1184 void
1185 smb_session_disconnect_share(
1186     smb_session_t	*session,
1187     const char		*sharename)
1188 {
1189 	smb_tree_t	*tree;
1190 	smb_tree_t	*next;
1191 
1192 	SMB_SESSION_VALID(session);
1193 
1194 	tree = smb_session_lookup_share(session, sharename, NULL);
1195 	while (tree) {
1196 		ASSERT3U(tree->t_magic, ==, SMB_TREE_MAGIC);
1197 		ASSERT(tree->t_session == session);
1198 		smb_tree_disconnect(tree, B_TRUE);
1199 		smb_session_cancel_requests(session, tree, NULL);
1200 		next = smb_session_lookup_share(session, sharename, tree);
1201 		smb_tree_release(tree);
1202 		tree = next;
1203 	}
1204 }
1205 
1206 void
1207 smb_session_post_tree(smb_session_t *session, smb_tree_t *tree)
1208 {
1209 	SMB_SESSION_VALID(session);
1210 	SMB_TREE_VALID(tree);
1211 	ASSERT0(tree->t_refcnt);
1212 	ASSERT(tree->t_state == SMB_TREE_STATE_DISCONNECTED);
1213 	ASSERT(tree->t_session == session);
1214 
1215 	smb_llist_post(&session->s_tree_list, tree, smb_tree_dealloc);
1216 }
1217 
1218 /*
1219  * Get the next connected tree in the list.  A reference is taken on
1220  * the tree, which can be released later with smb_tree_release().
1221  *
1222  * If the specified tree is NULL the search starts from the beginning of
1223  * the tree list.  If a tree is provided the search starts just after
1224  * that tree.
1225  *
1226  * Returns NULL if there are no connected trees in the list.
1227  */
1228 static smb_tree_t *
1229 smb_session_get_tree(
1230     smb_session_t	*session,
1231     smb_tree_t		*tree)
1232 {
1233 	smb_llist_t	*tree_list;
1234 
1235 	SMB_SESSION_VALID(session);
1236 	tree_list = &session->s_tree_list;
1237 
1238 	smb_llist_enter(tree_list, RW_READER);
1239 
1240 	if (tree) {
1241 		ASSERT3U(tree->t_magic, ==, SMB_TREE_MAGIC);
1242 		tree = smb_llist_next(tree_list, tree);
1243 	} else {
1244 		tree = smb_llist_head(tree_list);
1245 	}
1246 
1247 	while (tree) {
1248 		if (smb_tree_hold(tree))
1249 			break;
1250 
1251 		tree = smb_llist_next(tree_list, tree);
1252 	}
1253 
1254 	smb_llist_exit(tree_list);
1255 	return (tree);
1256 }
1257 
1258 /*
1259  * Logoff all users associated with the specified session.
1260  */
1261 static void
1262 smb_session_logoff(smb_session_t *session)
1263 {
1264 	smb_user_t	*user;
1265 
1266 	SMB_SESSION_VALID(session);
1267 
1268 	smb_session_disconnect_trees(session);
1269 
1270 	smb_llist_enter(&session->s_user_list, RW_READER);
1271 
1272 	user = smb_llist_head(&session->s_user_list);
1273 	while (user) {
1274 		SMB_USER_VALID(user);
1275 		ASSERT(user->u_session == session);
1276 
1277 		switch (user->u_state) {
1278 		case SMB_USER_STATE_LOGGING_ON:
1279 		case SMB_USER_STATE_LOGGED_ON:
1280 			smb_user_hold_internal(user);
1281 			smb_user_logoff(user);
1282 			smb_user_release(user);
1283 			break;
1284 
1285 		case SMB_USER_STATE_LOGGED_OFF:
1286 		case SMB_USER_STATE_LOGGING_OFF:
1287 			break;
1288 
1289 		default:
1290 			ASSERT(0);
1291 			break;
1292 		}
1293 
1294 		user = smb_llist_next(&session->s_user_list, user);
1295 	}
1296 
1297 	smb_llist_exit(&session->s_user_list);
1298 }
1299 
1300 /*
1301  * Copy the session workstation/client name to buf.  If the workstation
1302  * is an empty string (which it will be on TCP connections), use the
1303  * client IP address.
1304  */
1305 void
1306 smb_session_getclient(smb_session_t *sn, char *buf, size_t buflen)
1307 {
1308 
1309 	*buf = '\0';
1310 
1311 	if (sn->workstation[0] != '\0') {
1312 		(void) strlcpy(buf, sn->workstation, buflen);
1313 		return;
1314 	}
1315 
1316 	(void) strlcpy(buf, sn->ip_addr_str, buflen);
1317 }
1318 
1319 /*
1320  * Check whether or not the specified client name is the client of this
1321  * session.  The name may be in UNC format (\\CLIENT).
1322  *
1323  * A workstation/client name is setup on NBT connections as part of the
1324  * NetBIOS session request but that isn't available on TCP connections.
1325  * If the session doesn't have a client name we typically return the
1326  * client IP address as the workstation name on MSRPC requests.  So we
1327  * check for the IP address here in addition to the workstation name.
1328  */
1329 boolean_t
1330 smb_session_isclient(smb_session_t *sn, const char *client)
1331 {
1332 
1333 	client += strspn(client, "\\");
1334 
1335 	if (smb_strcasecmp(client, sn->workstation, 0) == 0)
1336 		return (B_TRUE);
1337 
1338 	if (smb_strcasecmp(client, sn->ip_addr_str, 0) == 0)
1339 		return (B_TRUE);
1340 
1341 	return (B_FALSE);
1342 }
1343 
1344 /*
1345  * smb_request_alloc
1346  *
1347  * Allocate an smb_request_t structure from the kmem_cache.  Partially
1348  * initialize the found/new request.
1349  *
1350  * Returns pointer to a request, or NULL if the session state is
1351  * one in which new requests are no longer allowed.
1352  */
1353 smb_request_t *
1354 smb_request_alloc(smb_session_t *session, int req_length)
1355 {
1356 	smb_request_t	*sr;
1357 
1358 	ASSERT(session->s_magic == SMB_SESSION_MAGIC);
1359 	ASSERT(req_length <= session->cmd_max_bytes);
1360 
1361 	sr = kmem_cache_alloc(smb_cache_request, KM_SLEEP);
1362 
1363 	/*
1364 	 * Future:  Use constructor to pre-initialize some fields.  For now
1365 	 * there are so many fields that it is easiest just to zero the
1366 	 * whole thing and start over.
1367 	 */
1368 	bzero(sr, sizeof (smb_request_t));
1369 
1370 	mutex_init(&sr->sr_mutex, NULL, MUTEX_DEFAULT, NULL);
1371 	smb_srm_init(sr);
1372 	sr->session = session;
1373 	sr->sr_server = session->s_server;
1374 	sr->sr_gmtoff = session->s_server->si_gmtoff;
1375 	sr->sr_cfg = &session->s_cfg;
1376 	sr->command.max_bytes = req_length;
1377 	sr->reply.max_bytes = session->reply_max_bytes;
1378 	sr->sr_req_length = req_length;
1379 	if (req_length)
1380 		sr->sr_request_buf = kmem_alloc(req_length, KM_SLEEP);
1381 	sr->sr_magic = SMB_REQ_MAGIC;
1382 	sr->sr_state = SMB_REQ_STATE_INITIALIZING;
1383 
1384 	/*
1385 	 * Only allow new SMB requests in some states.
1386 	 */
1387 	smb_rwx_rwenter(&session->s_lock, RW_WRITER);
1388 	switch (session->s_state) {
1389 	case SMB_SESSION_STATE_CONNECTED:
1390 	case SMB_SESSION_STATE_INITIALIZED:
1391 	case SMB_SESSION_STATE_ESTABLISHED:
1392 	case SMB_SESSION_STATE_NEGOTIATED:
1393 		smb_slist_insert_tail(&session->s_req_list, sr);
1394 		break;
1395 
1396 	default:
1397 		ASSERT(0);
1398 		/* FALLTHROUGH */
1399 	case SMB_SESSION_STATE_DISCONNECTED:
1400 	case SMB_SESSION_STATE_TERMINATED:
1401 		/* Disallow new requests in these states. */
1402 		if (sr->sr_request_buf)
1403 			kmem_free(sr->sr_request_buf, sr->sr_req_length);
1404 		sr->session = NULL;
1405 		sr->sr_magic = 0;
1406 		mutex_destroy(&sr->sr_mutex);
1407 		kmem_cache_free(smb_cache_request, sr);
1408 		sr = NULL;
1409 		break;
1410 	}
1411 	smb_rwx_rwexit(&session->s_lock);
1412 
1413 	return (sr);
1414 }
1415 
1416 /*
1417  * smb_request_free
1418  *
1419  * release the memories which have been allocated for a smb request.
1420  */
1421 void
1422 smb_request_free(smb_request_t *sr)
1423 {
1424 	ASSERT(sr->sr_magic == SMB_REQ_MAGIC);
1425 	ASSERT(sr->session);
1426 	ASSERT(sr->r_xa == NULL);
1427 
1428 	if (sr->fid_ofile != NULL) {
1429 		smb_ofile_request_complete(sr->fid_ofile);
1430 		smb_ofile_release(sr->fid_ofile);
1431 	}
1432 
1433 	if (sr->tid_tree != NULL)
1434 		smb_tree_release(sr->tid_tree);
1435 
1436 	if (sr->uid_user != NULL)
1437 		smb_user_release(sr->uid_user);
1438 
1439 	/*
1440 	 * The above may have left work on the delete queues
1441 	 */
1442 	smb_llist_flush(&sr->session->s_tree_list);
1443 	smb_llist_flush(&sr->session->s_user_list);
1444 
1445 	smb_slist_remove(&sr->session->s_req_list, sr);
1446 
1447 	sr->session = NULL;
1448 
1449 	smb_srm_fini(sr);
1450 
1451 	if (sr->sr_request_buf)
1452 		kmem_free(sr->sr_request_buf, sr->sr_req_length);
1453 	if (sr->command.chain)
1454 		m_freem(sr->command.chain);
1455 	if (sr->reply.chain)
1456 		m_freem(sr->reply.chain);
1457 	if (sr->raw_data.chain)
1458 		m_freem(sr->raw_data.chain);
1459 
1460 	sr->sr_magic = 0;
1461 	mutex_destroy(&sr->sr_mutex);
1462 	kmem_cache_free(smb_cache_request, sr);
1463 }
1464 
1465 boolean_t
1466 smb_session_oplocks_enable(smb_session_t *session)
1467 {
1468 	SMB_SESSION_VALID(session);
1469 	if (session->s_cfg.skc_oplock_enable == 0)
1470 		return (B_FALSE);
1471 	else
1472 		return (B_TRUE);
1473 }
1474 
1475 boolean_t
1476 smb_session_levelII_oplocks(smb_session_t *session)
1477 {
1478 	SMB_SESSION_VALID(session);
1479 
1480 	/* Clients using SMB2 and later always know about oplocks. */
1481 	if (session->dialect > NT_LM_0_12)
1482 		return (B_TRUE);
1483 
1484 	/* Older clients only do Level II oplocks if negotiated. */
1485 	if ((session->capabilities & CAP_LEVEL_II_OPLOCKS) != 0)
1486 		return (B_TRUE);
1487 
1488 	return (B_FALSE);
1489 }
1490 
1491 /*
1492  * smb_session_oplock_break
1493  *
1494  * Send an oplock break request to the client,
1495  * recalling some cache delegation.
1496  */
1497 void
1498 smb_session_oplock_break(smb_request_t *sr, uint8_t brk)
1499 {
1500 	smb_session_t	*session = sr->session;
1501 	mbuf_chain_t	*mbc = &sr->reply;
1502 
1503 	SMB_SESSION_VALID(session);
1504 
1505 	/*
1506 	 * Build the break message in sr->reply and then send it.
1507 	 * The mbc is free'd later, in smb_request_free().
1508 	 */
1509 	mbc->max_bytes = MLEN;
1510 	if (session->dialect <= NT_LM_0_12) {
1511 		smb1_oplock_break_notification(sr, brk);
1512 	} else {
1513 		smb2_oplock_break_notification(sr, brk);
1514 	}
1515 
1516 	(void) smb_session_send(session, 0, mbc);
1517 }
1518 
1519 static void
1520 smb_session_genkey(smb_session_t *session)
1521 {
1522 	uint8_t		tmp_key[SMB_CHALLENGE_SZ];
1523 
1524 	(void) random_get_pseudo_bytes(tmp_key, SMB_CHALLENGE_SZ);
1525 	bcopy(tmp_key, &session->challenge_key, SMB_CHALLENGE_SZ);
1526 	session->challenge_len = SMB_CHALLENGE_SZ;
1527 
1528 	(void) random_get_pseudo_bytes(tmp_key, 4);
1529 	session->sesskey = tmp_key[0] | tmp_key[1] << 8 |
1530 	    tmp_key[2] << 16 | tmp_key[3] << 24;
1531 }
1532