xref: /titanic_50/usr/src/uts/common/fs/smbsrv/smb_session.c (revision 8142c2b2a11acff39ec7e0576c566a751eb30ba6)
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 2007 Sun Microsystems, Inc.  All rights reserved.
23  * Use is subject to license terms.
24  */
25 
26 #pragma ident	"%Z%%M%	%I%	%E% SMI"
27 
28 #include <sys/atomic.h>
29 #include <sys/strsubr.h>
30 #include <sys/synch.h>
31 #include <sys/types.h>
32 #include <sys/socketvar.h>
33 #include <sys/sdt.h>
34 #include <smbsrv/netbios.h>
35 #include <smbsrv/smb_incl.h>
36 #include <smbsrv/smb_i18n.h>
37 
38 extern int smb_maxbufsize;
39 
40 extern unsigned int smb_nt_tcp_rcvbuf;
41 
42 uint32_t			smb_keep_alive = SSN_KEEP_ALIVE_TIMEOUT;
43 uint32_t			smb_send_retries = 0;
44 uint32_t			smb_receive_retries = 0;
45 
46 static int smb_session_message(smb_session_t *);
47 static int smb_session_xprt_puthdr(smb_session_t *, smb_xprt_t *,
48     uint8_t *, size_t);
49 
50 void smb_request_init_command_mbuf(smb_request_t *sr);
51 static void smb_session_wakeup_daemon(smb_thread_t *thread, void *so_void);
52 
53 
54 void
55 smb_timers(smb_thread_t *thread, void *si_void)
56 {
57 	smb_info_t	*si = si_void;
58 	smb_session_t	*sn;
59 
60 	ASSERT(si != NULL);
61 
62 	while (smb_thread_continue_timedwait(thread, 1 /* Seconds */)) {
63 		/*
64 		 * Walk through the table and decrement each keep_alive
65 		 * timer that has not timed out yet. (keepalive > 0)
66 		 */
67 		smb_svcstate_lock_read(&si->si_svc_sm_ctx);
68 
69 		sn = NULL;
70 		while ((sn = smb_svcstate_session_getnext(&si->si_svc_sm_ctx,
71 		    sn)) != NULL) {
72 			ASSERT(sn->s_magic == SMB_SESSION_MAGIC);
73 			if (sn->keep_alive && (sn->keep_alive != (uint32_t)-1))
74 				sn->keep_alive--;
75 		}
76 		smb_svcstate_unlock(&smb_info.si_svc_sm_ctx);
77 
78 	}
79 }
80 
81 /*
82  * smb_reconnection_check
83  *
84  * This function is called when a client indicates its current connection
85  * should be the only one it has with the server, as indicated by VC=0 in
86  * a SessionSetupX request. We go through the session list and destroy any
87  * stale connections for that client.
88  *
89  * Clients don't associate IP addresses and servers. So a client may make
90  * independent connections (i.e. with VC=0) to a server with multiple
91  * IP addresses. So, when checking for a reconnection, we need to include
92  * the local IP address, to which the client is connecting, when checking
93  * for stale sessions.
94  *
95  * Also check the server's NetBIOS name to support simultaneous access by
96  * multiple clients behind a NAT server.  This will only work for SMB over
97  * NetBIOS on TCP port 139, it will not work SMB over TCP port 445 because
98  * there is no NetBIOS name.  See also Knowledge Base article Q301673.
99  */
100 void
101 smb_reconnection_check(struct smb_session *session)
102 {
103 	smb_info_t		*si = &smb_info;
104 	smb_session_t		*sn;
105 
106 	smb_svcstate_lock_read(&si->si_svc_sm_ctx);
107 
108 	sn = NULL;
109 	while ((sn = smb_svcstate_session_getnext(&si->si_svc_sm_ctx, sn))
110 	    != NULL) {
111 
112 		ASSERT(sn->s_magic == SMB_SESSION_MAGIC);
113 		if ((sn != session) &&
114 		    (sn->ipaddr == session->ipaddr) &&
115 		    (sn->local_ipaddr == session->local_ipaddr) &&
116 		    (strcasecmp(sn->workstation, session->workstation) == 0) &&
117 		    (sn->opentime <= session->opentime) &&
118 		    (sn->s_kid < session->s_kid)) {
119 			smb_thread_stop(&sn->s_thread);
120 		}
121 	}
122 
123 	smb_svcstate_unlock(&smb_info.si_svc_sm_ctx);
124 }
125 
126 
127 void
128 smb_correct_keep_alive_values(uint32_t new_keep_alive)
129 {
130 	smb_info_t		*si = &smb_info;
131 	smb_session_t		*sn;
132 
133 	if (new_keep_alive == smb_keep_alive)
134 		return;
135 	/*
136 	 * keep alive == 0 means do not drop connection if it's idle
137 	 */
138 	smb_keep_alive = (new_keep_alive) ? new_keep_alive : -1;
139 
140 	/*
141 	 * Walk through the table and set each session to the new keep_alive
142 	 * value if they have not already timed out.  Block clock interrupts.
143 	 */
144 	smb_svcstate_lock_read(&si->si_svc_sm_ctx);
145 
146 	sn = NULL;
147 	while ((sn = smb_svcstate_session_getnext(&si->si_svc_sm_ctx, sn))
148 	    != NULL) {
149 		if (sn->keep_alive)
150 			sn->keep_alive = new_keep_alive;
151 	}
152 
153 	smb_svcstate_unlock(&smb_info.si_svc_sm_ctx);
154 }
155 
156 /*
157  * Send a session message - supports SMB-over-NBT and SMB-over-TCP.
158  *
159  * The mbuf chain is copied into a contiguous buffer so that the whole
160  * message is submitted to smb_sosend as a single request.  This should
161  * help Ethereal/Wireshark delineate the packets correctly even though
162  * TCP_NODELAY has been set on the socket.
163  *
164  * If an mbuf chain is provided, it will be freed and set to NULL here.
165  */
166 int
167 smb_session_send(smb_session_t *session, uint8_t type, struct mbuf_chain *mbc)
168 {
169 	struct mbuf	*m = 0;
170 	uint8_t *buf;
171 	smb_xprt_t hdr;
172 	int count = 0;
173 	int rc;
174 
175 	switch (session->s_state) {
176 	case SMB_SESSION_STATE_DISCONNECTED:
177 	case SMB_SESSION_STATE_TERMINATED:
178 		if ((mbc != NULL) && (mbc->chain != NULL)) {
179 			m_freem(mbc->chain);
180 			mbc->chain = NULL;
181 			mbc->flags = 0;
182 		}
183 		return (ENOTCONN);
184 	default:
185 		break;
186 	}
187 
188 	buf = kmem_alloc(NETBIOS_REQ_MAX_SIZE, KM_SLEEP);
189 
190 	if ((mbc != NULL) && (mbc->chain != NULL)) {
191 		count = NETBIOS_HDR_SZ;	/* Account for the NBT header. */
192 		m = mbc->chain;
193 
194 		while (m) {
195 			if ((count + m->m_len) > NETBIOS_REQ_MAX_SIZE) {
196 				kmem_free(buf, NETBIOS_REQ_MAX_SIZE);
197 				m_freem(mbc->chain);
198 				mbc->chain = NULL;
199 				mbc->flags = 0;
200 				return (EMSGSIZE);
201 			}
202 			bcopy(m->m_data, buf + count, m->m_len);
203 			count += m->m_len;
204 			m = m->m_next;
205 		}
206 
207 		m_freem(mbc->chain);
208 		mbc->chain = NULL;
209 		mbc->flags = 0;
210 		count -= NETBIOS_HDR_SZ;
211 	}
212 
213 	hdr.xh_type = type;
214 	hdr.xh_length = count;
215 
216 	rc = smb_session_xprt_puthdr(session, &hdr, buf, NETBIOS_HDR_SZ);
217 	if (rc == 0) {
218 		count += NETBIOS_HDR_SZ;
219 		rc = smb_sosend(session->sock, buf, count);
220 	}
221 
222 	kmem_free(buf, NETBIOS_REQ_MAX_SIZE);
223 	return (rc);
224 }
225 
226 /*
227  * Read, process and respond to a NetBIOS session request.
228  *
229  * A NetBIOS session must be established for SMB-over-NetBIOS.  Validate
230  * the calling and called name format and save the client NetBIOS name,
231  * which is used when a NetBIOS session is established to check for and
232  * cleanup leftover state from a previous session.
233  *
234  * Session requests are not valid for SMB-over-TCP, which is unfortunate
235  * because without the client name leftover state cannot be cleaned up
236  * if the client is behind a NAT server.
237  */
238 static int
239 smb_session_request(struct smb_session *session)
240 {
241 	int			rc;
242 	char			*calling_name;
243 	char			*called_name;
244 	char 			client_name[NETBIOS_NAME_SZ];
245 	struct mbuf_chain 	mbc;
246 	char 			*names = NULL;
247 	mts_wchar_t		*wbuf = NULL;
248 	smb_xprt_t		hdr;
249 	char *p;
250 	unsigned int cpid = oem_get_smb_cpid();
251 	int rc1, rc2;
252 
253 	session->keep_alive = smb_keep_alive;
254 
255 	if (smb_session_xprt_gethdr(session, &hdr) != 0)
256 		return (EINVAL);
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_encode_mbc(&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 (mts_wchar_t)), KM_SLEEP);
312 	(void) oemstounicodes(wbuf, client_name, SMB_PI_MAX_HOST, cpid);
313 	(void) mts_wcstombs(session->workstation, wbuf, SMB_PI_MAX_HOST);
314 	kmem_free(wbuf, (SMB_PI_MAX_HOST * sizeof (mts_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 	unsigned char buf[NETBIOS_HDR_SZ];
336 
337 	if (smb_sorecv(session->sock, buf, NETBIOS_HDR_SZ) != 0)
338 		return (-1);
339 
340 	switch (session->s_local_port) {
341 	case SSN_SRVC_TCP_PORT:
342 		ret_hdr->xh_type = buf[0];
343 		ret_hdr->xh_length = (((uint32_t)buf[1] & 1) << 16) |
344 		    ((uint32_t)buf[2] << 8) |
345 		    ((uint32_t)buf[3]);
346 		break;
347 
348 	case SMB_SRVC_TCP_PORT:
349 		ret_hdr->xh_type = buf[0];
350 
351 		if (ret_hdr->xh_type != 0) {
352 			cmn_err(CE_WARN, "0x%08x: invalid type (%u)",
353 			    session->ipaddr, ret_hdr->xh_type);
354 			return (-1);
355 		}
356 
357 		ret_hdr->xh_length = ((uint32_t)buf[1] << 16) |
358 		    ((uint32_t)buf[2] << 8) |
359 		    ((uint32_t)buf[3]);
360 		break;
361 
362 	default:
363 		cmn_err(CE_WARN, "0x%08x: invalid port %u",
364 		    session->ipaddr, session->s_local_port);
365 		return (-1);
366 	}
367 
368 	return (0);
369 }
370 
371 /*
372  * Encode a transport session packet header into a 4-byte buffer.
373  * See smb_xprt_t definition for header format information.
374  */
375 static int
376 smb_session_xprt_puthdr(smb_session_t *session, smb_xprt_t *hdr,
377     uint8_t *buf, size_t buflen)
378 {
379 	if (session == NULL || hdr == NULL ||
380 	    buf == NULL || buflen < NETBIOS_HDR_SZ) {
381 		return (-1);
382 	}
383 
384 	switch (session->s_local_port) {
385 	case SSN_SRVC_TCP_PORT:
386 		buf[0] = hdr->xh_type;
387 		buf[1] = ((hdr->xh_length >> 16) & 1);
388 		buf[2] = (hdr->xh_length >> 8) & 0xff;
389 		buf[3] = hdr->xh_length & 0xff;
390 		break;
391 
392 	case SMB_SRVC_TCP_PORT:
393 		buf[0] = hdr->xh_type;
394 		buf[1] = (hdr->xh_length >> 16) & 0xff;
395 		buf[2] = (hdr->xh_length >> 8) & 0xff;
396 		buf[3] = hdr->xh_length & 0xff;
397 		break;
398 
399 	default:
400 		cmn_err(CE_WARN, "0x%08x: invalid port (%u)",
401 		    session->ipaddr, session->s_local_port);
402 		return (-1);
403 	}
404 
405 	return (0);
406 }
407 
408 /*
409  * smb_request_alloc
410  *
411  * Allocate an smb_request_t structure from the kmem_cache.  Partially
412  * initialize the found/new request.
413  *
414  * Returns pointer to a request
415  */
416 smb_request_t *
417 smb_request_alloc(struct smb_session *session, int req_length)
418 {
419 	struct smb_request *sr;
420 
421 	sr = kmem_cache_alloc(smb_info.si_cache_request, KM_SLEEP);
422 
423 	/*
424 	 * Future:  Use constructor to pre-initialize some fields.  For now
425 	 * there are so many fields that it is easiest just to zero the
426 	 * whole thing and start over.
427 	 */
428 	bzero(sr, sizeof (smb_request_t));
429 
430 	mutex_init(&sr->sr_mutex, NULL, MUTEX_DEFAULT, NULL);
431 	sr->session = session;
432 	sr->request_storage.forw = &sr->request_storage;
433 	sr->request_storage.back = &sr->request_storage;
434 	sr->command.max_bytes = req_length;
435 	sr->reply.max_bytes = smb_maxbufsize;
436 	sr->sr_req_length = req_length;
437 	sr->sr_request_buf = kmem_alloc(req_length, KM_SLEEP);
438 	sr->sr_magic = SMB_REQ_MAGIC;
439 	sr->sr_state = SMB_REQ_STATE_INITIALIZING;
440 	smb_slist_insert_tail(&session->s_req_list, sr);
441 	return (sr);
442 }
443 
444 void
445 smb_request_init_command_mbuf(smb_request_t *sr)
446 {
447 	MGET(sr->command.chain, 0, MT_DATA);
448 
449 	/*
450 	 * Setup mbuf, mimic MCLGET but use the complete packet buffer.
451 	 */
452 	sr->command.chain->m_ext.ext_buf = sr->sr_request_buf;
453 	sr->command.chain->m_data = sr->command.chain->m_ext.ext_buf;
454 	sr->command.chain->m_len = sr->sr_req_length;
455 	sr->command.chain->m_flags |= M_EXT;
456 	sr->command.chain->m_ext.ext_size = sr->sr_req_length;
457 	sr->command.chain->m_ext.ext_ref = &mclrefnoop;
458 
459 	/*
460 	 * Initialize the rest of the mbuf_chain fields
461 	 */
462 	sr->command.flags = 0;
463 	sr->command.shadow_of = 0;
464 	sr->command.max_bytes = sr->sr_req_length;
465 	sr->command.chain_offset = 0;
466 }
467 
468 /*
469  * smb_request_cancel
470  *
471  * Handle a cancel for a request properly depending on the current request
472  * state.
473  */
474 void
475 smb_request_cancel(smb_request_t *sr)
476 {
477 	mutex_enter(&sr->sr_mutex);
478 	switch (sr->sr_state) {
479 
480 	case SMB_REQ_STATE_SUBMITTED:
481 	case SMB_REQ_STATE_ACTIVE:
482 	case SMB_REQ_STATE_CLEANED_UP:
483 		sr->sr_state = SMB_REQ_STATE_CANCELED;
484 		break;
485 
486 	case SMB_REQ_STATE_WAITING_LOCK:
487 		/*
488 		 * This request is waiting on a lock.  Wakeup everything
489 		 * waiting on the lock so that the relevant thread regains
490 		 * control and notices that is has been canceled.  The
491 		 * other lock request threads waiting on this lock will go
492 		 * back to sleep when they discover they are still blocked.
493 		 */
494 		sr->sr_state = SMB_REQ_STATE_CANCELED;
495 
496 		ASSERT(sr->sr_awaiting != NULL);
497 		mutex_enter(&sr->sr_awaiting->l_mutex);
498 		cv_broadcast(&sr->sr_awaiting->l_cv);
499 		mutex_exit(&sr->sr_awaiting->l_mutex);
500 
501 		break;
502 
503 	case SMB_REQ_STATE_WAITING_EVENT:
504 	case SMB_REQ_STATE_EVENT_OCCURRED:
505 		/*
506 		 * Cancellations for these states are handled by the
507 		 * notify-change code
508 		 */
509 		break;
510 
511 	case SMB_REQ_STATE_COMPLETED:
512 	case SMB_REQ_STATE_CANCELED:
513 		/*
514 		 * No action required for these states since the request
515 		 * is completing.
516 		 */
517 		break;
518 	/*
519 	 * Cases included:
520 	 *	SMB_REQ_STATE_FREE:
521 	 *	SMB_REQ_STATE_INITIALIZING:
522 	 */
523 	default:
524 		ASSERT(0);
525 		break;
526 	}
527 	mutex_exit(&sr->sr_mutex);
528 }
529 
530 /*
531  * smb_request_free
532  *
533  * release the memories which have been allocated for a smb request.
534  */
535 void
536 smb_request_free(smb_request_t *sr)
537 {
538 	ASSERT(sr->session);
539 
540 	ASSERT(sr->fid_ofile == NULL);
541 	ASSERT(sr->sid_odir == NULL);
542 	ASSERT(sr->tid_tree == NULL);
543 	ASSERT(sr->uid_user == NULL);
544 	ASSERT(sr->r_xa == NULL);
545 
546 	smb_slist_remove(&sr->session->s_req_list, sr);
547 
548 	sr->session = 0;
549 
550 	/* Release any temp storage */
551 	smbsr_free_malloc_list(&sr->request_storage);
552 
553 	if (sr->sr_request_buf)
554 		kmem_free(sr->sr_request_buf, sr->sr_req_length);
555 	if (sr->command.chain)
556 		m_freem(sr->command.chain);
557 	if (sr->reply.chain)
558 		m_freem(sr->reply.chain);
559 	if (sr->raw_data.chain)
560 		m_freem(sr->raw_data.chain);
561 
562 	sr->sr_magic = (uint32_t)~SMB_REQ_MAGIC;
563 	mutex_destroy(&sr->sr_mutex);
564 	kmem_cache_free(smb_info.si_cache_request, sr);
565 }
566 
567 /*ARGSUSED*/
568 void
569 smb_wakeup_session_daemon(smb_thread_t *thread, void *session_void)
570 {
571 	struct smb_session	*session = session_void;
572 
573 	ASSERT(session);
574 	ASSERT(session->s_magic == SMB_SESSION_MAGIC);
575 
576 	smb_rwx_rwenter(&session->s_lock, RW_WRITER);
577 	switch (session->s_state) {
578 	case SMB_SESSION_STATE_TERMINATED:
579 	case SMB_SESSION_STATE_DISCONNECTED:
580 		break;
581 	default:
582 		smb_soshutdown(session->sock);
583 		break;
584 	}
585 	smb_rwx_rwexit(&session->s_lock);
586 }
587 
588 /*
589  * This is the entry point for processing SMB messages over NetBIOS or
590  * SMB-over-TCP.
591  *
592  * NetBIOS connections require a session request to establish a session
593  * on which to send session messages.
594  *
595  * Session requests are not valid on SMB-over-TCP.  We don't need to do
596  * anything here as session requests will be treated as an error when
597  * handling session messages.
598  */
599 /*ARGSUSED*/
600 void
601 smb_session_daemon(smb_thread_t *thread, void *session_void)
602 {
603 	struct smb_session *session = session_void;
604 	int rc = 0;
605 
606 	ASSERT(session != NULL);
607 
608 	if (session->s_local_port == SSN_SRVC_TCP_PORT)
609 		rc = smb_session_request(session);
610 
611 	smb_rwx_rwenter(&session->s_lock, RW_WRITER);
612 
613 	if ((rc == 0) || (session->s_local_port == SMB_SRVC_TCP_PORT))
614 		session->s_state = SMB_SESSION_STATE_ESTABLISHED;
615 	else
616 		session->s_state = SMB_SESSION_STATE_DISCONNECTED;
617 
618 	while (session->s_state != SMB_SESSION_STATE_DISCONNECTED) {
619 		smb_rwx_rwexit(&session->s_lock);
620 
621 		rc = smb_session_message(session);
622 
623 		smb_rwx_rwenter(&session->s_lock, RW_WRITER);
624 
625 		if (rc != 0)
626 			break;
627 	}
628 
629 	smb_soshutdown(session->sock);
630 	session->s_state = SMB_SESSION_STATE_DISCONNECTED;
631 	smb_rwx_rwexit(&session->s_lock);
632 
633 	DTRACE_PROBE2(session__drop, struct session *, session, int, rc);
634 
635 	smb_session_cancel(session);
636 
637 	/*
638 	 * At this point everything related to the session should have been
639 	 * cleaned up and we expect that nothing will attempt to use the
640 	 * socket.
641 	 */
642 	smb_rwx_rwenter(&session->s_lock, RW_WRITER);
643 	session->s_state = SMB_SESSION_STATE_TERMINATED;
644 	smb_sodestroy(session->sock);
645 	session->sock = NULL;
646 	smb_rwx_rwexit(&session->s_lock);
647 
648 	/*
649 	 * Notify SMB service state machine so it can cleanup the session
650 	 */
651 	smb_svcstate_event(SMB_SVCEVT_SESSION_DELETE, (uintptr_t)session);
652 }
653 
654 /*
655  * Read and process SMB requests.
656  *
657  * Returns:
658  *	0	Success
659  *	1	Unable to read transport header
660  *	2	Invalid transport header type
661  *	3	Invalid SMB length (too small)
662  *	4	Unable to read SMB header
663  *	5	Invalid SMB header (bad magic number)
664  *	6	Unable to read SMB data
665  *	2x	Write raw failed
666  */
667 static int
668 smb_session_message(smb_session_t *session)
669 {
670 	struct smb_request *sr = NULL;
671 	smb_xprt_t hdr;
672 	uint8_t *req_buf;
673 	uint32_t resid;
674 	int rc;
675 
676 	if (smb_session_xprt_gethdr(session, &hdr) != 0)
677 		return (1);
678 
679 	DTRACE_PROBE2(session__receive__xprthdr, struct session *, session,
680 	    smb_xprt_t *, &hdr);
681 
682 	if (hdr.xh_type != SESSION_MESSAGE) {
683 		/*
684 		 * Anything other than SESSION_MESSAGE or SESSION_KEEP_ALIVE
685 		 * is an error.  A SESSION_REQUEST may indicate a new session
686 		 * request but we need to close this session and we can treat
687 		 * it as an error here.
688 		 */
689 		if (hdr.xh_type == SESSION_KEEP_ALIVE) {
690 			session->keep_alive = smb_keep_alive;
691 			return (0);
692 		}
693 
694 		return (2);
695 	}
696 
697 	if (hdr.xh_length < SMB_HEADER_LEN)
698 		return (3);
699 
700 	session->keep_alive = smb_keep_alive;
701 
702 	/*
703 	 * Allocate a request context, read the SMB header and validate it.
704 	 * The sr includes a buffer large enough to hold the SMB request
705 	 * payload.  If the header looks valid, read any remaining data.
706 	 */
707 	sr = smb_request_alloc(session, hdr.xh_length);
708 
709 	req_buf = (uint8_t *)sr->sr_request_buf;
710 	resid = hdr.xh_length;
711 
712 	if (smb_sorecv(session->sock, req_buf, SMB_HEADER_LEN) != 0) {
713 		smb_request_free(sr);
714 		return (4);
715 	}
716 
717 	if (SMB_PROTOCOL_MAGIC_INVALID(sr)) {
718 		smb_request_free(sr);
719 		return (5);
720 	}
721 
722 	if (resid > SMB_HEADER_LEN) {
723 		req_buf += SMB_HEADER_LEN;
724 		resid -= SMB_HEADER_LEN;
725 
726 		if (smb_sorecv(session->sock, req_buf, resid) != 0) {
727 			smb_request_free(sr);
728 			return (6);
729 		}
730 	}
731 
732 	/*
733 	 * Initialize command MBC to represent the received data.
734 	 */
735 	smb_request_init_command_mbuf(sr);
736 
737 	DTRACE_PROBE1(session__receive__smb, smb_request_t *, sr);
738 
739 	/*
740 	 * If this is a raw write, hand off the request.  The handler
741 	 * will retrieve the remaining raw data and process the request.
742 	 */
743 	if (SMB_IS_WRITERAW(sr)) {
744 		rc = smb_handle_write_raw(session, sr);
745 		/* XXX smb_request_free(sr); ??? */
746 		return (rc);
747 	}
748 
749 	sr->sr_state = SMB_REQ_STATE_SUBMITTED;
750 	(void) taskq_dispatch(smb_info.thread_pool, smb_session_worker,
751 	    sr, TQ_SLEEP);
752 	return (0);
753 }
754 
755 /*
756  * smb_session_wakeup_daemon
757  *
758  * When the smbsrv kernel module/driver gets unloaded, chances are the
759  * smb_nbt_daemon and smb_tcp_daemon threads are blocked in soaccept.
760  * We can't get control of the threads until they return from soaccept.
761  * This function will attempt to connect to the SMB service via
762  * "localhost" to wake up the threads.
763  */
764 /*ARGSUSED*/
765 static void
766 smb_session_wakeup_daemon(smb_thread_t *thread, void *so_void)
767 {
768 	struct sonode	*so = so_void;
769 
770 	ASSERT(so != NULL);
771 
772 	mutex_enter(&so->so_lock);
773 	so->so_error = EINTR;
774 	cv_signal(&so->so_connind_cv);
775 	mutex_exit(&so->so_lock);
776 }
777 
778 /*
779  * SMB-over-NetBIOS service.
780  *
781  * Traditional SMB service over NetBIOS (port 139), which requires
782  * that a NetBIOS session be established.
783  */
784 void
785 smb_nbt_daemon(smb_thread_t *thread, void *arg)
786 {
787 	/* XXX Defaults for these values should come from smbd and SMF */
788 	uint32_t		txbuf_size = 128*1024;
789 	uint32_t		on = 1;
790 	struct smb_session	*session;
791 	struct sonode		*l_so, *s_so;
792 	struct sockaddr_in	sin;
793 	int			error;
794 	smb_info_t		*si = arg;
795 
796 	ASSERT(si != NULL);
797 	sin.sin_family = AF_INET;
798 	sin.sin_port = htons(SSN_SRVC_TCP_PORT);
799 	sin.sin_addr.s_addr = htonl(INADDR_ANY);
800 
801 	l_so = smb_socreate(AF_INET, SOCK_STREAM, 0);
802 	if (l_so == NULL) {
803 		cmn_err(CE_WARN, "NBT: socket create failed");
804 		smb_svcstate_event(SMB_SVCEVT_DISCONNECT, (uintptr_t)ENOMEM);
805 		return;
806 	}
807 
808 	(void) sosetsockopt(l_so, SOL_SOCKET, SO_REUSEADDR,
809 	    (const void *)&on, sizeof (on));
810 
811 	if ((error = sobind(l_so, (struct sockaddr *)&sin, sizeof (sin),
812 	    0, 0)) != 0) {
813 		cmn_err(CE_WARN, "NBT: bind failed");
814 		smb_soshutdown(l_so);
815 		smb_sodestroy(l_so);
816 		smb_svcstate_event(SMB_SVCEVT_DISCONNECT, (uintptr_t)error);
817 		return;
818 	}
819 	if ((error = solisten(l_so, 20)) < 0) {
820 		cmn_err(CE_WARN, "NBT: listen failed");
821 		smb_soshutdown(l_so);
822 		smb_sodestroy(l_so);
823 		smb_svcstate_event(SMB_SVCEVT_DISCONNECT, (uintptr_t)error);
824 		return;
825 	}
826 
827 	smb_thread_set_awaken(thread, smb_session_wakeup_daemon, l_so);
828 	si->si_connect_progress |= SMB_SI_NBT_CONNECTED;
829 	smb_svcstate_event(SMB_SVCEVT_CONNECT, NULL);
830 
831 	while (smb_thread_continue_nowait(thread)) {
832 		DTRACE_PROBE1(so__wait__accept, struct sonode *, l_so);
833 
834 		error = soaccept(l_so, 0, &s_so);
835 		if (error) {
836 			DTRACE_PROBE1(so__accept__error, int, error);
837 			if (error == EINTR) {
838 				continue;
839 			}
840 
841 			break;
842 		}
843 
844 		DTRACE_PROBE1(so__accept, struct sonode *, s_so);
845 
846 		(void) sosetsockopt(s_so, IPPROTO_TCP, TCP_NODELAY,
847 		    (const void *)&on, sizeof (on));
848 		(void) sosetsockopt(s_so, SOL_SOCKET, SO_KEEPALIVE,
849 		    (const void *)&on, sizeof (on));
850 		(void) sosetsockopt(s_so, SOL_SOCKET, SO_SNDBUF,
851 		    (const void *)&txbuf_size, sizeof (txbuf_size));
852 
853 		/*
854 		 * Create a session for this connection and notify the SMB
855 		 * service state machine.  The service state machine may
856 		 * start a session thread or reject the session depending
857 		 * on the current service state or number of connections.
858 		 */
859 		session = smb_session_create(s_so, SSN_SRVC_TCP_PORT);
860 		smb_svcstate_event(SMB_SVCEVT_SESSION_CREATE,
861 		    (uintptr_t)session);
862 
863 	}
864 
865 	smb_soshutdown(l_so);
866 	smb_sodestroy(l_so);
867 	si->si_connect_progress &= ~SMB_SI_NBT_CONNECTED;
868 	smb_svcstate_event(SMB_SVCEVT_DISCONNECT, (uintptr_t)error);
869 }
870 
871 /*
872  * SMB-over-TCP (or NetBIOS-less SMB) service.
873  *
874  * SMB service natively over TCP (port 445), i.e. no NetBIOS support.
875  */
876 void
877 smb_tcp_daemon(smb_thread_t *thread, void *arg)
878 {
879 	/* XXX Defaults for these values should come from smbd and SMF */
880 	uint32_t		txbuf_size = 128*1024;
881 	uint32_t		on = 1;
882 	struct smb_session	*session;
883 	struct sonode		*l_so, *s_so;
884 	struct sockaddr_in	sin;
885 	int			error;
886 	smb_info_t		*si = arg;
887 
888 	ASSERT(si != NULL);
889 	sin.sin_family = AF_INET;
890 	sin.sin_port = htons(SMB_SRVC_TCP_PORT);
891 	sin.sin_addr.s_addr = htonl(INADDR_ANY);
892 
893 	l_so = smb_socreate(AF_INET, SOCK_STREAM, 0);
894 	if (l_so == NULL) {
895 		cmn_err(CE_WARN, "TCP: socket create failed");
896 		smb_svcstate_event(SMB_SVCEVT_DISCONNECT, (uintptr_t)ENOMEM);
897 		return;
898 	}
899 
900 	(void) sosetsockopt(l_so, SOL_SOCKET, SO_REUSEADDR,
901 	    (const void *)&on, sizeof (on));
902 
903 	if ((error = sobind(l_so, (struct sockaddr *)&sin, sizeof (sin),
904 	    0, 0)) != 0) {
905 		cmn_err(CE_WARN, "TCP: bind failed");
906 		smb_soshutdown(l_so);
907 		smb_sodestroy(l_so);
908 		smb_svcstate_event(SMB_SVCEVT_DISCONNECT, (uintptr_t)error);
909 		return;
910 	}
911 	if ((error = solisten(l_so, 20)) < 0) {
912 		cmn_err(CE_WARN, "TCP: listen failed");
913 		smb_soshutdown(l_so);
914 		smb_sodestroy(l_so);
915 		smb_svcstate_event(SMB_SVCEVT_DISCONNECT, (uintptr_t)error);
916 		return;
917 	}
918 
919 	smb_thread_set_awaken(thread, smb_session_wakeup_daemon, l_so);
920 	si->si_connect_progress |= SMB_SI_TCP_CONNECTED;
921 	smb_svcstate_event(SMB_SVCEVT_CONNECT, NULL);
922 
923 	while (smb_thread_continue_nowait(thread)) {
924 		DTRACE_PROBE1(so__wait__accept, struct sonode *, l_so);
925 
926 		error = soaccept(l_so, 0, &s_so);
927 		if (error) {
928 			DTRACE_PROBE1(so__accept__error, int, error);
929 			if (error == EINTR) {
930 				continue;
931 			}
932 
933 			break;
934 		}
935 
936 		DTRACE_PROBE1(so__accept, struct sonode *, s_so);
937 
938 		(void) sosetsockopt(s_so, IPPROTO_TCP, TCP_NODELAY,
939 		    (const void *)&on, sizeof (on));
940 		(void) sosetsockopt(s_so, SOL_SOCKET, SO_KEEPALIVE,
941 		    (const void *)&on, sizeof (on));
942 		(void) sosetsockopt(s_so, SOL_SOCKET, SO_SNDBUF,
943 		    (const void *)&txbuf_size, sizeof (txbuf_size));
944 
945 		/*
946 		 * Create a session for this connection and notify the SMB
947 		 * service state machine.  The service state machine may
948 		 * start a session thread or reject the session depending
949 		 * on the current service state or number of connections.
950 		 */
951 		session = smb_session_create(s_so, SMB_SRVC_TCP_PORT);
952 		smb_svcstate_event(SMB_SVCEVT_SESSION_CREATE,
953 		    (uintptr_t)session);
954 
955 	}
956 
957 	smb_soshutdown(l_so);
958 	smb_sodestroy(l_so);
959 	si->si_connect_progress &= ~SMB_SI_TCP_CONNECTED;
960 	smb_svcstate_event(SMB_SVCEVT_DISCONNECT, (uintptr_t)error);
961 }
962 
963 /*
964  * smb_session_reject
965  *
966  * Build and send a NEGATIVE_SESSION_RESPONSE on the specified socket.
967  * The reason is written to the log.
968  */
969 /*ARGSUSED*/
970 void
971 smb_session_reject(smb_session_t *session, char *reason)
972 {
973 	unsigned char		reply[8];
974 
975 	smb_rwx_rwenter(&session->s_lock, RW_READER);
976 	if (session->sock != NULL) {
977 		reply[0] = NEGATIVE_SESSION_RESPONSE;
978 		reply[1] = 0;
979 		reply[2] = 0;
980 		reply[3] = 1;
981 		reply[4] = SESSION_INSUFFICIENT_RESOURCES;
982 
983 		(void) smb_sosend(session->sock, reply, 5);
984 	}
985 	smb_rwx_rwexit(&session->s_lock);
986 }
987 
988 /*
989  * Port will be SSN_SRVC_TCP_PORT or SMB_SRVC_TCP_PORT.
990  */
991 smb_session_t *
992 smb_session_create(struct sonode *new_so, uint16_t port)
993 {
994 	uint32_t		ipaddr;
995 	uint32_t		local_ipaddr;
996 	struct sockaddr_in	sin;
997 	smb_session_t		*session;
998 
999 	session = kmem_cache_alloc(smb_info.si_cache_session, KM_SLEEP);
1000 	bzero(session, sizeof (smb_session_t));
1001 
1002 	if (smb_idpool_constructor(&session->s_uid_pool)) {
1003 		kmem_cache_free(smb_info.si_cache_session, session);
1004 		return (NULL);
1005 	}
1006 
1007 	session->s_kid = SMB_NEW_KID();
1008 	session->s_state = SMB_SESSION_STATE_DISCONNECTED;
1009 	session->native_os = NATIVE_OS_UNKNOWN;
1010 	session->opentime = lbolt64;
1011 	session->keep_alive = smb_keep_alive;
1012 	session->activity_timestamp = lbolt64;
1013 
1014 	smb_slist_constructor(&session->s_req_list, sizeof (smb_request_t),
1015 	    offsetof(smb_request_t, sr_session_lnd));
1016 
1017 	smb_llist_constructor(&session->s_user_list, sizeof (smb_user_t),
1018 	    offsetof(smb_user_t, u_lnd));
1019 
1020 	smb_llist_constructor(&session->s_xa_list, sizeof (smb_xa_t),
1021 	    offsetof(smb_xa_t, xa_lnd));
1022 
1023 	smb_thread_init(&session->s_thread, "smb_session", &smb_session_daemon,
1024 	    session, smb_wakeup_session_daemon, session);
1025 
1026 	smb_rwx_init(&session->s_lock);
1027 
1028 	bcopy(new_so->so_faddr_sa, &sin, new_so->so_faddr_len);
1029 	ipaddr = sin.sin_addr.s_addr;
1030 
1031 	bcopy(new_so->so_laddr_sa, &sin, new_so->so_faddr_len);
1032 	local_ipaddr = sin.sin_addr.s_addr;
1033 
1034 	session->s_local_port = port;
1035 	session->ipaddr = ipaddr;
1036 	session->local_ipaddr = local_ipaddr;
1037 	session->sock = new_so;
1038 
1039 	session->s_magic = SMB_SESSION_MAGIC;
1040 	return (session);
1041 }
1042 
1043 void
1044 smb_session_delete(smb_session_t *session)
1045 {
1046 	ASSERT(session);
1047 	ASSERT(session->s_magic == SMB_SESSION_MAGIC);
1048 
1049 	session->s_magic = (uint32_t)~SMB_SESSION_MAGIC;
1050 
1051 	smb_rwx_destroy(&session->s_lock);
1052 	smb_thread_destroy(&session->s_thread);
1053 	smb_slist_destructor(&session->s_req_list);
1054 	smb_llist_destructor(&session->s_user_list);
1055 	smb_llist_destructor(&session->s_xa_list);
1056 
1057 	ASSERT(session->s_tree_cnt == 0);
1058 	ASSERT(session->s_file_cnt == 0);
1059 	ASSERT(session->s_dir_cnt == 0);
1060 
1061 	smb_idpool_destructor(&session->s_uid_pool);
1062 	kmem_cache_free(smb_info.si_cache_session, session);
1063 }
1064 
1065 void
1066 smb_session_cancel(smb_session_t *session)
1067 {
1068 	smb_xa_t	*xa, *nextxa;
1069 
1070 	/* All the request currently being treated must be canceled. */
1071 	smb_session_cancel_requests(session);
1072 
1073 	/*
1074 	 * We wait for the completion of all the requests associated with
1075 	 * this session.
1076 	 */
1077 	smb_slist_wait_for_empty(&session->s_req_list);
1078 
1079 	/*
1080 	 * At this point the reference count of the users, trees, files,
1081 	 * directories should be zero. It should be possible to destroy them
1082 	 * without any problem.
1083 	 */
1084 	xa = smb_llist_head(&session->s_xa_list);
1085 	while (xa) {
1086 		nextxa = smb_llist_next(&session->s_xa_list, xa);
1087 		smb_xa_close(xa);
1088 		xa = nextxa;
1089 	}
1090 	smb_user_logoff_all(session);
1091 }
1092 
1093 void
1094 smb_session_cancel_requests(
1095     smb_session_t	*session)
1096 {
1097 	smb_request_t	*sr;
1098 	smb_request_t	*tmp;
1099 
1100 	/* All the SMB requests on the notification queue are canceled. */
1101 	smb_process_session_notify_change_queue(session);
1102 
1103 	smb_slist_enter(&session->s_req_list);
1104 	sr = smb_slist_head(&session->s_req_list);
1105 	while (sr) {
1106 		ASSERT(sr->sr_magic == SMB_REQ_MAGIC);
1107 		tmp = smb_slist_next(&session->s_req_list, sr);
1108 
1109 		smb_request_cancel(sr);
1110 
1111 		sr = tmp;
1112 	}
1113 	smb_slist_exit(&session->s_req_list);
1114 }
1115 
1116 void
1117 smb_session_worker(
1118     void	*arg)
1119 {
1120 	smb_request_t	*sr;
1121 
1122 	sr = (smb_request_t *)arg;
1123 
1124 	ASSERT(sr != NULL);
1125 	ASSERT(sr->sr_magic == SMB_REQ_MAGIC);
1126 
1127 	mutex_enter(&sr->sr_mutex);
1128 	switch (sr->sr_state) {
1129 	case SMB_REQ_STATE_SUBMITTED:
1130 		mutex_exit(&sr->sr_mutex);
1131 		if (smb_dispatch_request(sr) < 0) {
1132 			smb_rwx_rwenter(&sr->session->s_lock, RW_WRITER);
1133 			if (sr->session->s_state !=
1134 			    SMB_SESSION_STATE_DISCONNECTED) {
1135 				smb_soshutdown(sr->session->sock);
1136 				sr->session->s_state =
1137 				    SMB_SESSION_STATE_DISCONNECTED;
1138 			}
1139 			smb_rwx_rwexit(&sr->session->s_lock);
1140 		}
1141 		mutex_enter(&sr->sr_mutex);
1142 		if (!sr->sr_keep) {
1143 			sr->sr_state = SMB_REQ_STATE_COMPLETED;
1144 			mutex_exit(&sr->sr_mutex);
1145 			smb_request_free(sr);
1146 			break;
1147 		}
1148 		mutex_exit(&sr->sr_mutex);
1149 		break;
1150 
1151 	default:
1152 		ASSERT(sr->sr_state == SMB_REQ_STATE_CANCELED);
1153 		sr->sr_state = SMB_REQ_STATE_COMPLETED;
1154 		mutex_exit(&sr->sr_mutex);
1155 		smb_request_free(sr);
1156 		break;
1157 	}
1158 }
1159 
1160 /*
1161  * smb_session_disconnect_share
1162  *
1163  * Disconnects the specified share. This function should be called after the
1164  * share passed in has been made unavailable by the "share manager".
1165  */
1166 void
1167 smb_session_disconnect_share(char *sharename)
1168 {
1169 	smb_session_t	*session;
1170 
1171 	smb_svcstate_lock_read(&smb_info.si_svc_sm_ctx);
1172 
1173 	session = NULL;
1174 	while ((session = smb_svcstate_session_getnext(&smb_info.si_svc_sm_ctx,
1175 	    session)) != NULL) {
1176 
1177 		ASSERT(session->s_magic == SMB_SESSION_MAGIC);
1178 		smb_rwx_rwenter(&session->s_lock, RW_READER);
1179 		switch (session->s_state) {
1180 		case SMB_SESSION_STATE_NEGOTIATED:
1181 		case SMB_SESSION_STATE_OPLOCK_BREAKING:
1182 		case SMB_SESSION_STATE_WRITE_RAW_ACTIVE: {
1183 			smb_user_t	*user;
1184 			smb_user_t	*next;
1185 
1186 			user = smb_user_lookup_by_state(session, NULL);
1187 			while (user) {
1188 				smb_user_disconnect_share(user, sharename);
1189 				next = smb_user_lookup_by_state(session, user);
1190 				smb_user_release(user);
1191 				user = next;
1192 			}
1193 			break;
1194 
1195 		}
1196 		default:
1197 			break;
1198 		}
1199 		smb_rwx_rwexit(&session->s_lock);
1200 	}
1201 	smb_svcstate_unlock(&smb_info.si_svc_sm_ctx);
1202 }
1203 
1204 /*
1205  * smb_session_disconnect_volume
1206  *
1207  * This function is called when a volume is deleted. We need to ensure
1208  * all trees with a reference to the volume are destroyed before we
1209  * discard the fs_online. Before destroying each tree, we notify any
1210  * in-progress requests and give them a chance to complete.
1211  *
1212  * NOTE:
1213  * We shouldn't be accepting any new connection on this volume while
1214  * we are in this function.
1215  */
1216 void
1217 smb_session_disconnect_volume(fs_desc_t *fsd)
1218 {
1219 	smb_session_t	*session;
1220 
1221 	smb_svcstate_lock_read(&smb_info.si_svc_sm_ctx);
1222 
1223 	session = NULL;
1224 	while ((session = smb_svcstate_session_getnext(&smb_info.si_svc_sm_ctx,
1225 	    session)) != NULL) {
1226 
1227 		ASSERT(session->s_magic == SMB_SESSION_MAGIC);
1228 		smb_rwx_rwenter(&session->s_lock, RW_READER);
1229 		switch (session->s_state) {
1230 		case SMB_SESSION_STATE_NEGOTIATED:
1231 		case SMB_SESSION_STATE_OPLOCK_BREAKING:
1232 		case SMB_SESSION_STATE_WRITE_RAW_ACTIVE: {
1233 			smb_user_t	*user;
1234 			smb_user_t	*next;
1235 
1236 			user = smb_user_lookup_by_state(session, NULL);
1237 			while (user) {
1238 				smb_user_disconnect_volume(user, fsd);
1239 				next = smb_user_lookup_by_state(session, user);
1240 				smb_user_release(user);
1241 				user = next;
1242 			}
1243 			break;
1244 
1245 		}
1246 		default:
1247 			break;
1248 		}
1249 		smb_rwx_rwexit(&session->s_lock);
1250 	}
1251 	smb_svcstate_unlock(&smb_info.si_svc_sm_ctx);
1252 }
1253