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