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