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 2009 Sun Microsystems, Inc. All rights reserved. 23 * Use is subject to license terms. 24 */ 25 26 /* 27 * General Structures Layout 28 * ------------------------- 29 * 30 * This is a simplified diagram showing the relationship between most of the 31 * main structures. 32 * 33 * +-------------------+ 34 * | SMB_SERVER | 35 * +-------------------+ 36 * | 37 * | 38 * v 39 * +-------------------+ +-------------------+ +-------------------+ 40 * | SESSION |<----->| SESSION |......| SESSION | 41 * +-------------------+ +-------------------+ +-------------------+ 42 * | 43 * | 44 * v 45 * +-------------------+ +-------------------+ +-------------------+ 46 * | USER |<----->| USER |......| USER | 47 * +-------------------+ +-------------------+ +-------------------+ 48 * | 49 * | 50 * v 51 * +-------------------+ +-------------------+ +-------------------+ 52 * | TREE |<----->| TREE |......| TREE | 53 * +-------------------+ +-------------------+ +-------------------+ 54 * | | 55 * | | 56 * | v 57 * | +-------+ +-------+ +-------+ 58 * | | OFILE |<----->| OFILE |......| OFILE | 59 * | +-------+ +-------+ +-------+ 60 * | 61 * | 62 * v 63 * +-------+ +------+ +------+ 64 * | ODIR |<----->| ODIR |......| ODIR | 65 * +-------+ +------+ +------+ 66 * 67 * 68 * Module Interface Overview 69 * ------------------------- 70 * 71 * 72 * +===================================+ 73 * | smbd daemon | 74 * +===================================+ 75 * | | ^ 76 * | | | 77 * User | | | 78 * -----------|--------------|----------------|-------------------------------- 79 * Kernel | | | 80 * | | | 81 * | | | 82 * +=========|==============|================|=================+ 83 * | v v | | 84 * | +-----------+ +--------------------+ +------------------+ | 85 * | | IO | | Kernel Door Server | | User Door Servers| | 86 * | | Interface | | Interface | | Interface | | 87 * | +-----------+ +--------------------+ +------------------+ | 88 * | | | ^ ^ | 89 * | v v | | | +=========+ 90 * | +-----------------------------------+ | | | | 91 * | + SMB Server Management (this file) |<------------------| ZFS | 92 * | +-----------------------------------+ | | | | 93 * | | | | Module | 94 * | +-----------------------------------+ | | | | 95 * | + SMB Server Internal Layers |------+ | +=========+ 96 * | +-----------------------------------+ | 97 * | | 98 * | | 99 * +===========================================================+ 100 * 101 * 102 * Server State Machine 103 * -------------------- 104 * | 105 * | T0 106 * | 107 * v 108 * +-----------------------------+ 109 * | SMB_SERVER_STATE_CREATED | 110 * +-----------------------------+ 111 * | 112 * | T1 113 * | 114 * v 115 * +-----------------------------+ 116 * | SMB_SERVER_STATE_CONFIGURED | 117 * +-----------------------------+ 118 * | 119 * | T2 120 * | 121 * v 122 * +-----------------------------+ 123 * | SMB_SERVER_STATE_RUNNING | 124 * +-----------------------------+ 125 * | 126 * | T3 127 * | 128 * v 129 * +-----------------------------+ 130 * | SMB_SERVER_STATE_DELETING | 131 * +-----------------------------+ 132 * | 133 * | 134 * | 135 * v 136 * 137 * States 138 * ------ 139 * 140 * SMB_SERVER_STATE_CREATED 141 * 142 * This is the state of the server just after creation. 143 * 144 * SMB_SERVER_STATE_CONFIGURED 145 * 146 * The server has been configured. 147 * 148 * SMB_SERVER_STATE_RUNNING 149 * 150 * The server has been started. While in this state the threads listening on 151 * the sockets car be started. The smbd daemon does so through an Ioctl: 152 * 153 * smb_drv_ioctl(SMB_IOC_NBT_LISTEN) --> smb_server_nbt_listen() 154 * smb_drv_ioctl(SMB_IOC_TCP_LISTEN) --> smb_server_nbt_listen() 155 * 156 * When a client establishes a connection the thread listening leaves 157 * temporarily the kernel. While in user space it creates a thread for the 158 * new session. It then returns to kernel with the result of the thread 159 * creation. If the creation failed the new session context is destroyed 160 * before returning listening. 161 * 162 * The new created thread enters the kernel though an Ioctl: 163 * 164 * smb_drv_ioctl(SMB_IOC_NBT_RECEIVE) --> smb_server_nbt_receive() 165 * smb_drv_ioctl(SMB_IOC_TCP_RECEIVE) --> smb_server_tcp_receive() 166 * 167 * SMB_SERVER_STATE_STOPPING 168 * 169 * The threads listening on the NBT and TCP sockets are being terminated. 170 * 171 * 172 * Transitions 173 * ----------- 174 * 175 * Transition T0 176 * 177 * The daemon smbd triggers its creation by opening the smbsrv device. If 178 * the zone where the daemon lives doesn't have an smb server yet it is 179 * created. 180 * 181 * smb_drv_open() --> smb_server_create() 182 * 183 * Transition T1 184 * 185 * This transition occurs in smb_server_configure(). It is triggered by the 186 * daemon through an Ioctl. 187 * 188 * smb_drv_ioctl(SMB_IOC_CONFIG) --> smb_server_configure() 189 * 190 * Transition T2 191 * 192 * This transition occurs in smb_server_start(). It is triggered by the 193 * daemon through an Ioctl. 194 * 195 * smb_drv_ioctl(SMB_IOC_START) --> smb_server_start() 196 * 197 * Transition T3 198 * 199 * This transition occurs in smb_server_delete(). It is triggered by the 200 * daemon when closing the smbsrv device 201 * 202 * smb_drv_close() --> smb_server_delete() 203 * 204 * Comments 205 * -------- 206 * 207 * This files assumes that there will one SMB server per zone. For now the 208 * smb server works only in global zone. There's nothing in this file preventing 209 * an smb server from being created in a non global zone. That limitation is 210 * enforced in user space. 211 */ 212 213 #include <sys/strsubr.h> 214 #include <sys/cmn_err.h> 215 #include <sys/priv.h> 216 #include <sys/socketvar.h> 217 #include <sys/zone.h> 218 #include <smbsrv/smb_kproto.h> 219 #include <smbsrv/netbios.h> 220 #include <smbsrv/smb_incl.h> 221 #include <smbsrv/cifs.h> 222 #include <smbsrv/smb_fsops.h> 223 #include <smbsrv/smb_share.h> 224 #include <smbsrv/smb_door_svc.h> 225 #include <smbsrv/smb_kstat.h> 226 227 extern void smb_dispatch_kstat_init(void); 228 extern void smb_dispatch_kstat_fini(void); 229 extern void smb_reply_notify_change_request(smb_request_t *); 230 231 static int smb_server_kstat_init(smb_server_t *); 232 static void smb_server_kstat_fini(smb_server_t *); 233 static int smb_server_kstat_update_info(kstat_t *, int); 234 static void smb_server_timers(smb_thread_t *, void *); 235 static int smb_server_listen(smb_server_t *, smb_listener_daemon_t *, 236 in_port_t, int, int); 237 static int smb_server_lookup(smb_server_t **); 238 static void smb_server_release(smb_server_t *); 239 static int smb_server_ulist_geti(smb_session_list_t *, int, 240 smb_opipe_context_t *, int); 241 static void smb_server_store_cfg(smb_server_t *, smb_kmod_cfg_t *); 242 static void smb_server_stop(smb_server_t *); 243 static int smb_server_fsop_start(smb_server_t *); 244 static void smb_server_fsop_stop(smb_server_t *); 245 246 static void smb_server_disconnect_share(char *, smb_server_t *); 247 static void smb_server_thread_unexport(smb_thread_t *, void *); 248 249 static smb_llist_t smb_servers; 250 251 /* 252 * ***************************************************************************** 253 * **************** Functions called from the device interface ***************** 254 * ***************************************************************************** 255 * 256 * These functions determine the relevant smb server to which the call apply. 257 */ 258 259 /* 260 * smb_server_svc_init 261 * 262 * This function must be called from smb_drv_attach(). 263 */ 264 int 265 smb_server_svc_init(void) 266 { 267 int rc = 0; 268 269 while (rc == 0) { 270 if (rc = smb_mbc_init()) 271 continue; 272 if (rc = smb_vop_init()) 273 continue; 274 if (rc = smb_node_init()) 275 continue; 276 if (rc = smb_fem_init()) 277 continue; 278 if (rc = smb_user_init()) 279 continue; 280 if (rc = smb_notify_init()) 281 continue; 282 if (rc = smb_net_init()) 283 continue; 284 if (rc = smb_kdoor_srv_start()) 285 continue; 286 smb_llist_constructor(&smb_servers, sizeof (smb_server_t), 287 offsetof(smb_server_t, sv_lnd)); 288 return (0); 289 } 290 smb_net_fini(); 291 smb_notify_fini(); 292 smb_user_fini(); 293 smb_fem_fini(); 294 smb_node_fini(); 295 smb_vop_fini(); 296 smb_mbc_fini(); 297 return (rc); 298 } 299 300 /* 301 * smb_server_svc_fini 302 * 303 * This function must called from smb_drv_detach(). It will fail if servers 304 * still exist. 305 */ 306 int 307 smb_server_svc_fini(void) 308 { 309 int rc = EBUSY; 310 311 if (smb_llist_get_count(&smb_servers) == 0) { 312 smb_kdoor_srv_stop(); 313 smb_net_fini(); 314 smb_notify_fini(); 315 smb_user_fini(); 316 smb_fem_fini(); 317 smb_node_fini(); 318 smb_vop_fini(); 319 smb_mbc_fini(); 320 smb_llist_destructor(&smb_servers); 321 rc = 0; 322 } 323 return (rc); 324 } 325 326 /* 327 * smb_server_create 328 * 329 * This function will fail if there's already a server associated with the 330 * caller's zone. 331 */ 332 int 333 smb_server_create(void) 334 { 335 zoneid_t zid; 336 smb_server_t *sv; 337 338 zid = getzoneid(); 339 340 smb_llist_enter(&smb_servers, RW_WRITER); 341 sv = smb_llist_head(&smb_servers); 342 while (sv) { 343 ASSERT(sv->sv_magic == SMB_SERVER_MAGIC); 344 if (sv->sv_zid == zid) { 345 smb_llist_exit(&smb_servers); 346 return (EPERM); 347 } 348 sv = smb_llist_next(&smb_servers, sv); 349 } 350 351 sv = kmem_zalloc(sizeof (smb_server_t), KM_NOSLEEP); 352 if (sv == NULL) { 353 smb_llist_exit(&smb_servers); 354 return (ENOMEM); 355 } 356 357 smb_llist_constructor(&sv->sv_vfs_list, sizeof (smb_vfs_t), 358 offsetof(smb_vfs_t, sv_lnd)); 359 360 smb_slist_constructor(&sv->sv_unexport_list, sizeof (smb_unexport_t), 361 offsetof(smb_unexport_t, ux_lnd)); 362 363 smb_session_list_constructor(&sv->sv_nbt_daemon.ld_session_list); 364 smb_session_list_constructor(&sv->sv_tcp_daemon.ld_session_list); 365 366 sv->si_cache_unexport = kmem_cache_create("smb_unexport_cache", 367 sizeof (smb_unexport_t), 8, NULL, NULL, NULL, NULL, NULL, 0); 368 sv->si_cache_vfs = kmem_cache_create("smb_vfs_cache", 369 sizeof (smb_vfs_t), 8, NULL, NULL, NULL, NULL, NULL, 0); 370 sv->si_cache_request = kmem_cache_create("smb_request_cache", 371 sizeof (smb_request_t), 8, NULL, NULL, NULL, NULL, NULL, 0); 372 sv->si_cache_session = kmem_cache_create("smb_session_cache", 373 sizeof (smb_session_t), 8, NULL, NULL, NULL, NULL, NULL, 0); 374 sv->si_cache_user = kmem_cache_create("smb_user_cache", 375 sizeof (smb_user_t), 8, NULL, NULL, NULL, NULL, NULL, 0); 376 sv->si_cache_tree = kmem_cache_create("smb_tree_cache", 377 sizeof (smb_tree_t), 8, NULL, NULL, NULL, NULL, NULL, 0); 378 sv->si_cache_ofile = kmem_cache_create("smb_ofile_cache", 379 sizeof (smb_ofile_t), 8, NULL, NULL, NULL, NULL, NULL, 0); 380 sv->si_cache_odir = kmem_cache_create("smb_odir_cache", 381 sizeof (smb_odir_t), 8, NULL, NULL, NULL, NULL, NULL, 0); 382 383 smb_thread_init(&sv->si_thread_timers, 384 "smb_timers", smb_server_timers, sv, 385 NULL, NULL); 386 387 smb_thread_init(&sv->si_thread_unexport, "smb_thread_unexport", 388 smb_server_thread_unexport, sv, NULL, NULL); 389 390 sv->sv_pid = curproc->p_pid; 391 392 smb_kdoor_clnt_init(); 393 smb_opipe_door_init(); 394 (void) smb_server_kstat_init(sv); 395 396 mutex_init(&sv->sv_mutex, NULL, MUTEX_DEFAULT, NULL); 397 cv_init(&sv->sv_cv, NULL, CV_DEFAULT, NULL); 398 sv->sv_state = SMB_SERVER_STATE_CREATED; 399 sv->sv_magic = SMB_SERVER_MAGIC; 400 sv->sv_zid = zid; 401 402 smb_llist_insert_tail(&smb_servers, sv); 403 smb_llist_exit(&smb_servers); 404 return (0); 405 } 406 407 /* 408 * smb_server_delete 409 * 410 * This function will delete the server passed in. It will make sure that all 411 * activity associated that server has ceased before destroying it. 412 */ 413 int 414 smb_server_delete(void) 415 { 416 smb_server_t *sv; 417 smb_unexport_t *ux; 418 int rc; 419 420 rc = smb_server_lookup(&sv); 421 if (rc != 0) 422 return (rc); 423 424 mutex_enter(&sv->sv_mutex); 425 switch (sv->sv_state) { 426 case SMB_SERVER_STATE_RUNNING: 427 { 428 boolean_t nbt = B_FALSE; 429 boolean_t tcp = B_FALSE; 430 431 if (sv->sv_nbt_daemon.ld_kth) { 432 tsignal(sv->sv_nbt_daemon.ld_kth, SIGINT); 433 nbt = B_TRUE; 434 } 435 if (sv->sv_tcp_daemon.ld_kth) { 436 tsignal(sv->sv_tcp_daemon.ld_kth, SIGINT); 437 tcp = B_TRUE; 438 } 439 sv->sv_state = SMB_SERVER_STATE_DELETING; 440 mutex_exit(&sv->sv_mutex); 441 if (nbt) 442 thread_join(sv->sv_nbt_daemon.ld_ktdid); 443 if (tcp) 444 thread_join(sv->sv_tcp_daemon.ld_ktdid); 445 mutex_enter(&sv->sv_mutex); 446 break; 447 } 448 case SMB_SERVER_STATE_CONFIGURED: 449 case SMB_SERVER_STATE_CREATED: 450 sv->sv_state = SMB_SERVER_STATE_DELETING; 451 break; 452 default: 453 ASSERT(sv->sv_state == SMB_SERVER_STATE_DELETING); 454 mutex_exit(&sv->sv_mutex); 455 smb_server_release(sv); 456 return (ENOTTY); 457 } 458 459 ASSERT(sv->sv_state == SMB_SERVER_STATE_DELETING); 460 461 sv->sv_refcnt--; 462 while (sv->sv_refcnt) 463 cv_wait(&sv->sv_cv, &sv->sv_mutex); 464 465 mutex_exit(&sv->sv_mutex); 466 467 smb_llist_enter(&smb_servers, RW_WRITER); 468 smb_llist_remove(&smb_servers, sv); 469 smb_llist_exit(&smb_servers); 470 471 smb_server_stop(sv); 472 rw_destroy(&sv->sv_cfg_lock); 473 smb_opipe_door_fini(); 474 smb_kdoor_clnt_fini(); 475 smb_server_kstat_fini(sv); 476 smb_llist_destructor(&sv->sv_vfs_list); 477 478 while ((ux = list_head(&sv->sv_unexport_list.sl_list)) != NULL) { 479 smb_slist_remove(&sv->sv_unexport_list, ux); 480 kmem_cache_free(sv->si_cache_unexport, ux); 481 } 482 smb_slist_destructor(&sv->sv_unexport_list); 483 484 kmem_cache_destroy(sv->si_cache_unexport); 485 kmem_cache_destroy(sv->si_cache_vfs); 486 kmem_cache_destroy(sv->si_cache_request); 487 kmem_cache_destroy(sv->si_cache_session); 488 kmem_cache_destroy(sv->si_cache_user); 489 kmem_cache_destroy(sv->si_cache_tree); 490 kmem_cache_destroy(sv->si_cache_ofile); 491 kmem_cache_destroy(sv->si_cache_odir); 492 493 smb_thread_destroy(&sv->si_thread_timers); 494 smb_thread_destroy(&sv->si_thread_unexport); 495 mutex_destroy(&sv->sv_mutex); 496 cv_destroy(&sv->sv_cv); 497 sv->sv_magic = 0; 498 kmem_free(sv, sizeof (smb_server_t)); 499 500 return (0); 501 } 502 503 /* 504 * smb_server_configure 505 */ 506 int 507 smb_server_configure(smb_kmod_cfg_t *cfg) 508 { 509 int rc = 0; 510 smb_server_t *sv; 511 512 rc = smb_server_lookup(&sv); 513 if (rc) 514 return (rc); 515 516 mutex_enter(&sv->sv_mutex); 517 switch (sv->sv_state) { 518 case SMB_SERVER_STATE_CREATED: 519 smb_server_store_cfg(sv, cfg); 520 sv->sv_state = SMB_SERVER_STATE_CONFIGURED; 521 break; 522 523 case SMB_SERVER_STATE_CONFIGURED: 524 smb_server_store_cfg(sv, cfg); 525 break; 526 527 case SMB_SERVER_STATE_RUNNING: 528 rw_enter(&sv->sv_cfg_lock, RW_WRITER); 529 smb_server_store_cfg(sv, cfg); 530 rw_exit(&sv->sv_cfg_lock); 531 break; 532 533 default: 534 ASSERT(sv->sv_state == SMB_SERVER_STATE_DELETING); 535 rc = EFAULT; 536 break; 537 } 538 mutex_exit(&sv->sv_mutex); 539 540 smb_server_release(sv); 541 542 return (rc); 543 } 544 545 /* 546 * smb_server_start 547 */ 548 int 549 smb_server_start(struct smb_io_start *io_start) 550 { 551 int rc = 0; 552 smb_server_t *sv; 553 554 rc = smb_server_lookup(&sv); 555 if (rc) 556 return (rc); 557 558 mutex_enter(&sv->sv_mutex); 559 switch (sv->sv_state) { 560 case SMB_SERVER_STATE_CONFIGURED: 561 562 sv->sv_thread_pool = taskq_create("smb_workers", 563 sv->sv_cfg.skc_maxworkers, SMB_WORKER_PRIORITY, 564 sv->sv_cfg.skc_maxworkers, INT_MAX, 565 TASKQ_DYNAMIC|TASKQ_PREPOPULATE); 566 567 sv->sv_session = smb_session_create(NULL, 0, sv, 0); 568 569 if (sv->sv_thread_pool == NULL || sv->sv_session == NULL) { 570 rc = ENOMEM; 571 break; 572 } 573 574 if (rc = smb_server_fsop_start(sv)) 575 break; 576 ASSERT(sv->sv_lmshrd == NULL); 577 sv->sv_lmshrd = smb_kshare_init(io_start->lmshrd); 578 if (sv->sv_lmshrd == NULL) 579 break; 580 if (rc = smb_kdoor_clnt_open(io_start->udoor)) 581 break; 582 if (rc = smb_kdoor_srv_set_downcall()) { 583 cmn_err(CE_WARN, "Cannot set downcall descriptor"); 584 break; 585 } 586 if (rc = smb_thread_start(&sv->si_thread_timers)) 587 break; 588 if (rc = smb_thread_start(&sv->si_thread_unexport)) 589 break; 590 /* 591 * XXX We give up the NET_MAC_AWARE privilege because it keeps 592 * us from re-opening the connection when there are leftover TCP 593 * connections in TCPS_TIME_WAIT state. There seem to be some 594 * security ramifications around reestablishing a connection 595 * while possessing the NET_MAC_AWARE privilege. 596 * 597 * This approach may cause problems when we try to support 598 * zones. An alternative would be to retry the connection setup 599 * for a fixed period of time until the stale connections clear 600 * up but that implies we would be offline for a couple minutes 601 * every time the service is restarted with active connections. 602 */ 603 rc = setpflags(NET_MAC_AWARE, 0, CRED()); 604 if (rc) { 605 cmn_err(CE_WARN, 606 "Cannot remove NET_MAC_AWARE privilege"); 607 break; 608 } 609 if (rc = smb_opipe_door_open(io_start->opipe)) { 610 cmn_err(CE_WARN, "Cannot open opipe door"); 611 break; 612 } 613 sv->sv_state = SMB_SERVER_STATE_RUNNING; 614 mutex_exit(&sv->sv_mutex); 615 smb_server_release(sv); 616 return (0); 617 default: 618 ASSERT((sv->sv_state == SMB_SERVER_STATE_CREATED) || 619 (sv->sv_state == SMB_SERVER_STATE_RUNNING) || 620 (sv->sv_state == SMB_SERVER_STATE_DELETING)); 621 mutex_exit(&sv->sv_mutex); 622 smb_server_release(sv); 623 return (ENOTTY); 624 } 625 626 smb_server_stop(sv); 627 mutex_exit(&sv->sv_mutex); 628 smb_server_release(sv); 629 return (rc); 630 } 631 632 /* 633 * smb_server_nbt_listen: SMB-over-NetBIOS service 634 * 635 * Traditional SMB service over NetBIOS (port 139), which requires 636 * that a NetBIOS session be established. 637 */ 638 int 639 smb_server_nbt_listen(int error) 640 { 641 smb_server_t *sv; 642 int rc; 643 644 rc = smb_server_lookup(&sv); 645 if (rc) 646 return (rc); 647 648 mutex_enter(&sv->sv_mutex); 649 switch (sv->sv_state) { 650 case SMB_SERVER_STATE_RUNNING: 651 if ((sv->sv_nbt_daemon.ld_kth != NULL) && 652 (sv->sv_nbt_daemon.ld_kth != curthread)) { 653 mutex_exit(&sv->sv_mutex); 654 return (EACCES); 655 } else { 656 sv->sv_nbt_daemon.ld_kth = curthread; 657 sv->sv_nbt_daemon.ld_ktdid = curthread->t_did; 658 } 659 break; 660 default: 661 ASSERT((sv->sv_state == SMB_SERVER_STATE_CREATED) || 662 (sv->sv_state == SMB_SERVER_STATE_CONFIGURED) || 663 (sv->sv_state == SMB_SERVER_STATE_DELETING)); 664 mutex_exit(&sv->sv_mutex); 665 smb_server_release(sv); 666 return (EFAULT); 667 } 668 mutex_exit(&sv->sv_mutex); 669 670 /* 671 * netbios must be ipv4 672 */ 673 rc = smb_server_listen(sv, &sv->sv_nbt_daemon, SSN_SRVC_TCP_PORT, 674 AF_INET, error); 675 676 if (rc) { 677 mutex_enter(&sv->sv_mutex); 678 sv->sv_nbt_daemon.ld_kth = NULL; 679 mutex_exit(&sv->sv_mutex); 680 } 681 682 smb_server_release(sv); 683 684 return (rc); 685 } 686 687 int 688 smb_server_tcp_listen(int error) 689 { 690 smb_server_t *sv; 691 int rc; 692 693 rc = smb_server_lookup(&sv); 694 if (rc) 695 return (rc); 696 697 mutex_enter(&sv->sv_mutex); 698 switch (sv->sv_state) { 699 case SMB_SERVER_STATE_RUNNING: 700 if ((sv->sv_tcp_daemon.ld_kth) && 701 (sv->sv_tcp_daemon.ld_kth != curthread)) { 702 mutex_exit(&sv->sv_mutex); 703 return (EACCES); 704 } else { 705 sv->sv_tcp_daemon.ld_kth = curthread; 706 sv->sv_tcp_daemon.ld_ktdid = curthread->t_did; 707 } 708 break; 709 default: 710 ASSERT((sv->sv_state == SMB_SERVER_STATE_CREATED) || 711 (sv->sv_state == SMB_SERVER_STATE_CONFIGURED) || 712 (sv->sv_state == SMB_SERVER_STATE_DELETING)); 713 mutex_exit(&sv->sv_mutex); 714 return (EFAULT); 715 } 716 mutex_exit(&sv->sv_mutex); 717 718 if (sv->sv_cfg.skc_ipv6_enable) 719 rc = smb_server_listen(sv, &sv->sv_tcp_daemon, 720 SMB_SRVC_TCP_PORT, AF_INET6, error); 721 else 722 rc = smb_server_listen(sv, &sv->sv_tcp_daemon, 723 SMB_SRVC_TCP_PORT, AF_INET, error); 724 if (rc) { 725 mutex_enter(&sv->sv_mutex); 726 sv->sv_tcp_daemon.ld_kth = NULL; 727 mutex_exit(&sv->sv_mutex); 728 } 729 730 smb_server_release(sv); 731 732 return (rc); 733 } 734 735 /* 736 * smb_server_nbt_receive 737 */ 738 int 739 smb_server_nbt_receive(void) 740 { 741 int rc; 742 smb_server_t *sv; 743 744 rc = smb_server_lookup(&sv); 745 if (rc) 746 return (rc); 747 748 rc = smb_session_daemon(&sv->sv_nbt_daemon.ld_session_list); 749 750 smb_server_release(sv); 751 752 return (rc); 753 } 754 755 /* 756 * smb_server_tcp_receive 757 */ 758 int 759 smb_server_tcp_receive(void) 760 { 761 int rc; 762 smb_server_t *sv; 763 764 rc = smb_server_lookup(&sv); 765 if (rc) 766 return (rc); 767 768 rc = smb_session_daemon(&sv->sv_tcp_daemon.ld_session_list); 769 770 smb_server_release(sv); 771 772 return (rc); 773 } 774 775 int 776 smb_server_set_gmtoff(int32_t goff) 777 { 778 int rc; 779 smb_server_t *sv; 780 781 782 rc = smb_server_lookup(&sv); 783 if (rc) 784 return (rc); 785 786 sv->si_gmtoff = goff; 787 788 smb_server_release(sv); 789 790 return (rc); 791 } 792 793 /* 794 * ***************************************************************************** 795 * ****************** Functions called from the door interface ***************** 796 * ***************************************************************************** 797 * 798 * These functions determine the relevant smb server to which the call apply. 799 */ 800 801 uint32_t 802 smb_server_get_user_count(void) 803 { 804 smb_server_t *sv; 805 uint32_t counter = 0; 806 807 if (smb_server_lookup(&sv)) 808 return (0); 809 810 counter = (uint32_t)sv->sv_open_users; 811 812 smb_server_release(sv); 813 814 return (counter); 815 } 816 817 uint32_t 818 smb_server_get_session_count(void) 819 { 820 smb_server_t *sv; 821 uint32_t counter = 0; 822 823 if (smb_server_lookup(&sv)) 824 return (0); 825 826 rw_enter(&sv->sv_nbt_daemon.ld_session_list.se_lock, RW_READER); 827 counter = sv->sv_nbt_daemon.ld_session_list.se_act.count; 828 rw_exit(&sv->sv_nbt_daemon.ld_session_list.se_lock); 829 rw_enter(&sv->sv_tcp_daemon.ld_session_list.se_lock, RW_READER); 830 counter += sv->sv_tcp_daemon.ld_session_list.se_act.count; 831 rw_exit(&sv->sv_tcp_daemon.ld_session_list.se_lock); 832 833 smb_server_release(sv); 834 835 return (counter); 836 } 837 838 /* 839 * smb_server_disconnect_share 840 * 841 * Disconnects the specified share. This function should be called after the 842 * share passed in has been made unavailable by the "share manager". 843 */ 844 static void 845 smb_server_disconnect_share(char *sharename, smb_server_t *sv) 846 { 847 smb_session_disconnect_share(&sv->sv_nbt_daemon.ld_session_list, 848 sharename); 849 smb_session_disconnect_share(&sv->sv_tcp_daemon.ld_session_list, 850 sharename); 851 } 852 853 int 854 smb_server_dr_ulist_get(int offset, smb_dr_ulist_t *dr_ulist, int max_cnt) 855 { 856 smb_server_t *sv; 857 858 if (!dr_ulist) 859 return (-1); 860 861 if (smb_server_lookup(&sv)) 862 return (-1); 863 864 dr_ulist->dul_cnt = 865 smb_server_ulist_geti(&sv->sv_nbt_daemon.ld_session_list, 866 offset, dr_ulist->dul_users, max_cnt); 867 dr_ulist->dul_cnt += 868 smb_server_ulist_geti(&sv->sv_tcp_daemon.ld_session_list, 869 offset - dr_ulist->dul_cnt, &dr_ulist->dul_users[dr_ulist->dul_cnt], 870 max_cnt); 871 872 return (dr_ulist->dul_cnt); 873 } 874 875 /* 876 * smb_server_share_export() 877 * 878 * This function handles kernel processing at share enable time. 879 * 880 * At share-enable time (LMSHRD_ADD), the file system corresponding to 881 * the share is checked for characteristics that are required for SMB 882 * sharing. If this check passes, then a hold is taken on the root vnode 883 * of the file system (or a reference count on the corresponding smb_vfs_t 884 * is bumped), preventing an unmount. (See smb_vfs_hold()). 885 */ 886 887 int 888 smb_server_share_export(char *path) 889 { 890 smb_server_t *sv; 891 int error; 892 smb_node_t *fnode = NULL; 893 smb_node_t *dnode; 894 smb_attr_t ret_attr; 895 char last_comp[MAXNAMELEN]; 896 smb_request_t *sr; 897 898 if (smb_server_lookup(&sv)) 899 return (EINVAL); 900 901 sr = smb_request_alloc(sv->sv_session, 0); 902 if (sr == NULL) { 903 smb_server_release(sv); 904 return (ENOMEM); 905 } 906 907 sr->user_cr = kcred; 908 909 error = smb_pathname_reduce(sr, kcred, path, NULL, NULL, &dnode, 910 last_comp); 911 912 if (error) { 913 smb_request_free(sr); 914 smb_server_release(sv); 915 return (error); 916 } 917 918 error = smb_fsop_lookup(sr, sr->user_cr, SMB_FOLLOW_LINKS, NULL, dnode, 919 last_comp, &fnode, &ret_attr, NULL, NULL); 920 921 smb_node_release(dnode); 922 923 if (error) { 924 smb_request_free(sr); 925 smb_server_release(sv); 926 return (error); 927 } 928 929 ASSERT(fnode->vp && fnode->vp->v_vfsp); 930 931 #ifdef SMB_ENFORCE_NODEV 932 if (vfs_optionisset(fnode->vp->v_vfsp, MNTOPT_NODEVICES, NULL) == 0) 933 return (EINVAL); 934 #endif /* SMB_ENFORCE_NODEV */ 935 936 if (!smb_vfs_hold(sv, fnode->vp->v_vfsp)) { 937 smb_node_release(fnode); 938 smb_request_free(sr); 939 smb_server_release(sv); 940 return (ENOMEM); 941 } 942 943 /* 944 * The refcount on the smb_vfs has been incremented. 945 * If it wasn't already, a hold has also been taken 946 * on the root vnode of the file system. 947 */ 948 949 smb_node_release(fnode); 950 smb_request_free(sr); 951 smb_server_release(sv); 952 return (0); 953 } 954 955 956 957 /* 958 * smb_server_share_unexport() 959 * 960 * This function is invoked when a share is disabled to disconnect trees 961 * and close files. Cleaning up may involve VOP and/or VFS calls, which 962 * may conflict/deadlock with stuck threads if something is amiss with the 963 * file system. Queueing the request for asynchronous processing allows the 964 * call to return immediately so that, if the unshare is being done in the 965 * context of a forced unmount, the forced unmount will always be able to 966 * proceed (unblocking stuck I/O and eventually allowing all blocked unshare 967 * processes to complete). 968 * 969 * The path lookup to find the root vnode of the VFS in question and the 970 * release of this vnode are done synchronously prior to any associated 971 * unmount. Doing these asynchronous to an associated unmount could run 972 * the risk of a spurious EBUSY for a standard unmount or an EIO during 973 * the path lookup due to a forced unmount finishing first. 974 */ 975 976 int 977 smb_server_share_unexport(char *path, char *sharename) 978 { 979 smb_server_t *sv; 980 smb_request_t *sr; 981 smb_unexport_t *ux; 982 smb_node_t *fnode = NULL; 983 smb_node_t *dnode; 984 smb_attr_t ret_attr; 985 char last_comp[MAXNAMELEN]; 986 int rc; 987 988 if ((rc = smb_server_lookup(&sv))) 989 return (rc); 990 991 sr = smb_request_alloc(sv->sv_session, 0); 992 993 if (sr == NULL) { 994 smb_server_release(sv); 995 return (ENOMEM); 996 } 997 998 sr->user_cr = kcred; 999 1000 rc = smb_pathname_reduce(sr, kcred, path, NULL, NULL, &dnode, 1001 last_comp); 1002 1003 if (rc) { 1004 smb_request_free(sr); 1005 smb_server_release(sv); 1006 return (rc); 1007 } 1008 1009 rc = smb_fsop_lookup(sr, kcred, SMB_FOLLOW_LINKS, NULL, dnode, 1010 last_comp, &fnode, &ret_attr, NULL, NULL); 1011 1012 smb_node_release(dnode); 1013 smb_request_free(sr); 1014 1015 if (rc) { 1016 smb_server_release(sv); 1017 return (rc); 1018 } 1019 1020 ASSERT(fnode->vp && fnode->vp->v_vfsp); 1021 1022 smb_vfs_rele(sv, fnode->vp->v_vfsp); 1023 1024 smb_node_release(fnode); 1025 1026 ux = kmem_cache_alloc(sv->si_cache_unexport, KM_SLEEP); 1027 1028 (void) strlcpy(ux->ux_sharename, sharename, MAXNAMELEN); 1029 1030 smb_slist_insert_tail(&sv->sv_unexport_list, ux); 1031 smb_thread_signal(&sv->si_thread_unexport); 1032 1033 smb_server_release(sv); 1034 return (0); 1035 } 1036 1037 /* 1038 * smb_server_thread_unexport 1039 * 1040 * This function processes the unexport event list and disconnects shares 1041 * asynchronously. The function executes as a zone-specific thread. 1042 * 1043 * The server arg passed in is safe to use without a reference count, because 1044 * the server cannot be deleted until smb_thread_stop()/destroy() return, 1045 * which is also when the thread exits. 1046 */ 1047 1048 static void 1049 smb_server_thread_unexport(smb_thread_t *thread, void *arg) 1050 { 1051 smb_server_t *sv = (smb_server_t *)arg; 1052 smb_unexport_t *ux; 1053 1054 while (smb_thread_continue(thread)) { 1055 while ((ux = list_head(&sv->sv_unexport_list.sl_list)) 1056 != NULL) { 1057 smb_slist_remove(&sv->sv_unexport_list, ux); 1058 smb_server_disconnect_share(ux->ux_sharename, sv); 1059 kmem_cache_free(sv->si_cache_unexport, ux); 1060 } 1061 } 1062 } 1063 1064 /* 1065 * This is a special interface that will be utilized by ZFS to cause a share to 1066 * be added/removed. 1067 * 1068 * arg is either a lmshare_info_t or share_name from userspace. 1069 * It will need to be copied into the kernel. It is lmshare_info_t 1070 * for add operations and share_name for delete operations. 1071 */ 1072 int 1073 smb_server_share(void *arg, boolean_t add_share) 1074 { 1075 smb_server_t *sv; 1076 int rc; 1077 1078 rc = smb_server_lookup(&sv); 1079 if (rc == 0) { 1080 mutex_enter(&sv->sv_mutex); 1081 if (sv->sv_state == SMB_SERVER_STATE_RUNNING) { 1082 mutex_exit(&sv->sv_mutex); 1083 rc = smb_kshare_upcall(sv->sv_lmshrd, arg, add_share); 1084 } else { 1085 mutex_exit(&sv->sv_mutex); 1086 rc = EPERM; 1087 } 1088 smb_server_release(sv); 1089 } 1090 return (rc); 1091 } 1092 1093 /* 1094 * ***************************************************************************** 1095 * **************** Functions called from the internal layers ****************** 1096 * ***************************************************************************** 1097 * 1098 * These functions are provided the relevant smb server by the caller. 1099 */ 1100 1101 void 1102 smb_server_reconnection_check(smb_server_t *sv, smb_session_t *session) 1103 { 1104 ASSERT(sv == session->s_server); 1105 1106 smb_session_reconnection_check(&sv->sv_nbt_daemon.ld_session_list, 1107 session); 1108 smb_session_reconnection_check(&sv->sv_tcp_daemon.ld_session_list, 1109 session); 1110 } 1111 1112 void 1113 smb_server_get_cfg(smb_server_t *sv, smb_kmod_cfg_t *cfg) 1114 { 1115 rw_enter(&sv->sv_cfg_lock, RW_READER); 1116 bcopy(&sv->sv_cfg, cfg, sizeof (*cfg)); 1117 rw_exit(&sv->sv_cfg_lock); 1118 } 1119 1120 /* 1121 * ***************************************************************************** 1122 * *************************** Static Functions ******************************** 1123 * ***************************************************************************** 1124 */ 1125 1126 static void 1127 smb_server_timers(smb_thread_t *thread, void *arg) 1128 { 1129 smb_server_t *sv = (smb_server_t *)arg; 1130 1131 ASSERT(sv != NULL); 1132 1133 while (smb_thread_continue_timedwait(thread, 1 /* Seconds */)) { 1134 smb_session_timers(&sv->sv_nbt_daemon.ld_session_list); 1135 smb_session_timers(&sv->sv_tcp_daemon.ld_session_list); 1136 } 1137 } 1138 1139 /* 1140 * smb_server_kstat_init 1141 */ 1142 static int 1143 smb_server_kstat_init(smb_server_t *sv) 1144 { 1145 (void) snprintf(sv->sv_ksp_name, sizeof (sv->sv_ksp_name), "%s%d", 1146 SMBSRV_KSTAT_NAME, sv->sv_zid); 1147 1148 sv->sv_ksp = kstat_create(SMBSRV_KSTAT_MODULE, 0, sv->sv_ksp_name, 1149 SMBSRV_KSTAT_CLASS, KSTAT_TYPE_NAMED, 1150 sizeof (sv->sv_ks_data) / sizeof (kstat_named_t), 1151 KSTAT_FLAG_VIRTUAL); 1152 1153 if (sv->sv_ksp) { 1154 (void) strlcpy(sv->sv_ks_data.open_files.name, "open_files", 1155 sizeof (sv->sv_ks_data.open_files.name)); 1156 sv->sv_ks_data.open_files.data_type = KSTAT_DATA_UINT32; 1157 (void) strlcpy(sv->sv_ks_data.open_trees.name, "connections", 1158 sizeof (sv->sv_ks_data.open_trees.name)); 1159 sv->sv_ks_data.open_trees.data_type = KSTAT_DATA_UINT32; 1160 (void) strlcpy(sv->sv_ks_data.open_users.name, "sessions", 1161 sizeof (sv->sv_ks_data.open_users.name)); 1162 sv->sv_ks_data.open_users.data_type = KSTAT_DATA_UINT32; 1163 1164 mutex_init(&sv->sv_ksp_mutex, NULL, MUTEX_DEFAULT, NULL); 1165 sv->sv_ksp->ks_lock = &sv->sv_ksp_mutex; 1166 sv->sv_ksp->ks_data = (void *)&sv->sv_ks_data; 1167 sv->sv_ksp->ks_update = smb_server_kstat_update_info; 1168 kstat_install(sv->sv_ksp); 1169 } 1170 1171 /* create and initialize smb kstats - smb_dispatch stats */ 1172 smb_dispatch_kstat_init(); 1173 1174 return (0); 1175 } 1176 1177 /* 1178 * smb_server_kstat_fini 1179 */ 1180 static void 1181 smb_server_kstat_fini(smb_server_t *sv) 1182 { 1183 if (sv->sv_ksp) { 1184 kstat_delete(sv->sv_ksp); 1185 mutex_destroy(&sv->sv_ksp_mutex); 1186 sv->sv_ksp = NULL; 1187 } 1188 smb_dispatch_kstat_fini(); 1189 } 1190 1191 /* ARGSUSED */ 1192 static int 1193 smb_server_kstat_update_info(kstat_t *ksp, int rw) 1194 { 1195 smb_server_t *sv; 1196 1197 if (rw == KSTAT_WRITE) { 1198 return (EACCES); 1199 } else { 1200 ASSERT(MUTEX_HELD(ksp->ks_lock)); 1201 1202 _NOTE(LINTED("pointer cast may result in improper alignment")) 1203 sv = (smb_server_t *)((uint8_t *)(ksp->ks_data) - 1204 offsetof(smb_server_t, sv_ks_data)); 1205 1206 ASSERT(sv->sv_magic == SMB_SERVER_MAGIC); 1207 1208 sv->sv_ks_data.open_files.value.ui32 = sv->sv_open_files; 1209 sv->sv_ks_data.open_trees.value.ui32 = sv->sv_open_trees; 1210 sv->sv_ks_data.open_users.value.ui32 = sv->sv_open_users; 1211 } 1212 return (0); 1213 } 1214 1215 /* 1216 * smb_server_stop 1217 * 1218 * The mutex of the server must have been entered before calling this function. 1219 */ 1220 static void 1221 smb_server_stop(smb_server_t *sv) 1222 { 1223 ASSERT(sv->sv_magic == SMB_SERVER_MAGIC); 1224 1225 smb_opipe_door_close(); 1226 smb_thread_stop(&sv->si_thread_timers); 1227 smb_thread_stop(&sv->si_thread_unexport); 1228 smb_kdoor_clnt_close(); 1229 smb_kshare_fini(sv->sv_lmshrd); 1230 sv->sv_lmshrd = NULL; 1231 smb_server_fsop_stop(sv); 1232 1233 if (sv->sv_session) { 1234 smb_session_delete(sv->sv_session); 1235 sv->sv_session = NULL; 1236 } 1237 1238 if (sv->sv_thread_pool) { 1239 taskq_destroy(sv->sv_thread_pool); 1240 sv->sv_thread_pool = NULL; 1241 } 1242 } 1243 1244 static int 1245 smb_server_listen( 1246 smb_server_t *sv, 1247 smb_listener_daemon_t *ld, 1248 in_port_t port, 1249 int family, 1250 int pthread_create_error) 1251 { 1252 int rc; 1253 ksocket_t s_so; 1254 uint32_t on = 1; 1255 smb_session_t *session; 1256 1257 if (pthread_create_error) { 1258 /* 1259 * Delete the last session created. The user space thread 1260 * creation failed. 1261 */ 1262 smb_session_list_delete_tail(&ld->ld_session_list); 1263 } 1264 1265 if (ld->ld_so == NULL) { 1266 /* First time listener */ 1267 if (family == AF_INET) { 1268 ld->ld_sin.sin_family = (uint32_t)family; 1269 ld->ld_sin.sin_port = htons(port); 1270 ld->ld_sin.sin_addr.s_addr = htonl(INADDR_ANY); 1271 } else { 1272 ld->ld_sin6.sin6_family = (uint32_t)family; 1273 ld->ld_sin6.sin6_port = htons(port); 1274 (void) memset(&ld->ld_sin6.sin6_addr.s6_addr, 0, 1275 sizeof (ld->ld_sin6.sin6_addr.s6_addr)); 1276 } 1277 ld->ld_so = smb_socreate(family, SOCK_STREAM, 0); 1278 if (ld->ld_so) { 1279 1280 (void) ksocket_setsockopt(ld->ld_so, SOL_SOCKET, 1281 SO_REUSEADDR, (const void *)&on, sizeof (on), 1282 CRED()); 1283 if (family == AF_INET) { 1284 rc = ksocket_bind(ld->ld_so, 1285 (struct sockaddr *)&ld->ld_sin, 1286 sizeof (ld->ld_sin), CRED()); 1287 } else { 1288 rc = ksocket_bind(ld->ld_so, 1289 (struct sockaddr *)&ld->ld_sin6, 1290 sizeof (ld->ld_sin6), CRED()); 1291 } 1292 if (rc == 0) { 1293 rc = ksocket_listen(ld->ld_so, 20, CRED()); 1294 if (rc < 0) { 1295 cmn_err(CE_WARN, 1296 "Port %d: listen failed", port); 1297 smb_soshutdown(ld->ld_so); 1298 smb_sodestroy(ld->ld_so); 1299 ld->ld_so = NULL; 1300 return (rc); 1301 } 1302 } else { 1303 cmn_err(CE_WARN, 1304 "Port %d: bind failed", port); 1305 smb_soshutdown(ld->ld_so); 1306 smb_sodestroy(ld->ld_so); 1307 ld->ld_so = NULL; 1308 return (rc); 1309 } 1310 } else { 1311 cmn_err(CE_WARN, 1312 "Port %d: socket create failed", port); 1313 return (ENOMEM); 1314 } 1315 } 1316 1317 DTRACE_PROBE1(so__wait__accept, struct sonode *, ld->ld_so); 1318 1319 for (;;) { 1320 rc = ksocket_accept(ld->ld_so, NULL, NULL, &s_so, CRED()); 1321 if (rc == 0) { 1322 uint32_t txbuf_size = 128*1024; 1323 uint32_t on = 1; 1324 1325 DTRACE_PROBE1(so__accept, struct sonode *, s_so); 1326 1327 (void) ksocket_setsockopt(s_so, IPPROTO_TCP, 1328 TCP_NODELAY, (const void *)&on, sizeof (on), 1329 CRED()); 1330 (void) ksocket_setsockopt(s_so, SOL_SOCKET, 1331 SO_KEEPALIVE, (const void *)&on, sizeof (on), 1332 CRED()); 1333 (void) ksocket_setsockopt(s_so, SOL_SOCKET, SO_SNDBUF, 1334 (const void *)&txbuf_size, sizeof (txbuf_size), 1335 CRED()); 1336 /* 1337 * Create a session for this connection. 1338 */ 1339 session = smb_session_create(s_so, port, sv, family); 1340 if (session) { 1341 smb_session_list_append(&ld->ld_session_list, 1342 session); 1343 break; 1344 } else { 1345 smb_soshutdown(s_so); 1346 smb_sodestroy(s_so); 1347 } 1348 continue; 1349 } 1350 smb_session_list_signal(&ld->ld_session_list); 1351 smb_soshutdown(ld->ld_so); 1352 smb_sodestroy(ld->ld_so); 1353 ld->ld_so = NULL; 1354 break; 1355 } 1356 1357 return (rc); 1358 } 1359 1360 /* 1361 * smb_server_lookup 1362 * 1363 * This function tries to find the server associated with the zone of the 1364 * caller. 1365 */ 1366 static int 1367 smb_server_lookup(smb_server_t **psv) 1368 { 1369 zoneid_t zid; 1370 smb_server_t *sv; 1371 1372 zid = getzoneid(); 1373 1374 smb_llist_enter(&smb_servers, RW_READER); 1375 sv = smb_llist_head(&smb_servers); 1376 while (sv) { 1377 ASSERT(sv->sv_magic == SMB_SERVER_MAGIC); 1378 if (sv->sv_zid == zid) { 1379 mutex_enter(&sv->sv_mutex); 1380 if (sv->sv_state != SMB_SERVER_STATE_DELETING) { 1381 sv->sv_refcnt++; 1382 mutex_exit(&sv->sv_mutex); 1383 smb_llist_exit(&smb_servers); 1384 *psv = sv; 1385 return (0); 1386 } 1387 mutex_exit(&sv->sv_mutex); 1388 break; 1389 } 1390 sv = smb_llist_next(&smb_servers, sv); 1391 } 1392 smb_llist_exit(&smb_servers); 1393 return (EPERM); 1394 } 1395 1396 /* 1397 * smb_server_release 1398 * 1399 * This function decrements the reference count of the server and signals its 1400 * condition variable if the state of the server is SMB_SERVER_STATE_DELETING. 1401 */ 1402 static void 1403 smb_server_release(smb_server_t *sv) 1404 { 1405 ASSERT(sv->sv_magic == SMB_SERVER_MAGIC); 1406 1407 mutex_enter(&sv->sv_mutex); 1408 ASSERT(sv->sv_refcnt); 1409 sv->sv_refcnt--; 1410 if ((sv->sv_refcnt == 0) && (sv->sv_state == SMB_SERVER_STATE_DELETING)) 1411 cv_signal(&sv->sv_cv); 1412 mutex_exit(&sv->sv_mutex); 1413 } 1414 1415 static int 1416 smb_server_ulist_geti( 1417 smb_session_list_t *se, 1418 int offset, 1419 smb_opipe_context_t *ctx, 1420 int max_cnt) 1421 { 1422 smb_session_t *sn = NULL; 1423 smb_user_t *user; 1424 smb_llist_t *ulist; 1425 int cnt = 0, skip = 0; 1426 1427 rw_enter(&se->se_lock, RW_READER); 1428 sn = list_head(&se->se_act.lst); 1429 while (sn && (cnt < max_cnt)) { 1430 ASSERT(sn->s_magic == SMB_SESSION_MAGIC); 1431 ulist = &sn->s_user_list; 1432 smb_llist_enter(ulist, RW_READER); 1433 user = smb_llist_head(ulist); 1434 while (user && (cnt < max_cnt)) { 1435 ASSERT(user->u_magic == SMB_USER_MAGIC); 1436 mutex_enter(&user->u_mutex); 1437 if (user->u_state == SMB_USER_STATE_LOGGED_IN) { 1438 if (skip++ < offset) { 1439 mutex_exit(&user->u_mutex); 1440 user = smb_llist_next(ulist, user); 1441 continue; 1442 } 1443 1444 smb_user_context_init(user, ctx); 1445 ctx++; 1446 cnt++; 1447 } 1448 mutex_exit(&user->u_mutex); 1449 user = smb_llist_next(ulist, user); 1450 } 1451 smb_llist_exit(ulist); 1452 sn = list_next(&se->se_act.lst, sn); 1453 } 1454 rw_exit(&se->se_lock); 1455 return (cnt); 1456 } 1457 1458 static void 1459 smb_server_store_cfg(smb_server_t *sv, smb_kmod_cfg_t *cfg) 1460 { 1461 if (cfg->skc_maxconnections == 0) 1462 cfg->skc_maxconnections = 0xFFFFFFFF; 1463 1464 smb_session_correct_keep_alive_values( 1465 &sv->sv_nbt_daemon.ld_session_list, cfg->skc_keepalive); 1466 smb_session_correct_keep_alive_values( 1467 &sv->sv_tcp_daemon.ld_session_list, cfg->skc_keepalive); 1468 1469 bcopy(cfg, &sv->sv_cfg, sizeof (sv->sv_cfg)); 1470 } 1471 1472 static int 1473 smb_server_fsop_start(smb_server_t *sv) 1474 { 1475 int error; 1476 1477 error = smb_node_root_init(rootdir, sv, &sv->si_root_smb_node); 1478 if (error != 0) 1479 sv->si_root_smb_node = NULL; 1480 1481 return (error); 1482 } 1483 1484 static void 1485 smb_server_fsop_stop(smb_server_t *sv) 1486 { 1487 if (sv->si_root_smb_node != NULL) { 1488 smb_vfs_rele_all(sv); 1489 smb_node_release(sv->si_root_smb_node); 1490 sv->si_root_smb_node = NULL; 1491 } 1492 } 1493