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