1 /* 2 * CDDL HEADER START 3 * 4 * The contents of this file are subject to the terms of the 5 * Common Development and Distribution License (the "License"). 6 * You may not use this file except in compliance with the License. 7 * 8 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 9 * or http://www.opensolaris.org/os/licensing. 10 * See the License for the specific language governing permissions 11 * and limitations under the License. 12 * 13 * When distributing Covered Code, include this CDDL HEADER in each 14 * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 15 * If applicable, add the following below this CDDL HEADER, with the 16 * fields enclosed by brackets "[]" replaced with your own identifying 17 * information: Portions Copyright [yyyy] [name of copyright owner] 18 * 19 * CDDL HEADER END 20 */ 21 /* 22 * Copyright 2008 Sun Microsystems, Inc. All rights reserved. 23 * Use is subject to license terms. 24 */ 25 26 /* 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); 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_vop_init()) 271 continue; 272 if (rc = smb_node_init()) 273 continue; 274 if (rc = smb_fem_init()) 275 continue; 276 if (rc = smb_user_init()) 277 continue; 278 if (rc = smb_notify_init()) 279 continue; 280 if (rc = smb_net_init()) 281 continue; 282 if (rc = smb_kdoor_srv_start()) 283 continue; 284 smb_llist_constructor(&smb_servers, sizeof (smb_server_t), 285 offsetof(smb_server_t, sv_lnd)); 286 return (0); 287 } 288 smb_net_fini(); 289 smb_notify_fini(); 290 smb_user_fini(); 291 smb_fem_fini(); 292 smb_node_fini(); 293 smb_vop_fini(); 294 return (rc); 295 } 296 297 /* 298 * smb_server_svc_fini 299 * 300 * This function must called from smb_drv_detach(). It will fail if servers 301 * still exist. 302 */ 303 int 304 smb_server_svc_fini(void) 305 { 306 int rc = EBUSY; 307 308 if (smb_llist_get_count(&smb_servers) == 0) { 309 smb_kdoor_srv_stop(); 310 smb_net_fini(); 311 smb_notify_fini(); 312 smb_user_fini(); 313 smb_fem_fini(); 314 smb_node_fini(); 315 smb_vop_fini(); 316 smb_llist_destructor(&smb_servers); 317 rc = 0; 318 } 319 return (rc); 320 } 321 322 /* 323 * smb_server_create 324 * 325 * This function will fail if there's already a server associated with the 326 * caller's zone. 327 */ 328 int 329 smb_server_create(void) 330 { 331 zoneid_t zid; 332 smb_server_t *sv; 333 334 zid = getzoneid(); 335 336 smb_llist_enter(&smb_servers, RW_WRITER); 337 sv = smb_llist_head(&smb_servers); 338 while (sv) { 339 ASSERT(sv->sv_magic == SMB_SERVER_MAGIC); 340 if (sv->sv_zid == zid) { 341 smb_llist_exit(&smb_servers); 342 return (EEXIST); 343 } 344 sv = smb_llist_next(&smb_servers, sv); 345 } 346 347 sv = kmem_zalloc(sizeof (smb_server_t), KM_NOSLEEP); 348 if (sv == NULL) { 349 smb_llist_exit(&smb_servers); 350 return (ENOMEM); 351 } 352 353 smb_llist_constructor(&sv->sv_vfs_list, sizeof (smb_vfs_t), 354 offsetof(smb_vfs_t, sv_lnd)); 355 356 smb_slist_constructor(&sv->sv_unexport_list, sizeof (smb_unexport_t), 357 offsetof(smb_unexport_t, ux_lnd)); 358 359 smb_session_list_constructor(&sv->sv_nbt_daemon.ld_session_list); 360 smb_session_list_constructor(&sv->sv_tcp_daemon.ld_session_list); 361 362 sv->si_cache_unexport = kmem_cache_create("smb_unexport_cache", 363 sizeof (smb_unexport_t), 8, NULL, NULL, NULL, NULL, NULL, 0); 364 sv->si_cache_vfs = kmem_cache_create("smb_vfs_cache", 365 sizeof (smb_vfs_t), 8, NULL, NULL, NULL, NULL, NULL, 0); 366 sv->si_cache_request = kmem_cache_create("smb_request_cache", 367 sizeof (smb_request_t), 8, NULL, NULL, NULL, NULL, NULL, 0); 368 sv->si_cache_session = kmem_cache_create("smb_session_cache", 369 sizeof (smb_session_t), 8, NULL, NULL, NULL, NULL, NULL, 0); 370 sv->si_cache_user = kmem_cache_create("smb_user_cache", 371 sizeof (smb_user_t), 8, NULL, NULL, NULL, NULL, NULL, 0); 372 sv->si_cache_tree = kmem_cache_create("smb_tree_cache", 373 sizeof (smb_tree_t), 8, NULL, NULL, NULL, NULL, NULL, 0); 374 sv->si_cache_ofile = kmem_cache_create("smb_ofile_cache", 375 sizeof (smb_ofile_t), 8, NULL, NULL, NULL, NULL, NULL, 0); 376 sv->si_cache_odir = kmem_cache_create("smb_odir_cache", 377 sizeof (smb_odir_t), 8, NULL, NULL, NULL, NULL, NULL, 0); 378 sv->si_cache_node = kmem_cache_create("smb_node_cache", 379 sizeof (smb_node_t), 8, NULL, NULL, NULL, NULL, NULL, 0); 380 381 smb_thread_init(&sv->si_thread_timers, 382 "smb_timers", smb_server_timers, sv, 383 NULL, NULL); 384 385 smb_thread_init(&sv->si_thread_unexport, "smb_thread_unexport", 386 smb_server_thread_unexport, sv, NULL, NULL); 387 388 sv->sv_pid = curproc->p_pid; 389 390 smb_kdoor_clnt_init(); 391 smb_opipe_door_init(); 392 (void) smb_server_kstat_init(sv); 393 394 mutex_init(&sv->sv_mutex, NULL, MUTEX_DEFAULT, NULL); 395 cv_init(&sv->sv_cv, NULL, CV_DEFAULT, NULL); 396 sv->sv_state = SMB_SERVER_STATE_CREATED; 397 sv->sv_magic = SMB_SERVER_MAGIC; 398 sv->sv_zid = zid; 399 400 smb_llist_insert_tail(&smb_servers, sv); 401 smb_llist_exit(&smb_servers); 402 return (0); 403 } 404 405 /* 406 * smb_server_delete 407 * 408 * This function will delete the server passed in. It will make sure that all 409 * activity associated that server has ceased before destroying it. 410 */ 411 int 412 smb_server_delete(void) 413 { 414 smb_server_t *sv; 415 smb_unexport_t *ux; 416 int rc; 417 418 rc = smb_server_lookup(&sv); 419 if (rc != 0) 420 return (rc); 421 422 mutex_enter(&sv->sv_mutex); 423 switch (sv->sv_state) { 424 case SMB_SERVER_STATE_RUNNING: 425 { 426 boolean_t nbt = B_FALSE; 427 boolean_t tcp = B_FALSE; 428 429 if (sv->sv_nbt_daemon.ld_kth) { 430 tsignal(sv->sv_nbt_daemon.ld_kth, SIGINT); 431 nbt = B_TRUE; 432 } 433 if (sv->sv_tcp_daemon.ld_kth) { 434 tsignal(sv->sv_tcp_daemon.ld_kth, SIGINT); 435 tcp = B_TRUE; 436 } 437 sv->sv_state = SMB_SERVER_STATE_DELETING; 438 mutex_exit(&sv->sv_mutex); 439 if (nbt) 440 thread_join(sv->sv_nbt_daemon.ld_ktdid); 441 if (tcp) 442 thread_join(sv->sv_tcp_daemon.ld_ktdid); 443 mutex_enter(&sv->sv_mutex); 444 break; 445 } 446 case SMB_SERVER_STATE_CONFIGURED: 447 case SMB_SERVER_STATE_CREATED: 448 sv->sv_state = SMB_SERVER_STATE_DELETING; 449 break; 450 default: 451 ASSERT(sv->sv_state == SMB_SERVER_STATE_DELETING); 452 mutex_exit(&sv->sv_mutex); 453 smb_server_release(sv); 454 return (ENOTTY); 455 } 456 457 ASSERT(sv->sv_state == SMB_SERVER_STATE_DELETING); 458 459 sv->sv_refcnt--; 460 while (sv->sv_refcnt) 461 cv_wait(&sv->sv_cv, &sv->sv_mutex); 462 463 mutex_exit(&sv->sv_mutex); 464 465 smb_llist_enter(&smb_servers, RW_WRITER); 466 smb_llist_remove(&smb_servers, sv); 467 smb_llist_exit(&smb_servers); 468 469 smb_server_stop(sv); 470 rw_destroy(&sv->sv_cfg_lock); 471 smb_opipe_door_fini(); 472 smb_kdoor_clnt_fini(); 473 smb_server_kstat_fini(sv); 474 smb_llist_destructor(&sv->sv_vfs_list); 475 476 while ((ux = list_head(&sv->sv_unexport_list.sl_list)) != NULL) { 477 smb_slist_remove(&sv->sv_unexport_list, ux); 478 kmem_cache_free(sv->si_cache_unexport, ux); 479 } 480 smb_slist_destructor(&sv->sv_unexport_list); 481 482 kmem_cache_destroy(sv->si_cache_unexport); 483 kmem_cache_destroy(sv->si_cache_vfs); 484 kmem_cache_destroy(sv->si_cache_request); 485 kmem_cache_destroy(sv->si_cache_session); 486 kmem_cache_destroy(sv->si_cache_user); 487 kmem_cache_destroy(sv->si_cache_tree); 488 kmem_cache_destroy(sv->si_cache_ofile); 489 kmem_cache_destroy(sv->si_cache_odir); 490 kmem_cache_destroy(sv->si_cache_node); 491 492 smb_thread_destroy(&sv->si_thread_timers); 493 smb_thread_destroy(&sv->si_thread_unexport); 494 mutex_destroy(&sv->sv_mutex); 495 cv_destroy(&sv->sv_cv); 496 sv->sv_magic = 0; 497 kmem_free(sv, sizeof (smb_server_t)); 498 499 return (0); 500 } 501 502 /* 503 * smb_server_configure 504 */ 505 int 506 smb_server_configure(smb_kmod_cfg_t *cfg) 507 { 508 int rc = 0; 509 smb_server_t *sv; 510 511 rc = smb_server_lookup(&sv); 512 if (rc) 513 return (rc); 514 515 mutex_enter(&sv->sv_mutex); 516 switch (sv->sv_state) { 517 case SMB_SERVER_STATE_CREATED: 518 smb_server_store_cfg(sv, cfg); 519 sv->sv_state = SMB_SERVER_STATE_CONFIGURED; 520 break; 521 522 case SMB_SERVER_STATE_CONFIGURED: 523 smb_server_store_cfg(sv, cfg); 524 break; 525 526 case SMB_SERVER_STATE_RUNNING: 527 rw_enter(&sv->sv_cfg_lock, RW_WRITER); 528 smb_server_store_cfg(sv, cfg); 529 rw_exit(&sv->sv_cfg_lock); 530 break; 531 532 default: 533 ASSERT(sv->sv_state == SMB_SERVER_STATE_DELETING); 534 rc = EFAULT; 535 break; 536 } 537 mutex_exit(&sv->sv_mutex); 538 539 smb_server_release(sv); 540 541 return (rc); 542 } 543 544 /* 545 * smb_server_start 546 */ 547 int 548 smb_server_start(struct smb_io_start *io_start) 549 { 550 int rc = 0; 551 smb_server_t *sv; 552 553 rc = smb_server_lookup(&sv); 554 if (rc) 555 return (rc); 556 557 mutex_enter(&sv->sv_mutex); 558 switch (sv->sv_state) { 559 case SMB_SERVER_STATE_CONFIGURED: 560 561 sv->sv_thread_pool = taskq_create("smb_workers", 562 sv->sv_cfg.skc_maxworkers, SMB_WORKER_PRIORITY, 563 sv->sv_cfg.skc_maxworkers, INT_MAX, 564 TASKQ_DYNAMIC|TASKQ_PREPOPULATE); 565 566 sv->sv_session = smb_session_create(NULL, 0, sv); 567 568 if (sv->sv_thread_pool == NULL || sv->sv_session == NULL) { 569 rc = ENOMEM; 570 break; 571 } 572 573 if (rc = smb_server_fsop_start(sv)) 574 break; 575 ASSERT(sv->sv_lmshrd == NULL); 576 sv->sv_lmshrd = smb_kshare_init(io_start->lmshrd); 577 if (sv->sv_lmshrd == NULL) 578 break; 579 if (rc = smb_kdoor_clnt_open(io_start->udoor)) 580 break; 581 if (rc = smb_kdoor_srv_set_downcall()) { 582 cmn_err(CE_WARN, "Cannot set downcall descriptor"); 583 break; 584 } 585 if (rc = smb_thread_start(&sv->si_thread_timers)) 586 break; 587 if (rc = smb_thread_start(&sv->si_thread_unexport)) 588 break; 589 /* 590 * XXX We give up the NET_MAC_AWARE privilege because it keeps 591 * us from re-opening the connection when there are leftover TCP 592 * connections in TCPS_TIME_WAIT state. There seem to be some 593 * security ramifications around reestablishing a connection 594 * while possessing the NET_MAC_AWARE privilege. 595 * 596 * This approach may cause problems when we try to support 597 * zones. An alternative would be to retry the connection setup 598 * for a fixed period of time until the stale connections clear 599 * up but that implies we would be offline for a couple minutes 600 * every time the service is restarted with active connections. 601 */ 602 rc = setpflags(NET_MAC_AWARE, 0, CRED()); 603 if (rc) { 604 cmn_err(CE_WARN, 605 "Cannot remove NET_MAC_AWARE privilege"); 606 break; 607 } 608 if (rc = smb_opipe_door_open(io_start->opipe)) { 609 cmn_err(CE_WARN, "Cannot open opipe door"); 610 break; 611 } 612 sv->sv_state = SMB_SERVER_STATE_RUNNING; 613 mutex_exit(&sv->sv_mutex); 614 smb_server_release(sv); 615 return (0); 616 default: 617 ASSERT((sv->sv_state == SMB_SERVER_STATE_CREATED) || 618 (sv->sv_state == SMB_SERVER_STATE_RUNNING) || 619 (sv->sv_state == SMB_SERVER_STATE_DELETING)); 620 mutex_exit(&sv->sv_mutex); 621 smb_server_release(sv); 622 return (ENOTTY); 623 } 624 625 smb_server_stop(sv); 626 mutex_exit(&sv->sv_mutex); 627 smb_server_release(sv); 628 return (rc); 629 } 630 631 /* 632 * smb_server_nbt_listen: SMB-over-NetBIOS service 633 * 634 * Traditional SMB service over NetBIOS (port 139), which requires 635 * that a NetBIOS session be established. 636 */ 637 int 638 smb_server_nbt_listen(int error) 639 { 640 smb_server_t *sv; 641 int rc; 642 643 rc = smb_server_lookup(&sv); 644 if (rc) 645 return (rc); 646 647 mutex_enter(&sv->sv_mutex); 648 switch (sv->sv_state) { 649 case SMB_SERVER_STATE_RUNNING: 650 if ((sv->sv_nbt_daemon.ld_kth != NULL) && 651 (sv->sv_nbt_daemon.ld_kth != curthread)) { 652 mutex_exit(&sv->sv_mutex); 653 return (EACCES); 654 } else { 655 sv->sv_nbt_daemon.ld_kth = curthread; 656 sv->sv_nbt_daemon.ld_ktdid = curthread->t_did; 657 } 658 break; 659 default: 660 ASSERT((sv->sv_state == SMB_SERVER_STATE_CREATED) || 661 (sv->sv_state == SMB_SERVER_STATE_CONFIGURED) || 662 (sv->sv_state == SMB_SERVER_STATE_DELETING)); 663 mutex_exit(&sv->sv_mutex); 664 smb_server_release(sv); 665 return (EFAULT); 666 } 667 mutex_exit(&sv->sv_mutex); 668 669 rc = smb_server_listen(sv, &sv->sv_nbt_daemon, SSN_SRVC_TCP_PORT, 670 error); 671 672 if (rc) { 673 mutex_enter(&sv->sv_mutex); 674 sv->sv_nbt_daemon.ld_kth = NULL; 675 mutex_exit(&sv->sv_mutex); 676 } 677 678 smb_server_release(sv); 679 680 return (rc); 681 } 682 683 int 684 smb_server_tcp_listen(int error) 685 { 686 smb_server_t *sv; 687 int rc; 688 689 rc = smb_server_lookup(&sv); 690 if (rc) 691 return (rc); 692 693 mutex_enter(&sv->sv_mutex); 694 switch (sv->sv_state) { 695 case SMB_SERVER_STATE_RUNNING: 696 if ((sv->sv_tcp_daemon.ld_kth) && 697 (sv->sv_tcp_daemon.ld_kth != curthread)) { 698 mutex_exit(&sv->sv_mutex); 699 return (EACCES); 700 } else { 701 sv->sv_tcp_daemon.ld_kth = curthread; 702 sv->sv_tcp_daemon.ld_ktdid = curthread->t_did; 703 } 704 break; 705 default: 706 ASSERT((sv->sv_state == SMB_SERVER_STATE_CREATED) || 707 (sv->sv_state == SMB_SERVER_STATE_CONFIGURED) || 708 (sv->sv_state == SMB_SERVER_STATE_DELETING)); 709 mutex_exit(&sv->sv_mutex); 710 return (EFAULT); 711 } 712 mutex_exit(&sv->sv_mutex); 713 714 rc = smb_server_listen(sv, &sv->sv_tcp_daemon, SMB_SRVC_TCP_PORT, 715 error); 716 717 if (rc) { 718 mutex_enter(&sv->sv_mutex); 719 sv->sv_tcp_daemon.ld_kth = NULL; 720 mutex_exit(&sv->sv_mutex); 721 } 722 723 smb_server_release(sv); 724 725 return (rc); 726 } 727 728 /* 729 * smb_server_nbt_receive 730 */ 731 int 732 smb_server_nbt_receive(void) 733 { 734 int rc; 735 smb_server_t *sv; 736 737 rc = smb_server_lookup(&sv); 738 if (rc) 739 return (rc); 740 741 rc = smb_session_daemon(&sv->sv_nbt_daemon.ld_session_list); 742 743 smb_server_release(sv); 744 745 return (rc); 746 } 747 748 /* 749 * smb_server_tcp_receive 750 */ 751 int 752 smb_server_tcp_receive(void) 753 { 754 int rc; 755 smb_server_t *sv; 756 757 rc = smb_server_lookup(&sv); 758 if (rc) 759 return (rc); 760 761 rc = smb_session_daemon(&sv->sv_tcp_daemon.ld_session_list); 762 763 smb_server_release(sv); 764 765 return (rc); 766 } 767 768 int 769 smb_server_set_gmtoff(int32_t goff) 770 { 771 int rc; 772 smb_server_t *sv; 773 774 775 rc = smb_server_lookup(&sv); 776 if (rc) 777 return (rc); 778 779 sv->si_gmtoff = goff; 780 781 smb_server_release(sv); 782 783 return (rc); 784 } 785 786 /* 787 * ***************************************************************************** 788 * ****************** Functions called from the door interface ***************** 789 * ***************************************************************************** 790 * 791 * These functions determine the relevant smb server to which the call apply. 792 */ 793 794 uint32_t 795 smb_server_get_user_count(void) 796 { 797 smb_server_t *sv; 798 uint32_t counter = 0; 799 800 if (smb_server_lookup(&sv)) 801 return (0); 802 803 counter = (uint32_t)sv->sv_open_users; 804 805 smb_server_release(sv); 806 807 return (counter); 808 } 809 810 uint32_t 811 smb_server_get_session_count(void) 812 { 813 smb_server_t *sv; 814 uint32_t counter = 0; 815 816 if (smb_server_lookup(&sv)) 817 return (0); 818 819 rw_enter(&sv->sv_nbt_daemon.ld_session_list.se_lock, RW_READER); 820 counter = sv->sv_nbt_daemon.ld_session_list.se_act.count; 821 rw_exit(&sv->sv_nbt_daemon.ld_session_list.se_lock); 822 rw_enter(&sv->sv_tcp_daemon.ld_session_list.se_lock, RW_READER); 823 counter += sv->sv_tcp_daemon.ld_session_list.se_act.count; 824 rw_exit(&sv->sv_tcp_daemon.ld_session_list.se_lock); 825 826 smb_server_release(sv); 827 828 return (counter); 829 } 830 831 /* 832 * smb_server_disconnect_share 833 * 834 * Disconnects the specified share. This function should be called after the 835 * share passed in has been made unavailable by the "share manager". 836 */ 837 static void 838 smb_server_disconnect_share(char *sharename, smb_server_t *sv) 839 { 840 smb_session_disconnect_share(&sv->sv_nbt_daemon.ld_session_list, 841 sharename); 842 smb_session_disconnect_share(&sv->sv_tcp_daemon.ld_session_list, 843 sharename); 844 } 845 846 int 847 smb_server_dr_ulist_get(int offset, smb_dr_ulist_t *dr_ulist, int max_cnt) 848 { 849 smb_server_t *sv; 850 851 if (!dr_ulist) 852 return (-1); 853 854 if (smb_server_lookup(&sv)) 855 return (-1); 856 857 dr_ulist->dul_cnt = 858 smb_server_ulist_geti(&sv->sv_nbt_daemon.ld_session_list, 859 offset, dr_ulist->dul_users, max_cnt); 860 dr_ulist->dul_cnt += 861 smb_server_ulist_geti(&sv->sv_tcp_daemon.ld_session_list, 862 offset - dr_ulist->dul_cnt, &dr_ulist->dul_users[dr_ulist->dul_cnt], 863 max_cnt); 864 865 return (dr_ulist->dul_cnt); 866 } 867 868 /* 869 * smb_server_share_export() 870 * 871 * This function handles kernel processing at share enable time. 872 * 873 * At share-enable time (LMSHRD_ADD), the file system corresponding to 874 * the share is checked for characteristics that are required for SMB 875 * sharing. If this check passes, then a hold is taken on the root vnode 876 * of the file system (or a reference count on the corresponding smb_vfs_t 877 * is bumped), preventing an unmount. (See smb_vfs_hold()). 878 */ 879 880 int 881 smb_server_share_export(char *path) 882 { 883 smb_server_t *sv; 884 int error; 885 smb_node_t *fnode = NULL; 886 smb_node_t *dnode; 887 smb_attr_t ret_attr; 888 char last_comp[MAXNAMELEN]; 889 smb_request_t *sr; 890 891 if (smb_server_lookup(&sv)) 892 return (EINVAL); 893 894 sr = smb_request_alloc(sv->sv_session, 0); 895 if (sr == NULL) { 896 smb_server_release(sv); 897 return (ENOMEM); 898 } 899 900 sr->user_cr = kcred; 901 902 error = smb_pathname_reduce(sr, kcred, path, NULL, NULL, &dnode, 903 last_comp); 904 905 if (error) { 906 smb_request_free(sr); 907 smb_server_release(sv); 908 return (error); 909 } 910 911 error = smb_fsop_lookup(sr, sr->user_cr, SMB_FOLLOW_LINKS, NULL, dnode, 912 last_comp, &fnode, &ret_attr, NULL, NULL); 913 914 smb_node_release(dnode); 915 916 if (error) { 917 smb_request_free(sr); 918 smb_server_release(sv); 919 return (error); 920 } 921 922 ASSERT(fnode->vp && fnode->vp->v_vfsp); 923 924 #ifdef SMB_ENFORCE_NODEV 925 if (vfs_optionisset(fnode->vp->v_vfsp, MNTOPT_NODEVICES, NULL) == 0) 926 return (EINVAL); 927 #endif /* SMB_ENFORCE_NODEV */ 928 929 if (!smb_vfs_hold(sv, fnode->vp->v_vfsp)) { 930 smb_node_release(fnode); 931 smb_request_free(sr); 932 smb_server_release(sv); 933 return (ENOMEM); 934 } 935 936 /* 937 * The refcount on the smb_vfs has been incremented. 938 * If it wasn't already, a hold has also been taken 939 * on the root vnode of the file system. 940 */ 941 942 smb_node_release(fnode); 943 smb_request_free(sr); 944 smb_server_release(sv); 945 return (0); 946 } 947 948 949 950 /* 951 * smb_server_share_unexport() 952 * 953 * This function is invoked when a share is disabled to disconnect trees 954 * and close files. Cleaning up may involve VOP and/or VFS calls, which 955 * may conflict/deadlock with stuck threads if something is amiss with the 956 * file system. Queueing the request for asynchronous processing allows the 957 * call to return immediately so that, if the unshare is being done in the 958 * context of a forced unmount, the forced unmount will always be able to 959 * proceed (unblocking stuck I/O and eventually allowing all blocked unshare 960 * processes to complete). 961 * 962 * The path lookup to find the root vnode of the VFS in question and the 963 * release of this vnode are done synchronously prior to any associated 964 * unmount. Doing these asynchronous to an associated unmount could run 965 * the risk of a spurious EBUSY for a standard unmount or an EIO during 966 * the path lookup due to a forced unmount finishing first. 967 */ 968 969 int 970 smb_server_share_unexport(char *path, char *sharename) 971 { 972 smb_server_t *sv; 973 smb_request_t *sr; 974 smb_unexport_t *ux; 975 smb_node_t *fnode = NULL; 976 smb_node_t *dnode; 977 smb_attr_t ret_attr; 978 char last_comp[MAXNAMELEN]; 979 int rc; 980 981 if ((rc = smb_server_lookup(&sv))) 982 return (rc); 983 984 sr = smb_request_alloc(sv->sv_session, 0); 985 986 if (sr == NULL) { 987 smb_server_release(sv); 988 return (ENOMEM); 989 } 990 991 sr->user_cr = kcred; 992 993 rc = smb_pathname_reduce(sr, kcred, path, NULL, NULL, &dnode, 994 last_comp); 995 996 if (rc) { 997 smb_request_free(sr); 998 smb_server_release(sv); 999 return (rc); 1000 } 1001 1002 rc = smb_fsop_lookup(sr, kcred, SMB_FOLLOW_LINKS, NULL, dnode, 1003 last_comp, &fnode, &ret_attr, NULL, NULL); 1004 1005 smb_node_release(dnode); 1006 smb_request_free(sr); 1007 1008 if (rc) { 1009 smb_server_release(sv); 1010 return (rc); 1011 } 1012 1013 ASSERT(fnode->vp && fnode->vp->v_vfsp); 1014 1015 smb_vfs_rele(sv, fnode->vp->v_vfsp); 1016 1017 smb_node_release(fnode); 1018 1019 ux = kmem_cache_alloc(sv->si_cache_unexport, KM_SLEEP); 1020 1021 (void) strlcpy(ux->ux_sharename, sharename, MAXNAMELEN); 1022 1023 smb_slist_insert_tail(&sv->sv_unexport_list, ux); 1024 smb_thread_signal(&sv->si_thread_unexport); 1025 1026 smb_server_release(sv); 1027 return (0); 1028 } 1029 1030 /* 1031 * smb_server_thread_unexport 1032 * 1033 * This function processes the unexport event list and disconnects shares 1034 * asynchronously. The function executes as a zone-specific thread. 1035 * 1036 * The server arg passed in is safe to use without a reference count, because 1037 * the server cannot be deleted until smb_thread_stop()/destroy() return, 1038 * which is also when the thread exits. 1039 */ 1040 1041 static void 1042 smb_server_thread_unexport(smb_thread_t *thread, void *arg) 1043 { 1044 smb_server_t *sv = (smb_server_t *)arg; 1045 smb_unexport_t *ux; 1046 1047 while (smb_thread_continue(thread)) { 1048 while ((ux = list_head(&sv->sv_unexport_list.sl_list)) 1049 != NULL) { 1050 smb_slist_remove(&sv->sv_unexport_list, ux); 1051 smb_server_disconnect_share(ux->ux_sharename, sv); 1052 kmem_cache_free(sv->si_cache_unexport, ux); 1053 } 1054 } 1055 } 1056 1057 /* 1058 * This is a special interface that will be utilized by ZFS to cause a share to 1059 * be added/removed. 1060 * 1061 * arg is either a lmshare_info_t or share_name from userspace. 1062 * It will need to be copied into the kernel. It is lmshare_info_t 1063 * for add operations and share_name for delete operations. 1064 */ 1065 int 1066 smb_server_share(void *arg, boolean_t add_share) 1067 { 1068 smb_server_t *sv; 1069 int rc; 1070 1071 rc = smb_server_lookup(&sv); 1072 if (rc == 0) { 1073 mutex_enter(&sv->sv_mutex); 1074 if (sv->sv_state == SMB_SERVER_STATE_RUNNING) { 1075 mutex_exit(&sv->sv_mutex); 1076 rc = smb_kshare_upcall(sv->sv_lmshrd, arg, add_share); 1077 } else { 1078 mutex_exit(&sv->sv_mutex); 1079 rc = EPERM; 1080 } 1081 smb_server_release(sv); 1082 } 1083 return (rc); 1084 } 1085 1086 /* 1087 * ***************************************************************************** 1088 * **************** Functions called from the internal layers ****************** 1089 * ***************************************************************************** 1090 * 1091 * These functions are provided the relevant smb server by the caller. 1092 */ 1093 1094 void 1095 smb_server_reconnection_check(smb_server_t *sv, smb_session_t *session) 1096 { 1097 ASSERT(sv == session->s_server); 1098 1099 smb_session_reconnection_check(&sv->sv_nbt_daemon.ld_session_list, 1100 session); 1101 smb_session_reconnection_check(&sv->sv_tcp_daemon.ld_session_list, 1102 session); 1103 } 1104 1105 void 1106 smb_server_get_cfg(smb_server_t *sv, smb_kmod_cfg_t *cfg) 1107 { 1108 rw_enter(&sv->sv_cfg_lock, RW_READER); 1109 bcopy(&sv->sv_cfg, cfg, sizeof (*cfg)); 1110 rw_exit(&sv->sv_cfg_lock); 1111 } 1112 1113 /* 1114 * ***************************************************************************** 1115 * *************************** Static Functions ******************************** 1116 * ***************************************************************************** 1117 */ 1118 1119 static void 1120 smb_server_timers(smb_thread_t *thread, void *arg) 1121 { 1122 smb_server_t *sv = (smb_server_t *)arg; 1123 1124 ASSERT(sv != NULL); 1125 1126 while (smb_thread_continue_timedwait(thread, 1 /* Seconds */)) { 1127 smb_session_timers(&sv->sv_nbt_daemon.ld_session_list); 1128 smb_session_timers(&sv->sv_tcp_daemon.ld_session_list); 1129 } 1130 } 1131 1132 /* 1133 * smb_server_kstat_init 1134 */ 1135 static int 1136 smb_server_kstat_init(smb_server_t *sv) 1137 { 1138 (void) snprintf(sv->sv_ksp_name, sizeof (sv->sv_ksp_name), "%s%d", 1139 SMBSRV_KSTAT_NAME, sv->sv_zid); 1140 1141 sv->sv_ksp = kstat_create(SMBSRV_KSTAT_MODULE, 0, sv->sv_ksp_name, 1142 SMBSRV_KSTAT_CLASS, KSTAT_TYPE_NAMED, 1143 sizeof (sv->sv_ks_data) / sizeof (kstat_named_t), 1144 KSTAT_FLAG_VIRTUAL); 1145 1146 if (sv->sv_ksp) { 1147 (void) strlcpy(sv->sv_ks_data.open_files.name, "open_files", 1148 sizeof (sv->sv_ks_data.open_files.name)); 1149 sv->sv_ks_data.open_files.data_type = KSTAT_DATA_UINT32; 1150 (void) strlcpy(sv->sv_ks_data.open_trees.name, "connections", 1151 sizeof (sv->sv_ks_data.open_trees.name)); 1152 sv->sv_ks_data.open_trees.data_type = KSTAT_DATA_UINT32; 1153 (void) strlcpy(sv->sv_ks_data.open_users.name, "sessions", 1154 sizeof (sv->sv_ks_data.open_users.name)); 1155 sv->sv_ks_data.open_users.data_type = KSTAT_DATA_UINT32; 1156 1157 mutex_init(&sv->sv_ksp_mutex, NULL, MUTEX_DEFAULT, NULL); 1158 sv->sv_ksp->ks_lock = &sv->sv_ksp_mutex; 1159 sv->sv_ksp->ks_data = (void *)&sv->sv_ks_data; 1160 sv->sv_ksp->ks_update = smb_server_kstat_update_info; 1161 kstat_install(sv->sv_ksp); 1162 } 1163 1164 /* create and initialize smb kstats - smb_dispatch stats */ 1165 smb_dispatch_kstat_init(); 1166 1167 return (0); 1168 } 1169 1170 /* 1171 * smb_server_kstat_fini 1172 */ 1173 static void 1174 smb_server_kstat_fini(smb_server_t *sv) 1175 { 1176 if (sv->sv_ksp) { 1177 kstat_delete(sv->sv_ksp); 1178 mutex_destroy(&sv->sv_ksp_mutex); 1179 sv->sv_ksp = NULL; 1180 } 1181 smb_dispatch_kstat_fini(); 1182 } 1183 1184 /* ARGSUSED */ 1185 static int 1186 smb_server_kstat_update_info(kstat_t *ksp, int rw) 1187 { 1188 smb_server_t *sv; 1189 1190 if (rw == KSTAT_WRITE) { 1191 return (EACCES); 1192 } else { 1193 ASSERT(MUTEX_HELD(ksp->ks_lock)); 1194 1195 _NOTE(LINTED("pointer cast may result in improper alignment")) 1196 sv = (smb_server_t *)((uint8_t *)(ksp->ks_data) - 1197 offsetof(smb_server_t, sv_ks_data)); 1198 1199 ASSERT(sv->sv_magic == SMB_SERVER_MAGIC); 1200 1201 sv->sv_ks_data.open_files.value.ui32 = sv->sv_open_files; 1202 sv->sv_ks_data.open_trees.value.ui32 = sv->sv_open_trees; 1203 sv->sv_ks_data.open_users.value.ui32 = sv->sv_open_users; 1204 } 1205 return (0); 1206 } 1207 1208 /* 1209 * smb_server_stop 1210 * 1211 * The mutex of the server must have been entered before calling this function. 1212 */ 1213 static void 1214 smb_server_stop(smb_server_t *sv) 1215 { 1216 ASSERT(sv->sv_magic == SMB_SERVER_MAGIC); 1217 1218 smb_opipe_door_close(); 1219 smb_thread_stop(&sv->si_thread_timers); 1220 smb_thread_stop(&sv->si_thread_unexport); 1221 smb_kdoor_clnt_close(); 1222 smb_kshare_fini(sv->sv_lmshrd); 1223 sv->sv_lmshrd = NULL; 1224 smb_server_fsop_stop(sv); 1225 1226 if (sv->sv_session) { 1227 smb_session_delete(sv->sv_session); 1228 sv->sv_session = NULL; 1229 } 1230 1231 if (sv->sv_thread_pool) { 1232 taskq_destroy(sv->sv_thread_pool); 1233 sv->sv_thread_pool = NULL; 1234 } 1235 } 1236 1237 static int 1238 smb_server_listen( 1239 smb_server_t *sv, 1240 smb_listener_daemon_t *ld, 1241 in_port_t port, 1242 int pthread_create_error) 1243 { 1244 int rc; 1245 struct sonode *s_so; 1246 uint32_t on = 1; 1247 smb_session_t *session; 1248 1249 if (pthread_create_error) { 1250 /* 1251 * Delete the last session created. The user space thread 1252 * creation failed. 1253 */ 1254 smb_session_list_delete_tail(&ld->ld_session_list); 1255 } 1256 1257 if (ld->ld_so == NULL) { 1258 /* First time listener */ 1259 ld->ld_sin.sin_family = AF_INET; 1260 ld->ld_sin.sin_port = htons(port); 1261 ld->ld_sin.sin_addr.s_addr = htonl(INADDR_ANY); 1262 ld->ld_so = smb_socreate(AF_INET, SOCK_STREAM, 0); 1263 1264 if (ld->ld_so) { 1265 1266 (void) sosetsockopt(ld->ld_so, SOL_SOCKET, 1267 SO_REUSEADDR, (const void *)&on, sizeof (on)); 1268 1269 rc = sobind(ld->ld_so, (struct sockaddr *)&ld->ld_sin, 1270 sizeof (ld->ld_sin), 0, 0); 1271 1272 if (rc == 0) { 1273 rc = solisten(ld->ld_so, 20); 1274 if (rc < 0) { 1275 cmn_err(CE_WARN, 1276 "Port %d: listen 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: bind failed", port); 1285 smb_soshutdown(ld->ld_so); 1286 smb_sodestroy(ld->ld_so); 1287 ld->ld_so = NULL; 1288 return (rc); 1289 } 1290 } else { 1291 cmn_err(CE_WARN, 1292 "Port %d: socket create failed", port); 1293 return (ENOMEM); 1294 } 1295 } 1296 1297 DTRACE_PROBE1(so__wait__accept, struct sonode *, ld->ld_so); 1298 1299 for (;;) { 1300 rc = soaccept(ld->ld_so, 0, &s_so); 1301 if (rc == 0) { 1302 uint32_t txbuf_size = 128*1024; 1303 uint32_t on = 1; 1304 1305 DTRACE_PROBE1(so__accept, struct sonode *, s_so); 1306 1307 (void) sosetsockopt(s_so, IPPROTO_TCP, TCP_NODELAY, 1308 (const void *)&on, sizeof (on)); 1309 (void) sosetsockopt(s_so, SOL_SOCKET, SO_KEEPALIVE, 1310 (const void *)&on, sizeof (on)); 1311 (void) sosetsockopt(s_so, SOL_SOCKET, SO_SNDBUF, 1312 (const void *)&txbuf_size, sizeof (txbuf_size)); 1313 /* 1314 * Create a session for this connection. 1315 */ 1316 session = smb_session_create(s_so, port, sv); 1317 if (session) { 1318 smb_session_list_append(&ld->ld_session_list, 1319 session); 1320 break; 1321 } else { 1322 smb_soshutdown(s_so); 1323 smb_sodestroy(s_so); 1324 } 1325 continue; 1326 } 1327 smb_session_list_signal(&ld->ld_session_list); 1328 smb_soshutdown(ld->ld_so); 1329 smb_sodestroy(ld->ld_so); 1330 ld->ld_so = NULL; 1331 break; 1332 } 1333 1334 return (rc); 1335 } 1336 1337 /* 1338 * smb_server_lookup 1339 * 1340 * This function tries to find the server associated with the zone of the 1341 * caller. 1342 */ 1343 static int 1344 smb_server_lookup(smb_server_t **psv) 1345 { 1346 zoneid_t zid; 1347 smb_server_t *sv; 1348 1349 zid = getzoneid(); 1350 1351 smb_llist_enter(&smb_servers, RW_READER); 1352 sv = smb_llist_head(&smb_servers); 1353 while (sv) { 1354 ASSERT(sv->sv_magic == SMB_SERVER_MAGIC); 1355 if (sv->sv_zid == zid) { 1356 mutex_enter(&sv->sv_mutex); 1357 if (sv->sv_state != SMB_SERVER_STATE_DELETING) { 1358 sv->sv_refcnt++; 1359 mutex_exit(&sv->sv_mutex); 1360 smb_llist_exit(&smb_servers); 1361 *psv = sv; 1362 return (0); 1363 } 1364 mutex_exit(&sv->sv_mutex); 1365 break; 1366 } 1367 sv = smb_llist_next(&smb_servers, sv); 1368 } 1369 smb_llist_exit(&smb_servers); 1370 return (EPERM); 1371 } 1372 1373 /* 1374 * smb_server_release 1375 * 1376 * This function decrements the reference count of the server and signals its 1377 * condition variable if the state of the server is SMB_SERVER_STATE_DELETING. 1378 */ 1379 static void 1380 smb_server_release(smb_server_t *sv) 1381 { 1382 ASSERT(sv->sv_magic == SMB_SERVER_MAGIC); 1383 1384 mutex_enter(&sv->sv_mutex); 1385 ASSERT(sv->sv_refcnt); 1386 sv->sv_refcnt--; 1387 if ((sv->sv_refcnt == 0) && (sv->sv_state == SMB_SERVER_STATE_DELETING)) 1388 cv_signal(&sv->sv_cv); 1389 mutex_exit(&sv->sv_mutex); 1390 } 1391 1392 static int 1393 smb_server_ulist_geti( 1394 smb_session_list_t *se, 1395 int offset, 1396 smb_opipe_context_t *ctx, 1397 int max_cnt) 1398 { 1399 smb_session_t *sn = NULL; 1400 smb_user_t *user; 1401 smb_llist_t *ulist; 1402 int cnt = 0, skip = 0; 1403 1404 rw_enter(&se->se_lock, RW_READER); 1405 sn = list_head(&se->se_act.lst); 1406 while (sn && (cnt < max_cnt)) { 1407 ASSERT(sn->s_magic == SMB_SESSION_MAGIC); 1408 ulist = &sn->s_user_list; 1409 smb_llist_enter(ulist, RW_READER); 1410 user = smb_llist_head(ulist); 1411 while (user && (cnt < max_cnt)) { 1412 ASSERT(user->u_magic == SMB_USER_MAGIC); 1413 mutex_enter(&user->u_mutex); 1414 if (user->u_state == SMB_USER_STATE_LOGGED_IN) { 1415 if (skip++ < offset) { 1416 mutex_exit(&user->u_mutex); 1417 user = smb_llist_next(ulist, user); 1418 continue; 1419 } 1420 1421 smb_user_context_init(user, ctx); 1422 ctx++; 1423 cnt++; 1424 } 1425 mutex_exit(&user->u_mutex); 1426 user = smb_llist_next(ulist, user); 1427 } 1428 smb_llist_exit(ulist); 1429 } 1430 rw_exit(&se->se_lock); 1431 return (cnt); 1432 } 1433 1434 static void 1435 smb_server_store_cfg(smb_server_t *sv, smb_kmod_cfg_t *cfg) 1436 { 1437 if (cfg->skc_maxconnections == 0) 1438 cfg->skc_maxconnections = 0xFFFFFFFF; 1439 1440 smb_session_correct_keep_alive_values( 1441 &sv->sv_nbt_daemon.ld_session_list, cfg->skc_keepalive); 1442 smb_session_correct_keep_alive_values( 1443 &sv->sv_tcp_daemon.ld_session_list, cfg->skc_keepalive); 1444 1445 bcopy(cfg, &sv->sv_cfg, sizeof (sv->sv_cfg)); 1446 } 1447 1448 static int 1449 smb_server_fsop_start(smb_server_t *sv) 1450 { 1451 int error; 1452 1453 error = smb_node_root_init(rootdir, sv, &sv->si_root_smb_node); 1454 if (error != 0) 1455 sv->si_root_smb_node = NULL; 1456 1457 return (error); 1458 } 1459 1460 static void 1461 smb_server_fsop_stop(smb_server_t *sv) 1462 { 1463 if (sv->si_root_smb_node != NULL) { 1464 smb_vfs_rele_all(sv); 1465 smb_node_release(sv->si_root_smb_node); 1466 sv->si_root_smb_node = NULL; 1467 } 1468 } 1469