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 if (rc = smb_opipe_door_open(io_start->opipe)) { 591 cmn_err(CE_WARN, "Cannot open opipe door"); 592 break; 593 } 594 sv->sv_state = SMB_SERVER_STATE_RUNNING; 595 mutex_exit(&sv->sv_mutex); 596 smb_server_release(sv); 597 return (0); 598 default: 599 ASSERT((sv->sv_state == SMB_SERVER_STATE_CREATED) || 600 (sv->sv_state == SMB_SERVER_STATE_RUNNING) || 601 (sv->sv_state == SMB_SERVER_STATE_DELETING)); 602 mutex_exit(&sv->sv_mutex); 603 smb_server_release(sv); 604 return (ENOTTY); 605 } 606 607 smb_server_stop(sv); 608 mutex_exit(&sv->sv_mutex); 609 smb_server_release(sv); 610 return (rc); 611 } 612 613 /* 614 * smb_server_nbt_listen: SMB-over-NetBIOS service 615 * 616 * Traditional SMB service over NetBIOS (port 139), which requires 617 * that a NetBIOS session be established. 618 */ 619 int 620 smb_server_nbt_listen(int error) 621 { 622 smb_server_t *sv; 623 int rc; 624 625 rc = smb_server_lookup(&sv); 626 if (rc) 627 return (rc); 628 629 mutex_enter(&sv->sv_mutex); 630 switch (sv->sv_state) { 631 case SMB_SERVER_STATE_RUNNING: 632 if ((sv->sv_nbt_daemon.ld_kth != NULL) && 633 (sv->sv_nbt_daemon.ld_kth != curthread)) { 634 mutex_exit(&sv->sv_mutex); 635 return (EACCES); 636 } else { 637 sv->sv_nbt_daemon.ld_kth = curthread; 638 sv->sv_nbt_daemon.ld_ktdid = curthread->t_did; 639 } 640 break; 641 default: 642 ASSERT((sv->sv_state == SMB_SERVER_STATE_CREATED) || 643 (sv->sv_state == SMB_SERVER_STATE_CONFIGURED) || 644 (sv->sv_state == SMB_SERVER_STATE_DELETING)); 645 mutex_exit(&sv->sv_mutex); 646 smb_server_release(sv); 647 return (EFAULT); 648 } 649 mutex_exit(&sv->sv_mutex); 650 651 /* 652 * netbios must be ipv4 653 */ 654 rc = smb_server_listen(sv, &sv->sv_nbt_daemon, SSN_SRVC_TCP_PORT, 655 AF_INET, error); 656 657 if (rc) { 658 mutex_enter(&sv->sv_mutex); 659 sv->sv_nbt_daemon.ld_kth = NULL; 660 mutex_exit(&sv->sv_mutex); 661 } 662 663 smb_server_release(sv); 664 665 return (rc); 666 } 667 668 int 669 smb_server_tcp_listen(int error) 670 { 671 smb_server_t *sv; 672 int rc; 673 674 rc = smb_server_lookup(&sv); 675 if (rc) 676 return (rc); 677 678 mutex_enter(&sv->sv_mutex); 679 switch (sv->sv_state) { 680 case SMB_SERVER_STATE_RUNNING: 681 if ((sv->sv_tcp_daemon.ld_kth) && 682 (sv->sv_tcp_daemon.ld_kth != curthread)) { 683 mutex_exit(&sv->sv_mutex); 684 return (EACCES); 685 } else { 686 sv->sv_tcp_daemon.ld_kth = curthread; 687 sv->sv_tcp_daemon.ld_ktdid = curthread->t_did; 688 } 689 break; 690 default: 691 ASSERT((sv->sv_state == SMB_SERVER_STATE_CREATED) || 692 (sv->sv_state == SMB_SERVER_STATE_CONFIGURED) || 693 (sv->sv_state == SMB_SERVER_STATE_DELETING)); 694 mutex_exit(&sv->sv_mutex); 695 return (EFAULT); 696 } 697 mutex_exit(&sv->sv_mutex); 698 699 if (sv->sv_cfg.skc_ipv6_enable) 700 rc = smb_server_listen(sv, &sv->sv_tcp_daemon, 701 SMB_SRVC_TCP_PORT, AF_INET6, error); 702 else 703 rc = smb_server_listen(sv, &sv->sv_tcp_daemon, 704 SMB_SRVC_TCP_PORT, AF_INET, error); 705 if (rc) { 706 mutex_enter(&sv->sv_mutex); 707 sv->sv_tcp_daemon.ld_kth = NULL; 708 mutex_exit(&sv->sv_mutex); 709 } 710 711 smb_server_release(sv); 712 713 return (rc); 714 } 715 716 /* 717 * smb_server_nbt_receive 718 */ 719 int 720 smb_server_nbt_receive(void) 721 { 722 int rc; 723 smb_server_t *sv; 724 725 rc = smb_server_lookup(&sv); 726 if (rc) 727 return (rc); 728 729 rc = smb_session_daemon(&sv->sv_nbt_daemon.ld_session_list); 730 731 smb_server_release(sv); 732 733 return (rc); 734 } 735 736 /* 737 * smb_server_tcp_receive 738 */ 739 int 740 smb_server_tcp_receive(void) 741 { 742 int rc; 743 smb_server_t *sv; 744 745 rc = smb_server_lookup(&sv); 746 if (rc) 747 return (rc); 748 749 rc = smb_session_daemon(&sv->sv_tcp_daemon.ld_session_list); 750 751 smb_server_release(sv); 752 753 return (rc); 754 } 755 756 int 757 smb_server_set_gmtoff(int32_t goff) 758 { 759 int rc; 760 smb_server_t *sv; 761 762 763 rc = smb_server_lookup(&sv); 764 if (rc) 765 return (rc); 766 767 sv->si_gmtoff = goff; 768 769 smb_server_release(sv); 770 771 return (rc); 772 } 773 774 /* 775 * ***************************************************************************** 776 * ****************** Functions called from the door interface ***************** 777 * ***************************************************************************** 778 * 779 * These functions determine the relevant smb server to which the call apply. 780 */ 781 782 uint32_t 783 smb_server_get_user_count(void) 784 { 785 smb_server_t *sv; 786 uint32_t counter = 0; 787 788 if (smb_server_lookup(&sv)) 789 return (0); 790 791 counter = (uint32_t)sv->sv_open_users; 792 793 smb_server_release(sv); 794 795 return (counter); 796 } 797 798 uint32_t 799 smb_server_get_session_count(void) 800 { 801 smb_server_t *sv; 802 uint32_t counter = 0; 803 804 if (smb_server_lookup(&sv)) 805 return (0); 806 807 rw_enter(&sv->sv_nbt_daemon.ld_session_list.se_lock, RW_READER); 808 counter = sv->sv_nbt_daemon.ld_session_list.se_act.count; 809 rw_exit(&sv->sv_nbt_daemon.ld_session_list.se_lock); 810 rw_enter(&sv->sv_tcp_daemon.ld_session_list.se_lock, RW_READER); 811 counter += sv->sv_tcp_daemon.ld_session_list.se_act.count; 812 rw_exit(&sv->sv_tcp_daemon.ld_session_list.se_lock); 813 814 smb_server_release(sv); 815 816 return (counter); 817 } 818 819 /* 820 * smb_server_disconnect_share 821 * 822 * Disconnects the specified share. This function should be called after the 823 * share passed in has been made unavailable by the "share manager". 824 */ 825 static void 826 smb_server_disconnect_share(char *sharename, smb_server_t *sv) 827 { 828 smb_session_disconnect_share(&sv->sv_nbt_daemon.ld_session_list, 829 sharename); 830 smb_session_disconnect_share(&sv->sv_tcp_daemon.ld_session_list, 831 sharename); 832 } 833 834 int 835 smb_server_dr_ulist_get(int offset, smb_dr_ulist_t *dr_ulist, int max_cnt) 836 { 837 smb_server_t *sv; 838 839 if (!dr_ulist) 840 return (-1); 841 842 if (smb_server_lookup(&sv)) 843 return (-1); 844 845 dr_ulist->dul_cnt = 846 smb_server_ulist_geti(&sv->sv_nbt_daemon.ld_session_list, 847 offset, dr_ulist->dul_users, max_cnt); 848 dr_ulist->dul_cnt += 849 smb_server_ulist_geti(&sv->sv_tcp_daemon.ld_session_list, 850 offset - dr_ulist->dul_cnt, &dr_ulist->dul_users[dr_ulist->dul_cnt], 851 max_cnt); 852 853 return (dr_ulist->dul_cnt); 854 } 855 856 /* 857 * smb_server_share_export() 858 * 859 * This function handles kernel processing at share enable time. 860 * 861 * At share-enable time (LMSHRD_ADD), the file system corresponding to 862 * the share is checked for characteristics that are required for SMB 863 * sharing. If this check passes, then a hold is taken on the root vnode 864 * of the file system (or a reference count on the corresponding smb_vfs_t 865 * is bumped), preventing an unmount. (See smb_vfs_hold()). 866 */ 867 868 int 869 smb_server_share_export(char *path) 870 { 871 smb_server_t *sv; 872 int error; 873 smb_node_t *fnode = NULL; 874 smb_node_t *dnode; 875 smb_attr_t ret_attr; 876 char last_comp[MAXNAMELEN]; 877 smb_request_t *sr; 878 879 if (smb_server_lookup(&sv)) 880 return (EINVAL); 881 882 sr = smb_request_alloc(sv->sv_session, 0); 883 if (sr == NULL) { 884 smb_server_release(sv); 885 return (ENOMEM); 886 } 887 888 sr->user_cr = kcred; 889 890 error = smb_pathname_reduce(sr, kcred, path, NULL, NULL, &dnode, 891 last_comp); 892 893 if (error) { 894 smb_request_free(sr); 895 smb_server_release(sv); 896 return (error); 897 } 898 899 error = smb_fsop_lookup(sr, sr->user_cr, SMB_FOLLOW_LINKS, NULL, dnode, 900 last_comp, &fnode, &ret_attr, NULL, NULL); 901 902 smb_node_release(dnode); 903 904 if (error) { 905 smb_request_free(sr); 906 smb_server_release(sv); 907 return (error); 908 } 909 910 ASSERT(fnode->vp && fnode->vp->v_vfsp); 911 912 #ifdef SMB_ENFORCE_NODEV 913 if (vfs_optionisset(fnode->vp->v_vfsp, MNTOPT_NODEVICES, NULL) == 0) 914 return (EINVAL); 915 #endif /* SMB_ENFORCE_NODEV */ 916 917 if (!smb_vfs_hold(sv, fnode->vp->v_vfsp)) { 918 smb_node_release(fnode); 919 smb_request_free(sr); 920 smb_server_release(sv); 921 return (ENOMEM); 922 } 923 924 /* 925 * The refcount on the smb_vfs has been incremented. 926 * If it wasn't already, a hold has also been taken 927 * on the root vnode of the file system. 928 */ 929 930 smb_node_release(fnode); 931 smb_request_free(sr); 932 smb_server_release(sv); 933 return (0); 934 } 935 936 937 938 /* 939 * smb_server_share_unexport() 940 * 941 * This function is invoked when a share is disabled to disconnect trees 942 * and close files. Cleaning up may involve VOP and/or VFS calls, which 943 * may conflict/deadlock with stuck threads if something is amiss with the 944 * file system. Queueing the request for asynchronous processing allows the 945 * call to return immediately so that, if the unshare is being done in the 946 * context of a forced unmount, the forced unmount will always be able to 947 * proceed (unblocking stuck I/O and eventually allowing all blocked unshare 948 * processes to complete). 949 * 950 * The path lookup to find the root vnode of the VFS in question and the 951 * release of this vnode are done synchronously prior to any associated 952 * unmount. Doing these asynchronous to an associated unmount could run 953 * the risk of a spurious EBUSY for a standard unmount or an EIO during 954 * the path lookup due to a forced unmount finishing first. 955 */ 956 957 int 958 smb_server_share_unexport(char *path, char *sharename) 959 { 960 smb_server_t *sv; 961 smb_request_t *sr; 962 smb_unexport_t *ux; 963 smb_node_t *fnode = NULL; 964 smb_node_t *dnode; 965 smb_attr_t ret_attr; 966 char last_comp[MAXNAMELEN]; 967 int rc; 968 969 if ((rc = smb_server_lookup(&sv))) 970 return (rc); 971 972 sr = smb_request_alloc(sv->sv_session, 0); 973 974 if (sr == NULL) { 975 smb_server_release(sv); 976 return (ENOMEM); 977 } 978 979 sr->user_cr = kcred; 980 981 rc = smb_pathname_reduce(sr, kcred, path, NULL, NULL, &dnode, 982 last_comp); 983 984 if (rc) { 985 smb_request_free(sr); 986 smb_server_release(sv); 987 return (rc); 988 } 989 990 rc = smb_fsop_lookup(sr, kcred, SMB_FOLLOW_LINKS, NULL, dnode, 991 last_comp, &fnode, &ret_attr, NULL, NULL); 992 993 smb_node_release(dnode); 994 smb_request_free(sr); 995 996 if (rc) { 997 smb_server_release(sv); 998 return (rc); 999 } 1000 1001 ASSERT(fnode->vp && fnode->vp->v_vfsp); 1002 1003 smb_vfs_rele(sv, fnode->vp->v_vfsp); 1004 1005 smb_node_release(fnode); 1006 1007 ux = kmem_cache_alloc(sv->si_cache_unexport, KM_SLEEP); 1008 1009 (void) strlcpy(ux->ux_sharename, sharename, MAXNAMELEN); 1010 1011 smb_slist_insert_tail(&sv->sv_unexport_list, ux); 1012 smb_thread_signal(&sv->si_thread_unexport); 1013 1014 smb_server_release(sv); 1015 return (0); 1016 } 1017 1018 /* 1019 * smb_server_thread_unexport 1020 * 1021 * This function processes the unexport event list and disconnects shares 1022 * asynchronously. The function executes as a zone-specific thread. 1023 * 1024 * The server arg passed in is safe to use without a reference count, because 1025 * the server cannot be deleted until smb_thread_stop()/destroy() return, 1026 * which is also when the thread exits. 1027 */ 1028 1029 static void 1030 smb_server_thread_unexport(smb_thread_t *thread, void *arg) 1031 { 1032 smb_server_t *sv = (smb_server_t *)arg; 1033 smb_unexport_t *ux; 1034 1035 while (smb_thread_continue(thread)) { 1036 while ((ux = list_head(&sv->sv_unexport_list.sl_list)) 1037 != NULL) { 1038 smb_slist_remove(&sv->sv_unexport_list, ux); 1039 smb_server_disconnect_share(ux->ux_sharename, sv); 1040 kmem_cache_free(sv->si_cache_unexport, ux); 1041 } 1042 } 1043 } 1044 1045 /* 1046 * This is a special interface that will be utilized by ZFS to cause a share to 1047 * be added/removed. 1048 * 1049 * arg is either a lmshare_info_t or share_name from userspace. 1050 * It will need to be copied into the kernel. It is lmshare_info_t 1051 * for add operations and share_name for delete operations. 1052 */ 1053 int 1054 smb_server_share(void *arg, boolean_t add_share) 1055 { 1056 smb_server_t *sv; 1057 int rc; 1058 1059 rc = smb_server_lookup(&sv); 1060 if (rc == 0) { 1061 mutex_enter(&sv->sv_mutex); 1062 if (sv->sv_state == SMB_SERVER_STATE_RUNNING) { 1063 mutex_exit(&sv->sv_mutex); 1064 rc = smb_kshare_upcall(sv->sv_lmshrd, arg, add_share); 1065 } else { 1066 mutex_exit(&sv->sv_mutex); 1067 rc = EPERM; 1068 } 1069 smb_server_release(sv); 1070 } 1071 return (rc); 1072 } 1073 1074 /* 1075 * ***************************************************************************** 1076 * **************** Functions called from the internal layers ****************** 1077 * ***************************************************************************** 1078 * 1079 * These functions are provided the relevant smb server by the caller. 1080 */ 1081 1082 void 1083 smb_server_reconnection_check(smb_server_t *sv, smb_session_t *session) 1084 { 1085 ASSERT(sv == session->s_server); 1086 1087 smb_session_reconnection_check(&sv->sv_nbt_daemon.ld_session_list, 1088 session); 1089 smb_session_reconnection_check(&sv->sv_tcp_daemon.ld_session_list, 1090 session); 1091 } 1092 1093 void 1094 smb_server_get_cfg(smb_server_t *sv, smb_kmod_cfg_t *cfg) 1095 { 1096 rw_enter(&sv->sv_cfg_lock, RW_READER); 1097 bcopy(&sv->sv_cfg, cfg, sizeof (*cfg)); 1098 rw_exit(&sv->sv_cfg_lock); 1099 } 1100 1101 /* 1102 * ***************************************************************************** 1103 * *************************** Static Functions ******************************** 1104 * ***************************************************************************** 1105 */ 1106 1107 static void 1108 smb_server_timers(smb_thread_t *thread, void *arg) 1109 { 1110 smb_server_t *sv = (smb_server_t *)arg; 1111 1112 ASSERT(sv != NULL); 1113 1114 while (smb_thread_continue_timedwait(thread, 1 /* Seconds */)) { 1115 smb_session_timers(&sv->sv_nbt_daemon.ld_session_list); 1116 smb_session_timers(&sv->sv_tcp_daemon.ld_session_list); 1117 } 1118 } 1119 1120 /* 1121 * smb_server_kstat_init 1122 */ 1123 static int 1124 smb_server_kstat_init(smb_server_t *sv) 1125 { 1126 (void) snprintf(sv->sv_ksp_name, sizeof (sv->sv_ksp_name), "%s%d", 1127 SMBSRV_KSTAT_NAME, sv->sv_zid); 1128 1129 sv->sv_ksp = kstat_create(SMBSRV_KSTAT_MODULE, 0, sv->sv_ksp_name, 1130 SMBSRV_KSTAT_CLASS, KSTAT_TYPE_NAMED, 1131 sizeof (sv->sv_ks_data) / sizeof (kstat_named_t), 1132 KSTAT_FLAG_VIRTUAL); 1133 1134 if (sv->sv_ksp) { 1135 (void) strlcpy(sv->sv_ks_data.open_files.name, "open_files", 1136 sizeof (sv->sv_ks_data.open_files.name)); 1137 sv->sv_ks_data.open_files.data_type = KSTAT_DATA_UINT32; 1138 (void) strlcpy(sv->sv_ks_data.open_trees.name, "connections", 1139 sizeof (sv->sv_ks_data.open_trees.name)); 1140 sv->sv_ks_data.open_trees.data_type = KSTAT_DATA_UINT32; 1141 (void) strlcpy(sv->sv_ks_data.open_users.name, "sessions", 1142 sizeof (sv->sv_ks_data.open_users.name)); 1143 sv->sv_ks_data.open_users.data_type = KSTAT_DATA_UINT32; 1144 1145 mutex_init(&sv->sv_ksp_mutex, NULL, MUTEX_DEFAULT, NULL); 1146 sv->sv_ksp->ks_lock = &sv->sv_ksp_mutex; 1147 sv->sv_ksp->ks_data = (void *)&sv->sv_ks_data; 1148 sv->sv_ksp->ks_update = smb_server_kstat_update_info; 1149 kstat_install(sv->sv_ksp); 1150 } 1151 1152 /* create and initialize smb kstats - smb_dispatch stats */ 1153 smb_dispatch_kstat_init(); 1154 1155 return (0); 1156 } 1157 1158 /* 1159 * smb_server_kstat_fini 1160 */ 1161 static void 1162 smb_server_kstat_fini(smb_server_t *sv) 1163 { 1164 if (sv->sv_ksp) { 1165 kstat_delete(sv->sv_ksp); 1166 mutex_destroy(&sv->sv_ksp_mutex); 1167 sv->sv_ksp = NULL; 1168 } 1169 smb_dispatch_kstat_fini(); 1170 } 1171 1172 /* ARGSUSED */ 1173 static int 1174 smb_server_kstat_update_info(kstat_t *ksp, int rw) 1175 { 1176 smb_server_t *sv; 1177 1178 if (rw == KSTAT_WRITE) { 1179 return (EACCES); 1180 } else { 1181 ASSERT(MUTEX_HELD(ksp->ks_lock)); 1182 1183 _NOTE(LINTED("pointer cast may result in improper alignment")) 1184 sv = (smb_server_t *)((uint8_t *)(ksp->ks_data) - 1185 offsetof(smb_server_t, sv_ks_data)); 1186 1187 ASSERT(sv->sv_magic == SMB_SERVER_MAGIC); 1188 1189 sv->sv_ks_data.open_files.value.ui32 = sv->sv_open_files; 1190 sv->sv_ks_data.open_trees.value.ui32 = sv->sv_open_trees; 1191 sv->sv_ks_data.open_users.value.ui32 = sv->sv_open_users; 1192 } 1193 return (0); 1194 } 1195 1196 /* 1197 * smb_server_stop 1198 * 1199 * The mutex of the server must have been entered before calling this function. 1200 */ 1201 static void 1202 smb_server_stop(smb_server_t *sv) 1203 { 1204 ASSERT(sv->sv_magic == SMB_SERVER_MAGIC); 1205 1206 smb_opipe_door_close(); 1207 smb_thread_stop(&sv->si_thread_timers); 1208 smb_thread_stop(&sv->si_thread_unexport); 1209 smb_kdoor_clnt_close(); 1210 smb_kshare_fini(sv->sv_lmshrd); 1211 sv->sv_lmshrd = NULL; 1212 smb_server_fsop_stop(sv); 1213 1214 if (sv->sv_session) { 1215 smb_session_delete(sv->sv_session); 1216 sv->sv_session = NULL; 1217 } 1218 1219 if (sv->sv_thread_pool) { 1220 taskq_destroy(sv->sv_thread_pool); 1221 sv->sv_thread_pool = NULL; 1222 } 1223 } 1224 1225 static int 1226 smb_server_listen( 1227 smb_server_t *sv, 1228 smb_listener_daemon_t *ld, 1229 in_port_t port, 1230 int family, 1231 int pthread_create_error) 1232 { 1233 int rc; 1234 ksocket_t s_so; 1235 const uint32_t on = 1; 1236 const uint32_t off = 0; 1237 smb_session_t *session; 1238 1239 if (pthread_create_error) { 1240 /* 1241 * Delete the last session created. The user space thread 1242 * creation failed. 1243 */ 1244 smb_session_list_delete_tail(&ld->ld_session_list); 1245 } 1246 1247 if (ld->ld_so == NULL) { 1248 /* First time listener */ 1249 if (family == AF_INET) { 1250 ld->ld_sin.sin_family = (uint32_t)family; 1251 ld->ld_sin.sin_port = htons(port); 1252 ld->ld_sin.sin_addr.s_addr = htonl(INADDR_ANY); 1253 } else { 1254 ld->ld_sin6.sin6_family = (uint32_t)family; 1255 ld->ld_sin6.sin6_port = htons(port); 1256 (void) memset(&ld->ld_sin6.sin6_addr.s6_addr, 0, 1257 sizeof (ld->ld_sin6.sin6_addr.s6_addr)); 1258 } 1259 ld->ld_so = smb_socreate(family, SOCK_STREAM, 0); 1260 if (ld->ld_so) { 1261 1262 (void) ksocket_setsockopt(ld->ld_so, SOL_SOCKET, 1263 SO_MAC_EXEMPT, &off, sizeof (off), CRED()); 1264 (void) ksocket_setsockopt(ld->ld_so, SOL_SOCKET, 1265 SO_REUSEADDR, &on, sizeof (on), CRED()); 1266 1267 if (family == AF_INET) { 1268 rc = ksocket_bind(ld->ld_so, 1269 (struct sockaddr *)&ld->ld_sin, 1270 sizeof (ld->ld_sin), CRED()); 1271 } else { 1272 rc = ksocket_bind(ld->ld_so, 1273 (struct sockaddr *)&ld->ld_sin6, 1274 sizeof (ld->ld_sin6), CRED()); 1275 } 1276 if (rc == 0) { 1277 rc = ksocket_listen(ld->ld_so, 20, CRED()); 1278 if (rc < 0) { 1279 cmn_err(CE_WARN, 1280 "Port %d: listen failed", port); 1281 smb_soshutdown(ld->ld_so); 1282 smb_sodestroy(ld->ld_so); 1283 ld->ld_so = NULL; 1284 return (rc); 1285 } 1286 } else { 1287 cmn_err(CE_WARN, 1288 "Port %d: bind failed", port); 1289 smb_soshutdown(ld->ld_so); 1290 smb_sodestroy(ld->ld_so); 1291 ld->ld_so = NULL; 1292 return (rc); 1293 } 1294 } else { 1295 cmn_err(CE_WARN, 1296 "Port %d: socket create failed", port); 1297 return (ENOMEM); 1298 } 1299 } 1300 1301 DTRACE_PROBE1(so__wait__accept, struct sonode *, ld->ld_so); 1302 1303 for (;;) { 1304 rc = ksocket_accept(ld->ld_so, NULL, NULL, &s_so, CRED()); 1305 if (rc == 0) { 1306 uint32_t txbuf_size = 128*1024; 1307 uint32_t on = 1; 1308 1309 DTRACE_PROBE1(so__accept, struct sonode *, s_so); 1310 1311 (void) ksocket_setsockopt(s_so, IPPROTO_TCP, 1312 TCP_NODELAY, &on, sizeof (on), CRED()); 1313 (void) ksocket_setsockopt(s_so, SOL_SOCKET, 1314 SO_KEEPALIVE, &on, sizeof (on), CRED()); 1315 (void) ksocket_setsockopt(s_so, SOL_SOCKET, SO_SNDBUF, 1316 (const void *)&txbuf_size, sizeof (txbuf_size), 1317 CRED()); 1318 /* 1319 * Create a session for this connection. 1320 */ 1321 session = smb_session_create(s_so, port, sv, family); 1322 if (session) { 1323 smb_session_list_append(&ld->ld_session_list, 1324 session); 1325 break; 1326 } else { 1327 smb_soshutdown(s_so); 1328 smb_sodestroy(s_so); 1329 } 1330 continue; 1331 } 1332 smb_session_list_signal(&ld->ld_session_list); 1333 smb_soshutdown(ld->ld_so); 1334 smb_sodestroy(ld->ld_so); 1335 ld->ld_so = NULL; 1336 break; 1337 } 1338 1339 return (rc); 1340 } 1341 1342 /* 1343 * smb_server_lookup 1344 * 1345 * This function tries to find the server associated with the zone of the 1346 * caller. 1347 */ 1348 static int 1349 smb_server_lookup(smb_server_t **psv) 1350 { 1351 zoneid_t zid; 1352 smb_server_t *sv; 1353 1354 zid = getzoneid(); 1355 1356 smb_llist_enter(&smb_servers, RW_READER); 1357 sv = smb_llist_head(&smb_servers); 1358 while (sv) { 1359 ASSERT(sv->sv_magic == SMB_SERVER_MAGIC); 1360 if (sv->sv_zid == zid) { 1361 mutex_enter(&sv->sv_mutex); 1362 if (sv->sv_state != SMB_SERVER_STATE_DELETING) { 1363 sv->sv_refcnt++; 1364 mutex_exit(&sv->sv_mutex); 1365 smb_llist_exit(&smb_servers); 1366 *psv = sv; 1367 return (0); 1368 } 1369 mutex_exit(&sv->sv_mutex); 1370 break; 1371 } 1372 sv = smb_llist_next(&smb_servers, sv); 1373 } 1374 smb_llist_exit(&smb_servers); 1375 return (EPERM); 1376 } 1377 1378 /* 1379 * smb_server_release 1380 * 1381 * This function decrements the reference count of the server and signals its 1382 * condition variable if the state of the server is SMB_SERVER_STATE_DELETING. 1383 */ 1384 static void 1385 smb_server_release(smb_server_t *sv) 1386 { 1387 ASSERT(sv->sv_magic == SMB_SERVER_MAGIC); 1388 1389 mutex_enter(&sv->sv_mutex); 1390 ASSERT(sv->sv_refcnt); 1391 sv->sv_refcnt--; 1392 if ((sv->sv_refcnt == 0) && (sv->sv_state == SMB_SERVER_STATE_DELETING)) 1393 cv_signal(&sv->sv_cv); 1394 mutex_exit(&sv->sv_mutex); 1395 } 1396 1397 static int 1398 smb_server_ulist_geti( 1399 smb_session_list_t *se, 1400 int offset, 1401 smb_opipe_context_t *ctx, 1402 int max_cnt) 1403 { 1404 smb_session_t *sn = NULL; 1405 smb_user_t *user; 1406 smb_llist_t *ulist; 1407 int cnt = 0, skip = 0; 1408 1409 rw_enter(&se->se_lock, RW_READER); 1410 sn = list_head(&se->se_act.lst); 1411 while (sn && (cnt < max_cnt)) { 1412 ASSERT(sn->s_magic == SMB_SESSION_MAGIC); 1413 ulist = &sn->s_user_list; 1414 smb_llist_enter(ulist, RW_READER); 1415 user = smb_llist_head(ulist); 1416 while (user && (cnt < max_cnt)) { 1417 ASSERT(user->u_magic == SMB_USER_MAGIC); 1418 mutex_enter(&user->u_mutex); 1419 if (user->u_state == SMB_USER_STATE_LOGGED_IN) { 1420 if (skip++ < offset) { 1421 mutex_exit(&user->u_mutex); 1422 user = smb_llist_next(ulist, user); 1423 continue; 1424 } 1425 1426 smb_user_context_init(user, ctx); 1427 ctx++; 1428 cnt++; 1429 } 1430 mutex_exit(&user->u_mutex); 1431 user = smb_llist_next(ulist, user); 1432 } 1433 smb_llist_exit(ulist); 1434 sn = list_next(&se->se_act.lst, sn); 1435 } 1436 rw_exit(&se->se_lock); 1437 return (cnt); 1438 } 1439 1440 static void 1441 smb_server_store_cfg(smb_server_t *sv, smb_kmod_cfg_t *cfg) 1442 { 1443 if (cfg->skc_maxconnections == 0) 1444 cfg->skc_maxconnections = 0xFFFFFFFF; 1445 1446 smb_session_correct_keep_alive_values( 1447 &sv->sv_nbt_daemon.ld_session_list, cfg->skc_keepalive); 1448 smb_session_correct_keep_alive_values( 1449 &sv->sv_tcp_daemon.ld_session_list, cfg->skc_keepalive); 1450 1451 bcopy(cfg, &sv->sv_cfg, sizeof (sv->sv_cfg)); 1452 } 1453 1454 static int 1455 smb_server_fsop_start(smb_server_t *sv) 1456 { 1457 int error; 1458 1459 error = smb_node_root_init(rootdir, sv, &sv->si_root_smb_node); 1460 if (error != 0) 1461 sv->si_root_smb_node = NULL; 1462 1463 return (error); 1464 } 1465 1466 static void 1467 smb_server_fsop_stop(smb_server_t *sv) 1468 { 1469 if (sv->si_root_smb_node != NULL) { 1470 smb_vfs_rele_all(sv); 1471 smb_node_release(sv->si_root_smb_node); 1472 sv->si_root_smb_node = NULL; 1473 } 1474 } 1475