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