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 (c) 2008, 2010, Oracle and/or its affiliates. All rights reserved. 23 * Copyright 2015 Nexenta Systems, Inc. All rights reserved. 24 * Copyright (c) 2017 by Delphix. All rights reserved. 25 */ 26 27 /* 28 * General Structures Layout 29 * ------------------------- 30 * 31 * This is a simplified diagram showing the relationship between most of the 32 * main structures. 33 * 34 * +-------------------+ 35 * | SMB_SERVER | 36 * +-------------------+ 37 * | 38 * | 39 * v 40 * +-------------------+ +-------------------+ +-------------------+ 41 * | SESSION |<----->| SESSION |......| SESSION | 42 * +-------------------+ +-------------------+ +-------------------+ 43 * | 44 * | 45 * v 46 * +-------------------+ +-------------------+ +-------------------+ 47 * | USER |<----->| USER |......| USER | 48 * +-------------------+ +-------------------+ +-------------------+ 49 * | 50 * | 51 * v 52 * +-------------------+ +-------------------+ +-------------------+ 53 * | TREE |<----->| TREE |......| TREE | 54 * +-------------------+ +-------------------+ +-------------------+ 55 * | | 56 * | | 57 * | v 58 * | +-------+ +-------+ +-------+ 59 * | | OFILE |<----->| OFILE |......| OFILE | 60 * | +-------+ +-------+ +-------+ 61 * | 62 * | 63 * v 64 * +-------+ +------+ +------+ 65 * | ODIR |<----->| ODIR |......| ODIR | 66 * +-------+ +------+ +------+ 67 * 68 * 69 * Module Interface Overview 70 * ------------------------- 71 * 72 * 73 * +===================================+ 74 * | smbd daemon | 75 * +===================================+ 76 * | | ^ 77 * | | | 78 * User | | | 79 * -----------|--------------|----------------|-------------------------------- 80 * Kernel | | | 81 * | | | 82 * | | | 83 * +=========|==============|================|=================+ 84 * | v v | | 85 * | +-----------+ +--------------------+ +------------------+ | 86 * | | IO | | Kernel Door Server | | User Door Servers| | 87 * | | Interface | | Interface | | Interface | | 88 * | +-----------+ +--------------------+ +------------------+ | 89 * | | | ^ ^ | 90 * | v v | | | +=========+ 91 * | +-----------------------------------+ | | | | 92 * | + SMB Server Management (this file) |<------------------| ZFS | 93 * | +-----------------------------------+ | | | | 94 * | | | | Module | 95 * | +-----------------------------------+ | | | | 96 * | + SMB Server Internal Layers |------+ | +=========+ 97 * | +-----------------------------------+ | 98 * | | 99 * | | 100 * +===========================================================+ 101 * 102 * 103 * Server State Machine 104 * -------------------- 105 * | 106 * | T0 107 * | 108 * v 109 * +-----------------------------+ 110 * | SMB_SERVER_STATE_CREATED | 111 * +-----------------------------+ 112 * | 113 * | T1 114 * | 115 * v 116 * +-----------------------------+ 117 * | SMB_SERVER_STATE_CONFIGURED | 118 * +-----------------------------+ 119 * | 120 * | T2 121 * | 122 * v 123 * +-----------------------------+ 124 * | SMB_SERVER_STATE_RUNNING / | 125 * | SMB_SERVER_STATE_STOPPING | 126 * +-----------------------------+ 127 * | 128 * | T3 129 * | 130 * v 131 * +-----------------------------+ 132 * | SMB_SERVER_STATE_DELETING | 133 * +-----------------------------+ 134 * | 135 * | 136 * | 137 * v 138 * 139 * States 140 * ------ 141 * 142 * SMB_SERVER_STATE_CREATED 143 * 144 * This is the state of the server just after creation. 145 * 146 * SMB_SERVER_STATE_CONFIGURED 147 * 148 * The server has been configured. 149 * 150 * SMB_SERVER_STATE_RUNNING 151 * 152 * The server has been started. While in this state the threads listening on 153 * the sockets are started. 154 * 155 * When a client establishes a connection the thread listening dispatches 156 * a task with the new session as an argument. If the dispatch fails the new 157 * session context is destroyed. 158 * 159 * SMB_SERVER_STATE_STOPPING 160 * 161 * The threads listening on the NBT and TCP sockets are being terminated. 162 * 163 * 164 * Transitions 165 * ----------- 166 * 167 * Transition T0 168 * 169 * The daemon smbd triggers its creation by opening the smbsrv device. If 170 * the zone where the daemon lives doesn't have an smb server yet it is 171 * created. 172 * 173 * smb_drv_open() --> smb_server_create() 174 * 175 * Transition T1 176 * 177 * This transition occurs in smb_server_configure(). It is triggered by the 178 * daemon through an Ioctl. 179 * 180 * smb_drv_ioctl(SMB_IOC_CONFIG) --> smb_server_configure() 181 * 182 * Transition T2 183 * 184 * This transition occurs in smb_server_start(). It is triggered by the 185 * daemon through an Ioctl. 186 * 187 * smb_drv_ioctl(SMB_IOC_START) --> smb_server_start() 188 * 189 * Transition T3 190 * 191 * This transition occurs in smb_server_delete(). It is triggered by the 192 * daemon when closing the smbsrv device 193 * 194 * smb_drv_close() --> smb_server_delete() 195 * 196 * Comments 197 * -------- 198 * 199 * This files assumes that there will one SMB server per zone. For now the 200 * smb server works only in global zone. There's nothing in this file preventing 201 * an smb server from being created in a non global zone. That limitation is 202 * enforced in user space. 203 */ 204 205 #include <sys/cmn_err.h> 206 #include <sys/priv.h> 207 #include <sys/zone.h> 208 #include <netinet/in.h> 209 #include <netinet/in_systm.h> 210 #include <netinet/ip.h> 211 #include <netinet/ip_icmp.h> 212 #include <netinet/ip_var.h> 213 #include <netinet/tcp.h> 214 #include <smbsrv/smb2_kproto.h> 215 #include <smbsrv/string.h> 216 #include <smbsrv/netbios.h> 217 #include <smbsrv/smb_fsops.h> 218 #include <smbsrv/smb_share.h> 219 #include <smbsrv/smb_door.h> 220 #include <smbsrv/smb_kstat.h> 221 222 typedef struct { 223 smb_listener_daemon_t *ra_listener; 224 smb_session_t *ra_session; 225 } smb_receiver_arg_t; 226 227 static void smb_server_kstat_init(smb_server_t *); 228 static void smb_server_kstat_fini(smb_server_t *); 229 static void smb_server_timers(smb_thread_t *, void *); 230 static void smb_server_store_cfg(smb_server_t *, smb_ioc_cfg_t *); 231 static void smb_server_shutdown(smb_server_t *); 232 static int smb_server_fsop_start(smb_server_t *); 233 static void smb_server_fsop_stop(smb_server_t *); 234 static void smb_event_cancel(smb_server_t *, uint32_t); 235 static uint32_t smb_event_alloc_txid(void); 236 237 static void smb_server_disconnect_share(smb_llist_t *, const char *); 238 static void smb_server_enum_users(smb_llist_t *, smb_svcenum_t *); 239 static void smb_server_enum_trees(smb_llist_t *, smb_svcenum_t *); 240 static int smb_server_session_disconnect(smb_llist_t *, const char *, 241 const char *); 242 static int smb_server_fclose(smb_llist_t *, uint32_t); 243 static int smb_server_kstat_update(kstat_t *, int); 244 static int smb_server_legacy_kstat_update(kstat_t *, int); 245 static void smb_server_listener_init(smb_server_t *, smb_listener_daemon_t *, 246 char *, in_port_t, int); 247 static void smb_server_listener_destroy(smb_listener_daemon_t *); 248 static int smb_server_listener_start(smb_listener_daemon_t *); 249 static void smb_server_listener_stop(smb_listener_daemon_t *); 250 static void smb_server_listener(smb_thread_t *, void *); 251 static void smb_server_receiver(void *); 252 static void smb_server_create_session(smb_listener_daemon_t *, ksocket_t); 253 static void smb_server_destroy_session(smb_listener_daemon_t *, 254 smb_session_t *); 255 static uint16_t smb_spool_get_fid(smb_server_t *); 256 static boolean_t smb_spool_lookup_doc_byfid(smb_server_t *, uint16_t, 257 smb_kspooldoc_t *); 258 259 int smb_event_debug = 0; 260 261 static smb_llist_t smb_servers; 262 263 kmem_cache_t *smb_cache_request; 264 kmem_cache_t *smb_cache_session; 265 kmem_cache_t *smb_cache_user; 266 kmem_cache_t *smb_cache_tree; 267 kmem_cache_t *smb_cache_ofile; 268 kmem_cache_t *smb_cache_odir; 269 kmem_cache_t *smb_cache_opipe; 270 kmem_cache_t *smb_cache_event; 271 kmem_cache_t *smb_cache_lock; 272 273 /* 274 * ***************************************************************************** 275 * **************** Functions called from the device interface ***************** 276 * ***************************************************************************** 277 * 278 * These functions typically have to determine the relevant smb server 279 * to which the call applies. 280 */ 281 282 /* 283 * How many zones have an SMB server active? 284 */ 285 int 286 smb_server_get_count(void) 287 { 288 return (smb_llist_get_count(&smb_servers)); 289 } 290 291 /* 292 * smb_server_g_init 293 * 294 * This function must be called from smb_drv_attach(). 295 */ 296 int 297 smb_server_g_init(void) 298 { 299 int rc; 300 301 if ((rc = smb_vop_init()) != 0) 302 goto errout; 303 if ((rc = smb_fem_init()) != 0) 304 goto errout; 305 306 smb_kshare_g_init(); 307 smb_codepage_init(); 308 smb_mbc_init(); /* smb_mbc_cache */ 309 smb_node_init(); /* smb_node_cache, lists */ 310 311 smb_cache_request = kmem_cache_create("smb_request_cache", 312 sizeof (smb_request_t), 8, NULL, NULL, NULL, NULL, NULL, 0); 313 smb_cache_session = kmem_cache_create("smb_session_cache", 314 sizeof (smb_session_t), 8, NULL, NULL, NULL, NULL, NULL, 0); 315 smb_cache_user = kmem_cache_create("smb_user_cache", 316 sizeof (smb_user_t), 8, NULL, NULL, NULL, NULL, NULL, 0); 317 smb_cache_tree = kmem_cache_create("smb_tree_cache", 318 sizeof (smb_tree_t), 8, NULL, NULL, NULL, NULL, NULL, 0); 319 smb_cache_ofile = kmem_cache_create("smb_ofile_cache", 320 sizeof (smb_ofile_t), 8, NULL, NULL, NULL, NULL, NULL, 0); 321 smb_cache_odir = kmem_cache_create("smb_odir_cache", 322 sizeof (smb_odir_t), 8, NULL, NULL, NULL, NULL, NULL, 0); 323 smb_cache_opipe = kmem_cache_create("smb_opipe_cache", 324 sizeof (smb_opipe_t), 8, NULL, NULL, NULL, NULL, NULL, 0); 325 smb_cache_event = kmem_cache_create("smb_event_cache", 326 sizeof (smb_event_t), 8, NULL, NULL, NULL, NULL, NULL, 0); 327 smb_cache_lock = kmem_cache_create("smb_lock_cache", 328 sizeof (smb_lock_t), 8, NULL, NULL, NULL, NULL, NULL, 0); 329 330 smb_llist_init(); 331 smb_llist_constructor(&smb_servers, sizeof (smb_server_t), 332 offsetof(smb_server_t, sv_lnd)); 333 334 return (0); 335 336 errout: 337 smb_fem_fini(); 338 smb_vop_fini(); 339 return (rc); 340 } 341 342 /* 343 * smb_server_g_fini 344 * 345 * This function must called from smb_drv_detach(). It will fail if servers 346 * still exist. 347 */ 348 void 349 smb_server_g_fini(void) 350 { 351 352 ASSERT(smb_llist_get_count(&smb_servers) == 0); 353 354 smb_llist_fini(); 355 356 kmem_cache_destroy(smb_cache_request); 357 kmem_cache_destroy(smb_cache_session); 358 kmem_cache_destroy(smb_cache_user); 359 kmem_cache_destroy(smb_cache_tree); 360 kmem_cache_destroy(smb_cache_ofile); 361 kmem_cache_destroy(smb_cache_odir); 362 kmem_cache_destroy(smb_cache_opipe); 363 kmem_cache_destroy(smb_cache_event); 364 kmem_cache_destroy(smb_cache_lock); 365 366 smb_node_fini(); 367 smb_mbc_fini(); 368 smb_codepage_fini(); 369 smb_kshare_g_fini(); 370 371 smb_fem_fini(); 372 smb_vop_fini(); 373 374 smb_llist_destructor(&smb_servers); 375 } 376 377 /* 378 * smb_server_create 379 * 380 * This function will fail if there's already a server associated with the 381 * caller's zone. 382 */ 383 int 384 smb_server_create(void) 385 { 386 zoneid_t zid; 387 smb_server_t *sv; 388 389 zid = getzoneid(); 390 391 smb_llist_enter(&smb_servers, RW_WRITER); 392 sv = smb_llist_head(&smb_servers); 393 while (sv) { 394 SMB_SERVER_VALID(sv); 395 if (sv->sv_zid == zid) { 396 smb_llist_exit(&smb_servers); 397 return (EPERM); 398 } 399 sv = smb_llist_next(&smb_servers, sv); 400 } 401 402 sv = kmem_zalloc(sizeof (smb_server_t), KM_SLEEP); 403 404 sv->sv_magic = SMB_SERVER_MAGIC; 405 sv->sv_state = SMB_SERVER_STATE_CREATED; 406 sv->sv_zid = zid; 407 sv->sv_pid = ddi_get_pid(); 408 409 mutex_init(&sv->sv_mutex, NULL, MUTEX_DEFAULT, NULL); 410 cv_init(&sv->sv_cv, NULL, CV_DEFAULT, NULL); 411 cv_init(&sv->sp_info.sp_cv, NULL, CV_DEFAULT, NULL); 412 413 smb_llist_constructor(&sv->sv_event_list, sizeof (smb_event_t), 414 offsetof(smb_event_t, se_lnd)); 415 416 smb_llist_constructor(&sv->sp_info.sp_list, sizeof (smb_kspooldoc_t), 417 offsetof(smb_kspooldoc_t, sd_lnd)); 418 419 smb_llist_constructor(&sv->sp_info.sp_fidlist, 420 sizeof (smb_spoolfid_t), offsetof(smb_spoolfid_t, sf_lnd)); 421 422 sv->sv_disp_stats1 = kmem_zalloc(SMB_COM_NUM * 423 sizeof (smb_disp_stats_t), KM_SLEEP); 424 425 sv->sv_disp_stats2 = kmem_zalloc(SMB2__NCMDS * 426 sizeof (smb_disp_stats_t), KM_SLEEP); 427 428 smb_thread_init(&sv->si_thread_timers, "smb_timers", 429 smb_server_timers, sv, smbsrv_timer_pri); 430 431 smb_srqueue_init(&sv->sv_srqueue); 432 433 smb_kdoor_init(sv); 434 smb_kshare_init(sv); 435 smb_server_kstat_init(sv); 436 437 smb_threshold_init(&sv->sv_ssetup_ct, SMB_SSETUP_CMD, 438 smb_ssetup_threshold, smb_ssetup_timeout); 439 smb_threshold_init(&sv->sv_tcon_ct, SMB_TCON_CMD, 440 smb_tcon_threshold, smb_tcon_timeout); 441 smb_threshold_init(&sv->sv_opipe_ct, SMB_OPIPE_CMD, 442 smb_opipe_threshold, smb_opipe_timeout); 443 444 smb_llist_insert_tail(&smb_servers, sv); 445 smb_llist_exit(&smb_servers); 446 447 return (0); 448 } 449 450 /* 451 * smb_server_delete 452 * 453 * This function will delete the server passed in. It will make sure that all 454 * activity associated that server has ceased before destroying it. 455 */ 456 int 457 smb_server_delete(void) 458 { 459 smb_server_t *sv; 460 int rc; 461 462 rc = smb_server_lookup(&sv); 463 if (rc != 0) 464 return (rc); 465 466 mutex_enter(&sv->sv_mutex); 467 switch (sv->sv_state) { 468 case SMB_SERVER_STATE_RUNNING: 469 sv->sv_state = SMB_SERVER_STATE_STOPPING; 470 mutex_exit(&sv->sv_mutex); 471 smb_server_shutdown(sv); 472 mutex_enter(&sv->sv_mutex); 473 cv_broadcast(&sv->sp_info.sp_cv); 474 sv->sv_state = SMB_SERVER_STATE_DELETING; 475 break; 476 case SMB_SERVER_STATE_STOPPING: 477 sv->sv_state = SMB_SERVER_STATE_DELETING; 478 break; 479 case SMB_SERVER_STATE_CONFIGURED: 480 case SMB_SERVER_STATE_CREATED: 481 sv->sv_state = SMB_SERVER_STATE_DELETING; 482 break; 483 default: 484 SMB_SERVER_STATE_VALID(sv->sv_state); 485 mutex_exit(&sv->sv_mutex); 486 smb_server_release(sv); 487 return (ENOTTY); 488 } 489 490 ASSERT(sv->sv_state == SMB_SERVER_STATE_DELETING); 491 492 sv->sv_refcnt--; 493 while (sv->sv_refcnt) 494 cv_wait(&sv->sv_cv, &sv->sv_mutex); 495 496 mutex_exit(&sv->sv_mutex); 497 498 smb_llist_enter(&smb_servers, RW_WRITER); 499 smb_llist_remove(&smb_servers, sv); 500 smb_llist_exit(&smb_servers); 501 502 smb_threshold_fini(&sv->sv_ssetup_ct); 503 smb_threshold_fini(&sv->sv_tcon_ct); 504 smb_threshold_fini(&sv->sv_opipe_ct); 505 506 smb_server_listener_destroy(&sv->sv_nbt_daemon); 507 smb_server_listener_destroy(&sv->sv_tcp_daemon); 508 rw_destroy(&sv->sv_cfg_lock); 509 smb_server_kstat_fini(sv); 510 smb_kshare_fini(sv); 511 smb_kdoor_fini(sv); 512 smb_llist_destructor(&sv->sv_event_list); 513 514 kmem_free(sv->sv_disp_stats1, 515 SMB_COM_NUM * sizeof (smb_disp_stats_t)); 516 517 kmem_free(sv->sv_disp_stats2, 518 SMB2__NCMDS * sizeof (smb_disp_stats_t)); 519 520 smb_srqueue_destroy(&sv->sv_srqueue); 521 smb_thread_destroy(&sv->si_thread_timers); 522 523 mutex_destroy(&sv->sv_mutex); 524 cv_destroy(&sv->sv_cv); 525 sv->sv_magic = 0; 526 kmem_free(sv, sizeof (smb_server_t)); 527 528 return (0); 529 } 530 531 /* 532 * smb_server_configure 533 */ 534 int 535 smb_server_configure(smb_ioc_cfg_t *ioc) 536 { 537 int rc = 0; 538 smb_server_t *sv; 539 540 /* 541 * Reality check negotiation token length vs. #define'd maximum. 542 */ 543 if (ioc->negtok_len > SMB_PI_MAX_NEGTOK) 544 return (EINVAL); 545 546 rc = smb_server_lookup(&sv); 547 if (rc) 548 return (rc); 549 550 mutex_enter(&sv->sv_mutex); 551 switch (sv->sv_state) { 552 case SMB_SERVER_STATE_CREATED: 553 smb_server_store_cfg(sv, ioc); 554 sv->sv_state = SMB_SERVER_STATE_CONFIGURED; 555 break; 556 557 case SMB_SERVER_STATE_CONFIGURED: 558 smb_server_store_cfg(sv, ioc); 559 break; 560 561 case SMB_SERVER_STATE_RUNNING: 562 case SMB_SERVER_STATE_STOPPING: 563 rw_enter(&sv->sv_cfg_lock, RW_WRITER); 564 smb_server_store_cfg(sv, ioc); 565 rw_exit(&sv->sv_cfg_lock); 566 break; 567 568 default: 569 SMB_SERVER_STATE_VALID(sv->sv_state); 570 rc = EFAULT; 571 break; 572 } 573 mutex_exit(&sv->sv_mutex); 574 575 smb_server_release(sv); 576 577 return (rc); 578 } 579 580 /* 581 * smb_server_start 582 */ 583 int 584 smb_server_start(smb_ioc_start_t *ioc) 585 { 586 int rc = 0; 587 int family; 588 smb_server_t *sv; 589 590 rc = smb_server_lookup(&sv); 591 if (rc) 592 return (rc); 593 594 mutex_enter(&sv->sv_mutex); 595 switch (sv->sv_state) { 596 case SMB_SERVER_STATE_CONFIGURED: 597 598 if ((rc = smb_server_fsop_start(sv)) != 0) 599 break; 600 601 if ((rc = smb_kshare_start(sv)) != 0) 602 break; 603 604 /* 605 * NB: the proc passed here has to be a "system" one. 606 * Normally that's p0, or the NGZ eqivalent. 607 */ 608 sv->sv_worker_pool = taskq_create_proc("smb_workers", 609 sv->sv_cfg.skc_maxworkers, smbsrv_worker_pri, 610 sv->sv_cfg.skc_maxworkers, INT_MAX, 611 curzone->zone_zsched, TASKQ_DYNAMIC); 612 613 sv->sv_receiver_pool = taskq_create_proc("smb_receivers", 614 sv->sv_cfg.skc_maxconnections, smbsrv_receive_pri, 615 sv->sv_cfg.skc_maxconnections, INT_MAX, 616 curzone->zone_zsched, TASKQ_DYNAMIC); 617 618 sv->sv_session = smb_session_create(NULL, 0, sv, 0); 619 620 if (sv->sv_worker_pool == NULL || sv->sv_session == NULL) { 621 rc = ENOMEM; 622 break; 623 } 624 625 #ifdef _KERNEL 626 ASSERT(sv->sv_lmshrd == NULL); 627 sv->sv_lmshrd = smb_kshare_door_init(ioc->lmshrd); 628 if (sv->sv_lmshrd == NULL) 629 break; 630 if ((rc = smb_kdoor_open(sv, ioc->udoor)) != 0) { 631 cmn_err(CE_WARN, "Cannot open smbd door"); 632 break; 633 } 634 #else /* _KERNEL */ 635 /* Fake kernel does not use the kshare_door */ 636 fksmb_kdoor_open(sv, ioc->udoor_func); 637 #endif /* _KERNEL */ 638 639 if ((rc = smb_thread_start(&sv->si_thread_timers)) != 0) 640 break; 641 642 family = AF_INET; 643 smb_server_listener_init(sv, &sv->sv_nbt_daemon, 644 "smb_nbt_listener", IPPORT_NETBIOS_SSN, family); 645 if (sv->sv_cfg.skc_ipv6_enable) 646 family = AF_INET6; 647 smb_server_listener_init(sv, &sv->sv_tcp_daemon, 648 "smb_tcp_listener", IPPORT_SMB, family); 649 rc = smb_server_listener_start(&sv->sv_tcp_daemon); 650 if (rc != 0) 651 break; 652 if (sv->sv_cfg.skc_netbios_enable) 653 (void) smb_server_listener_start(&sv->sv_nbt_daemon); 654 655 sv->sv_state = SMB_SERVER_STATE_RUNNING; 656 sv->sv_start_time = gethrtime(); 657 mutex_exit(&sv->sv_mutex); 658 smb_server_release(sv); 659 smb_export_start(sv); 660 return (0); 661 default: 662 SMB_SERVER_STATE_VALID(sv->sv_state); 663 mutex_exit(&sv->sv_mutex); 664 smb_server_release(sv); 665 return (ENOTTY); 666 } 667 668 mutex_exit(&sv->sv_mutex); 669 smb_server_shutdown(sv); 670 smb_server_release(sv); 671 return (rc); 672 } 673 674 /* 675 * An smbd is shutting down. 676 */ 677 int 678 smb_server_stop(void) 679 { 680 smb_server_t *sv; 681 int rc; 682 683 if ((rc = smb_server_lookup(&sv)) != 0) 684 return (rc); 685 686 mutex_enter(&sv->sv_mutex); 687 switch (sv->sv_state) { 688 case SMB_SERVER_STATE_RUNNING: 689 sv->sv_state = SMB_SERVER_STATE_STOPPING; 690 mutex_exit(&sv->sv_mutex); 691 smb_server_shutdown(sv); 692 mutex_enter(&sv->sv_mutex); 693 cv_broadcast(&sv->sp_info.sp_cv); 694 break; 695 default: 696 SMB_SERVER_STATE_VALID(sv->sv_state); 697 break; 698 } 699 mutex_exit(&sv->sv_mutex); 700 701 smb_server_release(sv); 702 return (0); 703 } 704 705 boolean_t 706 smb_server_is_stopping(smb_server_t *sv) 707 { 708 boolean_t status; 709 710 SMB_SERVER_VALID(sv); 711 712 mutex_enter(&sv->sv_mutex); 713 714 switch (sv->sv_state) { 715 case SMB_SERVER_STATE_STOPPING: 716 case SMB_SERVER_STATE_DELETING: 717 status = B_TRUE; 718 break; 719 default: 720 status = B_FALSE; 721 break; 722 } 723 724 mutex_exit(&sv->sv_mutex); 725 return (status); 726 } 727 728 void 729 smb_server_cancel_event(smb_server_t *sv, uint32_t txid) 730 { 731 smb_event_cancel(sv, txid); 732 } 733 734 int 735 smb_server_notify_event(smb_ioc_event_t *ioc) 736 { 737 smb_server_t *sv; 738 int rc; 739 740 if ((rc = smb_server_lookup(&sv)) == 0) { 741 smb_event_notify(sv, ioc->txid); 742 smb_server_release(sv); 743 } 744 745 return (rc); 746 } 747 748 /* 749 * smb_server_spooldoc 750 * 751 * Waits for print file close broadcast. 752 * Gets the head of the fid list, 753 * then searches the spooldoc list and returns 754 * this info via the ioctl to user land. 755 * 756 * rc - 0 success 757 */ 758 759 int 760 smb_server_spooldoc(smb_ioc_spooldoc_t *ioc) 761 { 762 smb_server_t *sv; 763 int rc; 764 smb_kspooldoc_t *spdoc; 765 uint16_t fid; 766 767 if ((rc = smb_server_lookup(&sv)) != 0) 768 return (rc); 769 770 if (sv->sv_cfg.skc_print_enable == 0) { 771 rc = ENOTTY; 772 goto out; 773 } 774 775 mutex_enter(&sv->sv_mutex); 776 for (;;) { 777 if (sv->sv_state != SMB_SERVER_STATE_RUNNING) { 778 rc = ECANCELED; 779 break; 780 } 781 if ((fid = smb_spool_get_fid(sv)) != 0) { 782 rc = 0; 783 break; 784 } 785 if (cv_wait_sig(&sv->sp_info.sp_cv, &sv->sv_mutex) == 0) { 786 rc = EINTR; 787 break; 788 } 789 } 790 mutex_exit(&sv->sv_mutex); 791 if (rc != 0) 792 goto out; 793 794 spdoc = kmem_zalloc(sizeof (*spdoc), KM_SLEEP); 795 if (smb_spool_lookup_doc_byfid(sv, fid, spdoc)) { 796 ioc->spool_num = spdoc->sd_spool_num; 797 ioc->ipaddr = spdoc->sd_ipaddr; 798 (void) strlcpy(ioc->path, spdoc->sd_path, 799 MAXPATHLEN); 800 (void) strlcpy(ioc->username, 801 spdoc->sd_username, MAXNAMELEN); 802 } else { 803 /* Did not find that print job. */ 804 rc = EAGAIN; 805 } 806 kmem_free(spdoc, sizeof (*spdoc)); 807 808 out: 809 smb_server_release(sv); 810 return (rc); 811 } 812 813 int 814 smb_server_set_gmtoff(smb_ioc_gmt_t *ioc) 815 { 816 int rc; 817 smb_server_t *sv; 818 819 if ((rc = smb_server_lookup(&sv)) == 0) { 820 sv->si_gmtoff = ioc->offset; 821 smb_server_release(sv); 822 } 823 824 return (rc); 825 } 826 827 int 828 smb_server_numopen(smb_ioc_opennum_t *ioc) 829 { 830 smb_server_t *sv; 831 int rc; 832 833 if ((rc = smb_server_lookup(&sv)) == 0) { 834 ioc->open_users = sv->sv_users; 835 ioc->open_trees = sv->sv_trees; 836 ioc->open_files = sv->sv_files + sv->sv_pipes; 837 smb_server_release(sv); 838 } 839 return (rc); 840 } 841 842 /* 843 * Enumerate objects within the server. The svcenum provides the 844 * enumeration context, i.e. what the caller want to get back. 845 */ 846 int 847 smb_server_enum(smb_ioc_svcenum_t *ioc) 848 { 849 smb_svcenum_t *svcenum = &ioc->svcenum; 850 smb_server_t *sv; 851 int rc; 852 853 /* 854 * Reality check that the buffer-length insize the enum doesn't 855 * overrun the ioctl's total length. 856 */ 857 if (svcenum->se_buflen + sizeof (*ioc) > ioc->hdr.len) 858 return (EINVAL); 859 860 if ((rc = smb_server_lookup(&sv)) != 0) 861 return (rc); 862 863 svcenum->se_bavail = svcenum->se_buflen; 864 svcenum->se_bused = 0; 865 svcenum->se_nitems = 0; 866 867 switch (svcenum->se_type) { 868 case SMB_SVCENUM_TYPE_USER: 869 smb_server_enum_users(&sv->sv_nbt_daemon.ld_session_list, 870 svcenum); 871 smb_server_enum_users(&sv->sv_tcp_daemon.ld_session_list, 872 svcenum); 873 break; 874 case SMB_SVCENUM_TYPE_TREE: 875 case SMB_SVCENUM_TYPE_FILE: 876 smb_server_enum_trees(&sv->sv_nbt_daemon.ld_session_list, 877 svcenum); 878 smb_server_enum_trees(&sv->sv_tcp_daemon.ld_session_list, 879 svcenum); 880 break; 881 default: 882 rc = EINVAL; 883 } 884 885 smb_server_release(sv); 886 return (rc); 887 } 888 889 /* 890 * Look for sessions to disconnect by client and user name. 891 */ 892 int 893 smb_server_session_close(smb_ioc_session_t *ioc) 894 { 895 smb_llist_t *ll; 896 smb_server_t *sv; 897 int nbt_cnt; 898 int tcp_cnt; 899 int rc; 900 901 if ((rc = smb_server_lookup(&sv)) != 0) 902 return (rc); 903 904 ll = &sv->sv_nbt_daemon.ld_session_list; 905 nbt_cnt = smb_server_session_disconnect(ll, ioc->client, ioc->username); 906 907 ll = &sv->sv_tcp_daemon.ld_session_list; 908 tcp_cnt = smb_server_session_disconnect(ll, ioc->client, ioc->username); 909 910 smb_server_release(sv); 911 912 if ((nbt_cnt == 0) && (tcp_cnt == 0)) 913 return (ENOENT); 914 return (0); 915 } 916 917 /* 918 * Close a file by uniqid. 919 */ 920 int 921 smb_server_file_close(smb_ioc_fileid_t *ioc) 922 { 923 uint32_t uniqid = ioc->uniqid; 924 smb_llist_t *ll; 925 smb_server_t *sv; 926 int rc; 927 928 if ((rc = smb_server_lookup(&sv)) != 0) 929 return (rc); 930 931 ll = &sv->sv_nbt_daemon.ld_session_list; 932 rc = smb_server_fclose(ll, uniqid); 933 934 if (rc == ENOENT) { 935 ll = &sv->sv_tcp_daemon.ld_session_list; 936 rc = smb_server_fclose(ll, uniqid); 937 } 938 939 smb_server_release(sv); 940 return (rc); 941 } 942 943 /* 944 * These functions determine the relevant smb server to which the call apply. 945 */ 946 947 uint32_t 948 smb_server_get_session_count(smb_server_t *sv) 949 { 950 uint32_t counter = 0; 951 952 counter = smb_llist_get_count(&sv->sv_nbt_daemon.ld_session_list); 953 counter += smb_llist_get_count(&sv->sv_tcp_daemon.ld_session_list); 954 955 return (counter); 956 } 957 958 /* 959 * Gets the vnode of the specified share path. 960 * 961 * A hold on the returned vnode pointer is taken so the caller 962 * must call VN_RELE. 963 */ 964 int 965 smb_server_sharevp(smb_server_t *sv, const char *shr_path, vnode_t **vp) 966 { 967 smb_request_t *sr; 968 smb_node_t *fnode = NULL; 969 smb_node_t *dnode; 970 char last_comp[MAXNAMELEN]; 971 int rc = 0; 972 973 ASSERT(shr_path); 974 975 mutex_enter(&sv->sv_mutex); 976 switch (sv->sv_state) { 977 case SMB_SERVER_STATE_RUNNING: 978 break; 979 default: 980 mutex_exit(&sv->sv_mutex); 981 return (ENOTACTIVE); 982 } 983 mutex_exit(&sv->sv_mutex); 984 985 if ((sr = smb_request_alloc(sv->sv_session, 0)) == NULL) { 986 return (ENOMEM); 987 } 988 sr->user_cr = zone_kcred(); 989 990 rc = smb_pathname_reduce(sr, sr->user_cr, shr_path, 991 NULL, NULL, &dnode, last_comp); 992 993 if (rc == 0) { 994 rc = smb_fsop_lookup(sr, sr->user_cr, SMB_FOLLOW_LINKS, 995 sv->si_root_smb_node, dnode, last_comp, &fnode); 996 smb_node_release(dnode); 997 } 998 999 smb_request_free(sr); 1000 1001 if (rc != 0) 1002 return (rc); 1003 1004 ASSERT(fnode->vp && fnode->vp->v_vfsp); 1005 1006 VN_HOLD(fnode->vp); 1007 *vp = fnode->vp; 1008 1009 smb_node_release(fnode); 1010 1011 return (0); 1012 } 1013 1014 #ifdef _KERNEL 1015 /* 1016 * This is a special interface that will be utilized by ZFS to cause a share to 1017 * be added/removed. 1018 * 1019 * arg is either a lmshare_info_t or share_name from userspace. 1020 * It will need to be copied into the kernel. It is lmshare_info_t 1021 * for add operations and share_name for delete operations. 1022 */ 1023 int 1024 smb_server_share(void *arg, boolean_t add_share) 1025 { 1026 smb_server_t *sv; 1027 int rc; 1028 1029 if ((rc = smb_server_lookup(&sv)) == 0) { 1030 mutex_enter(&sv->sv_mutex); 1031 switch (sv->sv_state) { 1032 case SMB_SERVER_STATE_RUNNING: 1033 mutex_exit(&sv->sv_mutex); 1034 (void) smb_kshare_upcall(sv->sv_lmshrd, arg, add_share); 1035 break; 1036 default: 1037 mutex_exit(&sv->sv_mutex); 1038 break; 1039 } 1040 smb_server_release(sv); 1041 } 1042 1043 return (rc); 1044 } 1045 #endif /* _KERNEL */ 1046 1047 int 1048 smb_server_unshare(const char *sharename) 1049 { 1050 smb_server_t *sv; 1051 smb_llist_t *ll; 1052 int rc; 1053 1054 if ((rc = smb_server_lookup(&sv))) 1055 return (rc); 1056 1057 mutex_enter(&sv->sv_mutex); 1058 switch (sv->sv_state) { 1059 case SMB_SERVER_STATE_RUNNING: 1060 case SMB_SERVER_STATE_STOPPING: 1061 break; 1062 default: 1063 mutex_exit(&sv->sv_mutex); 1064 smb_server_release(sv); 1065 return (ENOTACTIVE); 1066 } 1067 mutex_exit(&sv->sv_mutex); 1068 1069 ll = &sv->sv_nbt_daemon.ld_session_list; 1070 smb_server_disconnect_share(ll, sharename); 1071 1072 ll = &sv->sv_tcp_daemon.ld_session_list; 1073 smb_server_disconnect_share(ll, sharename); 1074 1075 smb_server_release(sv); 1076 return (0); 1077 } 1078 1079 /* 1080 * Disconnect the specified share. 1081 * Typically called when a share has been removed. 1082 */ 1083 static void 1084 smb_server_disconnect_share(smb_llist_t *ll, const char *sharename) 1085 { 1086 smb_session_t *session; 1087 1088 smb_llist_enter(ll, RW_READER); 1089 1090 session = smb_llist_head(ll); 1091 while (session) { 1092 SMB_SESSION_VALID(session); 1093 smb_rwx_rwenter(&session->s_lock, RW_READER); 1094 switch (session->s_state) { 1095 case SMB_SESSION_STATE_NEGOTIATED: 1096 smb_session_disconnect_share(session, sharename); 1097 break; 1098 default: 1099 break; 1100 } 1101 smb_rwx_rwexit(&session->s_lock); 1102 session = smb_llist_next(ll, session); 1103 } 1104 1105 smb_llist_exit(ll); 1106 } 1107 1108 /* 1109 * ***************************************************************************** 1110 * **************** Functions called from the internal layers ****************** 1111 * ***************************************************************************** 1112 * 1113 * These functions are provided the relevant smb server by the caller. 1114 */ 1115 1116 void 1117 smb_server_get_cfg(smb_server_t *sv, smb_kmod_cfg_t *cfg) 1118 { 1119 rw_enter(&sv->sv_cfg_lock, RW_READER); 1120 bcopy(&sv->sv_cfg, cfg, sizeof (*cfg)); 1121 rw_exit(&sv->sv_cfg_lock); 1122 } 1123 1124 /* 1125 * 1126 */ 1127 void 1128 smb_server_inc_nbt_sess(smb_server_t *sv) 1129 { 1130 SMB_SERVER_VALID(sv); 1131 atomic_inc_32(&sv->sv_nbt_sess); 1132 } 1133 1134 void 1135 smb_server_dec_nbt_sess(smb_server_t *sv) 1136 { 1137 SMB_SERVER_VALID(sv); 1138 atomic_dec_32(&sv->sv_nbt_sess); 1139 } 1140 1141 void 1142 smb_server_inc_tcp_sess(smb_server_t *sv) 1143 { 1144 SMB_SERVER_VALID(sv); 1145 atomic_inc_32(&sv->sv_tcp_sess); 1146 } 1147 1148 void 1149 smb_server_dec_tcp_sess(smb_server_t *sv) 1150 { 1151 SMB_SERVER_VALID(sv); 1152 atomic_dec_32(&sv->sv_tcp_sess); 1153 } 1154 1155 void 1156 smb_server_inc_users(smb_server_t *sv) 1157 { 1158 SMB_SERVER_VALID(sv); 1159 atomic_inc_32(&sv->sv_users); 1160 } 1161 1162 void 1163 smb_server_dec_users(smb_server_t *sv) 1164 { 1165 SMB_SERVER_VALID(sv); 1166 atomic_dec_32(&sv->sv_users); 1167 } 1168 1169 void 1170 smb_server_inc_trees(smb_server_t *sv) 1171 { 1172 SMB_SERVER_VALID(sv); 1173 atomic_inc_32(&sv->sv_trees); 1174 } 1175 1176 void 1177 smb_server_dec_trees(smb_server_t *sv) 1178 { 1179 SMB_SERVER_VALID(sv); 1180 atomic_dec_32(&sv->sv_trees); 1181 } 1182 1183 void 1184 smb_server_inc_files(smb_server_t *sv) 1185 { 1186 SMB_SERVER_VALID(sv); 1187 atomic_inc_32(&sv->sv_files); 1188 } 1189 1190 void 1191 smb_server_dec_files(smb_server_t *sv) 1192 { 1193 SMB_SERVER_VALID(sv); 1194 atomic_dec_32(&sv->sv_files); 1195 } 1196 1197 void 1198 smb_server_inc_pipes(smb_server_t *sv) 1199 { 1200 SMB_SERVER_VALID(sv); 1201 atomic_inc_32(&sv->sv_pipes); 1202 } 1203 1204 void 1205 smb_server_dec_pipes(smb_server_t *sv) 1206 { 1207 SMB_SERVER_VALID(sv); 1208 atomic_dec_32(&sv->sv_pipes); 1209 } 1210 1211 void 1212 smb_server_add_rxb(smb_server_t *sv, int64_t value) 1213 { 1214 SMB_SERVER_VALID(sv); 1215 atomic_add_64(&sv->sv_rxb, value); 1216 } 1217 1218 void 1219 smb_server_add_txb(smb_server_t *sv, int64_t value) 1220 { 1221 SMB_SERVER_VALID(sv); 1222 atomic_add_64(&sv->sv_txb, value); 1223 } 1224 1225 void 1226 smb_server_inc_req(smb_server_t *sv) 1227 { 1228 SMB_SERVER_VALID(sv); 1229 atomic_inc_64(&sv->sv_nreq); 1230 } 1231 1232 /* 1233 * ***************************************************************************** 1234 * *************************** Static Functions ******************************** 1235 * ***************************************************************************** 1236 */ 1237 1238 static void 1239 smb_server_timers(smb_thread_t *thread, void *arg) 1240 { 1241 smb_server_t *sv = (smb_server_t *)arg; 1242 1243 ASSERT(sv != NULL); 1244 1245 /* 1246 * This just kills old inactive sessions. No urgency. 1247 * The session code expects one call per minute. 1248 */ 1249 while (smb_thread_continue_timedwait(thread, 60 /* Seconds */)) { 1250 smb_session_timers(&sv->sv_nbt_daemon.ld_session_list); 1251 smb_session_timers(&sv->sv_tcp_daemon.ld_session_list); 1252 } 1253 } 1254 1255 /* 1256 * smb_server_kstat_init 1257 */ 1258 static void 1259 smb_server_kstat_init(smb_server_t *sv) 1260 { 1261 1262 sv->sv_ksp = kstat_create_zone(SMBSRV_KSTAT_MODULE, 0, 1263 SMBSRV_KSTAT_STATISTICS, SMBSRV_KSTAT_CLASS, KSTAT_TYPE_RAW, 1264 sizeof (smbsrv_kstats_t), 0, sv->sv_zid); 1265 1266 if (sv->sv_ksp != NULL) { 1267 sv->sv_ksp->ks_update = smb_server_kstat_update; 1268 sv->sv_ksp->ks_private = sv; 1269 ((smbsrv_kstats_t *)sv->sv_ksp->ks_data)->ks_start_time = 1270 sv->sv_start_time; 1271 smb_dispatch_stats_init(sv); 1272 smb2_dispatch_stats_init(sv); 1273 kstat_install(sv->sv_ksp); 1274 } else { 1275 cmn_err(CE_WARN, "SMB Server: Statistics unavailable"); 1276 } 1277 1278 sv->sv_legacy_ksp = kstat_create_zone(SMBSRV_KSTAT_MODULE, 0, 1279 SMBSRV_KSTAT_NAME, SMBSRV_KSTAT_CLASS, KSTAT_TYPE_NAMED, 1280 sizeof (smb_server_legacy_kstat_t) / sizeof (kstat_named_t), 1281 0, sv->sv_zid); 1282 1283 if (sv->sv_legacy_ksp != NULL) { 1284 smb_server_legacy_kstat_t *ksd; 1285 1286 ksd = sv->sv_legacy_ksp->ks_data; 1287 1288 (void) strlcpy(ksd->ls_files.name, "open_files", 1289 sizeof (ksd->ls_files.name)); 1290 ksd->ls_files.data_type = KSTAT_DATA_UINT32; 1291 1292 (void) strlcpy(ksd->ls_trees.name, "connections", 1293 sizeof (ksd->ls_trees.name)); 1294 ksd->ls_trees.data_type = KSTAT_DATA_UINT32; 1295 1296 (void) strlcpy(ksd->ls_users.name, "connections", 1297 sizeof (ksd->ls_users.name)); 1298 ksd->ls_users.data_type = KSTAT_DATA_UINT32; 1299 1300 mutex_init(&sv->sv_legacy_ksmtx, NULL, MUTEX_DEFAULT, NULL); 1301 sv->sv_legacy_ksp->ks_lock = &sv->sv_legacy_ksmtx; 1302 sv->sv_legacy_ksp->ks_update = smb_server_legacy_kstat_update; 1303 kstat_install(sv->sv_legacy_ksp); 1304 } 1305 } 1306 1307 /* 1308 * smb_server_kstat_fini 1309 */ 1310 static void 1311 smb_server_kstat_fini(smb_server_t *sv) 1312 { 1313 if (sv->sv_legacy_ksp != NULL) { 1314 kstat_delete(sv->sv_legacy_ksp); 1315 mutex_destroy(&sv->sv_legacy_ksmtx); 1316 sv->sv_legacy_ksp = NULL; 1317 } 1318 1319 if (sv->sv_ksp != NULL) { 1320 kstat_delete(sv->sv_ksp); 1321 sv->sv_ksp = NULL; 1322 smb_dispatch_stats_fini(sv); 1323 smb2_dispatch_stats_fini(sv); 1324 } 1325 } 1326 1327 /* 1328 * smb_server_kstat_update 1329 */ 1330 static int 1331 smb_server_kstat_update(kstat_t *ksp, int rw) 1332 { 1333 smb_server_t *sv; 1334 smbsrv_kstats_t *ksd; 1335 1336 if (rw == KSTAT_READ) { 1337 sv = ksp->ks_private; 1338 SMB_SERVER_VALID(sv); 1339 ksd = (smbsrv_kstats_t *)ksp->ks_data; 1340 /* 1341 * Counters 1342 */ 1343 ksd->ks_nbt_sess = sv->sv_nbt_sess; 1344 ksd->ks_tcp_sess = sv->sv_tcp_sess; 1345 ksd->ks_users = sv->sv_users; 1346 ksd->ks_trees = sv->sv_trees; 1347 ksd->ks_files = sv->sv_files; 1348 ksd->ks_pipes = sv->sv_pipes; 1349 /* 1350 * Throughput 1351 */ 1352 ksd->ks_txb = sv->sv_txb; 1353 ksd->ks_rxb = sv->sv_rxb; 1354 ksd->ks_nreq = sv->sv_nreq; 1355 /* 1356 * Busyness 1357 */ 1358 ksd->ks_maxreqs = sv->sv_cfg.skc_maxworkers; 1359 smb_srqueue_update(&sv->sv_srqueue, 1360 &ksd->ks_utilization); 1361 /* 1362 * Latency & Throughput of the requests 1363 */ 1364 smb_dispatch_stats_update(sv, ksd->ks_reqs1, 0, SMB_COM_NUM); 1365 smb2_dispatch_stats_update(sv, ksd->ks_reqs2, 0, SMB2__NCMDS); 1366 return (0); 1367 } 1368 if (rw == KSTAT_WRITE) 1369 return (EACCES); 1370 1371 return (EIO); 1372 } 1373 1374 static int 1375 smb_server_legacy_kstat_update(kstat_t *ksp, int rw) 1376 { 1377 smb_server_t *sv; 1378 smb_server_legacy_kstat_t *ksd; 1379 int rc; 1380 1381 switch (rw) { 1382 case KSTAT_WRITE: 1383 rc = EACCES; 1384 break; 1385 case KSTAT_READ: 1386 if (!smb_server_lookup(&sv)) { 1387 ASSERT(MUTEX_HELD(ksp->ks_lock)); 1388 ASSERT(sv->sv_legacy_ksp == ksp); 1389 ksd = (smb_server_legacy_kstat_t *)ksp->ks_data; 1390 ksd->ls_files.value.ui32 = sv->sv_files + sv->sv_pipes; 1391 ksd->ls_trees.value.ui32 = sv->sv_trees; 1392 ksd->ls_users.value.ui32 = sv->sv_users; 1393 smb_server_release(sv); 1394 rc = 0; 1395 break; 1396 } 1397 /* FALLTHROUGH */ 1398 default: 1399 rc = EIO; 1400 break; 1401 } 1402 return (rc); 1403 1404 } 1405 1406 /* 1407 * smb_server_shutdown 1408 */ 1409 static void 1410 smb_server_shutdown(smb_server_t *sv) 1411 { 1412 SMB_SERVER_VALID(sv); 1413 1414 /* 1415 * Stop the listeners first, so we don't get any more 1416 * new work while we're trying to shut down. 1417 * Also disconnects all sessions under each. 1418 */ 1419 smb_server_listener_stop(&sv->sv_nbt_daemon); 1420 smb_server_listener_stop(&sv->sv_tcp_daemon); 1421 smb_thread_stop(&sv->si_thread_timers); 1422 1423 /* 1424 * Wake up any threads we might have blocked. 1425 * Must precede kdoor_close etc. because those will 1426 * wait for such threads to get out. 1427 */ 1428 smb_event_cancel(sv, 0); 1429 smb_threshold_wake_all(&sv->sv_ssetup_ct); 1430 smb_threshold_wake_all(&sv->sv_tcon_ct); 1431 smb_threshold_wake_all(&sv->sv_opipe_ct); 1432 1433 smb_kdoor_close(sv); 1434 #ifdef _KERNEL 1435 smb_kshare_door_fini(sv->sv_lmshrd); 1436 #endif /* _KERNEL */ 1437 sv->sv_lmshrd = NULL; 1438 1439 smb_export_stop(sv); 1440 1441 if (sv->sv_session != NULL) { 1442 /* 1443 * smb_kshare_export may have a request on here. 1444 * Normal sessions do this in smb_session_cancel() 1445 * but this is a "fake" session used only for the 1446 * requests used by the kshare thread(s). 1447 */ 1448 smb_slist_wait_for_empty(&sv->sv_session->s_req_list); 1449 1450 smb_session_delete(sv->sv_session); 1451 sv->sv_session = NULL; 1452 } 1453 1454 if (sv->sv_receiver_pool != NULL) { 1455 taskq_destroy(sv->sv_receiver_pool); 1456 sv->sv_receiver_pool = NULL; 1457 } 1458 1459 if (sv->sv_worker_pool != NULL) { 1460 taskq_destroy(sv->sv_worker_pool); 1461 sv->sv_worker_pool = NULL; 1462 } 1463 1464 smb_kshare_stop(sv); 1465 smb_server_fsop_stop(sv); 1466 } 1467 1468 /* 1469 * smb_server_listener_init 1470 * 1471 * Initializes listener contexts. 1472 */ 1473 static void 1474 smb_server_listener_init( 1475 smb_server_t *sv, 1476 smb_listener_daemon_t *ld, 1477 char *name, 1478 in_port_t port, 1479 int family) 1480 { 1481 ASSERT(ld->ld_magic != SMB_LISTENER_MAGIC); 1482 1483 bzero(ld, sizeof (*ld)); 1484 1485 ld->ld_sv = sv; 1486 ld->ld_family = family; 1487 ld->ld_port = port; 1488 1489 if (family == AF_INET) { 1490 ld->ld_sin.sin_family = (uint32_t)family; 1491 ld->ld_sin.sin_port = htons(port); 1492 ld->ld_sin.sin_addr.s_addr = htonl(INADDR_ANY); 1493 } else { 1494 ld->ld_sin6.sin6_family = (uint32_t)family; 1495 ld->ld_sin6.sin6_port = htons(port); 1496 (void) memset(&ld->ld_sin6.sin6_addr.s6_addr, 0, 1497 sizeof (ld->ld_sin6.sin6_addr.s6_addr)); 1498 } 1499 1500 smb_llist_constructor(&ld->ld_session_list, sizeof (smb_session_t), 1501 offsetof(smb_session_t, s_lnd)); 1502 smb_thread_init(&ld->ld_thread, name, smb_server_listener, ld, 1503 smbsrv_listen_pri); 1504 ld->ld_magic = SMB_LISTENER_MAGIC; 1505 } 1506 1507 /* 1508 * smb_server_listener_destroy 1509 * 1510 * Destroyes listener contexts. 1511 */ 1512 static void 1513 smb_server_listener_destroy(smb_listener_daemon_t *ld) 1514 { 1515 /* 1516 * Note that if startup fails early, we can legitimately 1517 * get here with an all-zeros object. 1518 */ 1519 if (ld->ld_magic == 0) 1520 return; 1521 1522 SMB_LISTENER_VALID(ld); 1523 ASSERT(ld->ld_so == NULL); 1524 smb_thread_destroy(&ld->ld_thread); 1525 smb_llist_destructor(&ld->ld_session_list); 1526 ld->ld_magic = 0; 1527 } 1528 1529 /* 1530 * smb_server_listener_start 1531 * 1532 * Starts the listener associated with the context passed in. 1533 * 1534 * Return: 0 Success 1535 * not 0 Failure 1536 */ 1537 static int 1538 smb_server_listener_start(smb_listener_daemon_t *ld) 1539 { 1540 int rc; 1541 uint32_t on; 1542 uint32_t off; 1543 1544 SMB_LISTENER_VALID(ld); 1545 1546 if (ld->ld_so != NULL) 1547 return (EINVAL); 1548 1549 ld->ld_so = smb_socreate(ld->ld_family, SOCK_STREAM, 0); 1550 if (ld->ld_so == NULL) { 1551 cmn_err(CE_WARN, "port %d: socket create failed", ld->ld_port); 1552 return (ENOMEM); 1553 } 1554 1555 off = 0; 1556 (void) ksocket_setsockopt(ld->ld_so, SOL_SOCKET, 1557 SO_MAC_EXEMPT, &off, sizeof (off), CRED()); 1558 1559 on = 1; 1560 (void) ksocket_setsockopt(ld->ld_so, SOL_SOCKET, 1561 SO_REUSEADDR, &on, sizeof (on), CRED()); 1562 1563 if (ld->ld_family == AF_INET) { 1564 rc = ksocket_bind(ld->ld_so, 1565 (struct sockaddr *)&ld->ld_sin, 1566 sizeof (ld->ld_sin), CRED()); 1567 } else { 1568 rc = ksocket_bind(ld->ld_so, 1569 (struct sockaddr *)&ld->ld_sin6, 1570 sizeof (ld->ld_sin6), CRED()); 1571 } 1572 1573 if (rc != 0) { 1574 cmn_err(CE_WARN, "port %d: bind failed", ld->ld_port); 1575 return (rc); 1576 } 1577 1578 rc = ksocket_listen(ld->ld_so, 20, CRED()); 1579 if (rc < 0) { 1580 cmn_err(CE_WARN, "port %d: listen failed", ld->ld_port); 1581 return (rc); 1582 } 1583 1584 ksocket_hold(ld->ld_so); 1585 rc = smb_thread_start(&ld->ld_thread); 1586 if (rc != 0) { 1587 ksocket_rele(ld->ld_so); 1588 cmn_err(CE_WARN, "port %d: listener failed to start", 1589 ld->ld_port); 1590 return (rc); 1591 } 1592 return (0); 1593 } 1594 1595 /* 1596 * smb_server_listener_stop 1597 * 1598 * Stops the listener associated with the context passed in. 1599 */ 1600 static void 1601 smb_server_listener_stop(smb_listener_daemon_t *ld) 1602 { 1603 SMB_LISTENER_VALID(ld); 1604 1605 if (ld->ld_so != NULL) { 1606 smb_soshutdown(ld->ld_so); 1607 smb_sodestroy(ld->ld_so); 1608 smb_thread_stop(&ld->ld_thread); 1609 ld->ld_so = NULL; 1610 } 1611 } 1612 1613 /* 1614 * smb_server_listener 1615 * 1616 * Entry point of the listeners. 1617 */ 1618 static void 1619 smb_server_listener(smb_thread_t *thread, void *arg) 1620 { 1621 _NOTE(ARGUNUSED(thread)) 1622 smb_listener_daemon_t *ld; 1623 smb_session_t *session; 1624 ksocket_t s_so; 1625 int on; 1626 int txbuf_size; 1627 1628 ld = (smb_listener_daemon_t *)arg; 1629 1630 SMB_LISTENER_VALID(ld); 1631 1632 DTRACE_PROBE1(so__wait__accept, struct sonode *, ld->ld_so); 1633 1634 for (;;) { 1635 int ret = ksocket_accept(ld->ld_so, NULL, NULL, &s_so, CRED()); 1636 1637 switch (ret) { 1638 case 0: 1639 break; 1640 case ECONNABORTED: 1641 continue; 1642 case EINTR: 1643 case EBADF: /* libfakekernel */ 1644 goto out; 1645 default: 1646 cmn_err(CE_WARN, 1647 "smb_server_listener: ksocket_accept(%d)", 1648 ret); 1649 goto out; 1650 } 1651 1652 DTRACE_PROBE1(so__accept, struct sonode *, s_so); 1653 1654 on = 1; 1655 (void) ksocket_setsockopt(s_so, IPPROTO_TCP, TCP_NODELAY, 1656 &on, sizeof (on), CRED()); 1657 1658 on = 1; 1659 (void) ksocket_setsockopt(s_so, SOL_SOCKET, SO_KEEPALIVE, 1660 &on, sizeof (on), CRED()); 1661 1662 txbuf_size = 128*1024; 1663 (void) ksocket_setsockopt(s_so, SOL_SOCKET, SO_SNDBUF, 1664 (const void *)&txbuf_size, sizeof (txbuf_size), CRED()); 1665 1666 /* 1667 * Create a session for this connection. 1668 */ 1669 smb_server_create_session(ld, s_so); 1670 } 1671 out: 1672 /* Disconnect all the sessions this listener created. */ 1673 smb_llist_enter(&ld->ld_session_list, RW_READER); 1674 session = smb_llist_head(&ld->ld_session_list); 1675 while (session != NULL) { 1676 smb_session_disconnect(session); 1677 session = smb_llist_next(&ld->ld_session_list, session); 1678 } 1679 smb_llist_exit(&ld->ld_session_list); 1680 ksocket_rele(ld->ld_so); 1681 } 1682 1683 /* 1684 * smb_server_receiver 1685 * 1686 * Entry point of the receiver threads. 1687 */ 1688 static void 1689 smb_server_receiver(void *arg) 1690 { 1691 smb_listener_daemon_t *ld; 1692 smb_session_t *session; 1693 1694 ld = ((smb_receiver_arg_t *)arg)->ra_listener; 1695 session = ((smb_receiver_arg_t *)arg)->ra_session; 1696 smb_mem_free(arg); 1697 smb_session_receiver(session); 1698 smb_server_destroy_session(ld, session); 1699 } 1700 1701 /* 1702 * smb_server_lookup 1703 * 1704 * This function finds the server associated with the zone of the 1705 * caller. Note: requires a fix in the dynamic taskq code: 1706 * 1501 taskq_create_proc ... TQ_DYNAMIC puts tasks in p0 1707 */ 1708 int 1709 smb_server_lookup(smb_server_t **psv) 1710 { 1711 zoneid_t zid; 1712 smb_server_t *sv; 1713 1714 zid = getzoneid(); 1715 1716 smb_llist_enter(&smb_servers, RW_READER); 1717 sv = smb_llist_head(&smb_servers); 1718 while (sv) { 1719 SMB_SERVER_VALID(sv); 1720 if (sv->sv_zid == zid) { 1721 mutex_enter(&sv->sv_mutex); 1722 if (sv->sv_state != SMB_SERVER_STATE_DELETING) { 1723 sv->sv_refcnt++; 1724 mutex_exit(&sv->sv_mutex); 1725 smb_llist_exit(&smb_servers); 1726 *psv = sv; 1727 return (0); 1728 } 1729 mutex_exit(&sv->sv_mutex); 1730 break; 1731 } 1732 sv = smb_llist_next(&smb_servers, sv); 1733 } 1734 smb_llist_exit(&smb_servers); 1735 return (EPERM); 1736 } 1737 1738 /* 1739 * smb_server_release 1740 * 1741 * This function decrements the reference count of the server and signals its 1742 * condition variable if the state of the server is SMB_SERVER_STATE_DELETING. 1743 */ 1744 void 1745 smb_server_release(smb_server_t *sv) 1746 { 1747 SMB_SERVER_VALID(sv); 1748 1749 mutex_enter(&sv->sv_mutex); 1750 ASSERT(sv->sv_refcnt); 1751 sv->sv_refcnt--; 1752 if ((sv->sv_refcnt == 0) && (sv->sv_state == SMB_SERVER_STATE_DELETING)) 1753 cv_signal(&sv->sv_cv); 1754 mutex_exit(&sv->sv_mutex); 1755 } 1756 1757 /* 1758 * Enumerate the users associated with a session list. 1759 */ 1760 static void 1761 smb_server_enum_users(smb_llist_t *ll, smb_svcenum_t *svcenum) 1762 { 1763 smb_session_t *sn; 1764 smb_llist_t *ulist; 1765 smb_user_t *user; 1766 int rc = 0; 1767 1768 smb_llist_enter(ll, RW_READER); 1769 sn = smb_llist_head(ll); 1770 1771 while (sn != NULL) { 1772 SMB_SESSION_VALID(sn); 1773 ulist = &sn->s_user_list; 1774 smb_llist_enter(ulist, RW_READER); 1775 user = smb_llist_head(ulist); 1776 1777 while (user != NULL) { 1778 if (smb_user_hold(user)) { 1779 rc = smb_user_enum(user, svcenum); 1780 smb_user_release(user); 1781 if (rc != 0) 1782 break; 1783 } 1784 1785 user = smb_llist_next(ulist, user); 1786 } 1787 1788 smb_llist_exit(ulist); 1789 1790 if (rc != 0) 1791 break; 1792 1793 sn = smb_llist_next(ll, sn); 1794 } 1795 1796 smb_llist_exit(ll); 1797 } 1798 1799 /* 1800 * Enumerate the trees/files associated with a session list. 1801 */ 1802 static void 1803 smb_server_enum_trees(smb_llist_t *ll, smb_svcenum_t *svcenum) 1804 { 1805 smb_session_t *sn; 1806 smb_llist_t *tlist; 1807 smb_tree_t *tree; 1808 int rc = 0; 1809 1810 smb_llist_enter(ll, RW_READER); 1811 sn = smb_llist_head(ll); 1812 1813 while (sn != NULL) { 1814 SMB_SESSION_VALID(sn); 1815 tlist = &sn->s_tree_list; 1816 smb_llist_enter(tlist, RW_READER); 1817 tree = smb_llist_head(tlist); 1818 1819 while (tree != NULL) { 1820 if (smb_tree_hold(tree)) { 1821 rc = smb_tree_enum(tree, svcenum); 1822 smb_tree_release(tree); 1823 if (rc != 0) 1824 break; 1825 } 1826 1827 tree = smb_llist_next(tlist, tree); 1828 } 1829 1830 smb_llist_exit(tlist); 1831 1832 if (rc != 0) 1833 break; 1834 1835 sn = smb_llist_next(ll, sn); 1836 } 1837 1838 smb_llist_exit(ll); 1839 } 1840 1841 /* 1842 * Disconnect sessions associated with the specified client and username. 1843 * Empty strings are treated as wildcards. 1844 */ 1845 static int 1846 smb_server_session_disconnect(smb_llist_t *ll, 1847 const char *client, const char *name) 1848 { 1849 smb_session_t *sn; 1850 smb_llist_t *ulist; 1851 smb_user_t *user; 1852 boolean_t match; 1853 int count = 0; 1854 1855 smb_llist_enter(ll, RW_READER); 1856 sn = smb_llist_head(ll); 1857 1858 while (sn != NULL) { 1859 SMB_SESSION_VALID(sn); 1860 1861 if ((*client != '\0') && (!smb_session_isclient(sn, client))) { 1862 sn = smb_llist_next(ll, sn); 1863 continue; 1864 } 1865 1866 ulist = &sn->s_user_list; 1867 smb_llist_enter(ulist, RW_READER); 1868 user = smb_llist_head(ulist); 1869 1870 while (user != NULL) { 1871 if (smb_user_hold(user)) { 1872 match = (*name == '\0'); 1873 if (!match) 1874 match = smb_user_namecmp(user, name); 1875 1876 if (match) { 1877 smb_llist_exit(ulist); 1878 smb_user_logoff(user); 1879 ++count; 1880 smb_user_release(user); 1881 smb_llist_enter(ulist, RW_READER); 1882 user = smb_llist_head(ulist); 1883 continue; 1884 } 1885 1886 smb_user_release(user); 1887 } 1888 1889 user = smb_llist_next(ulist, user); 1890 } 1891 1892 smb_llist_exit(ulist); 1893 sn = smb_llist_next(ll, sn); 1894 } 1895 1896 smb_llist_exit(ll); 1897 return (count); 1898 } 1899 1900 /* 1901 * Close a file by its unique id. 1902 */ 1903 static int 1904 smb_server_fclose(smb_llist_t *ll, uint32_t uniqid) 1905 { 1906 smb_session_t *sn; 1907 smb_llist_t *tlist; 1908 smb_tree_t *tree; 1909 int rc = ENOENT; 1910 1911 smb_llist_enter(ll, RW_READER); 1912 sn = smb_llist_head(ll); 1913 1914 while ((sn != NULL) && (rc == ENOENT)) { 1915 SMB_SESSION_VALID(sn); 1916 tlist = &sn->s_tree_list; 1917 smb_llist_enter(tlist, RW_READER); 1918 tree = smb_llist_head(tlist); 1919 1920 while ((tree != NULL) && (rc == ENOENT)) { 1921 if (smb_tree_hold(tree)) { 1922 rc = smb_tree_fclose(tree, uniqid); 1923 smb_tree_release(tree); 1924 } 1925 1926 tree = smb_llist_next(tlist, tree); 1927 } 1928 1929 smb_llist_exit(tlist); 1930 sn = smb_llist_next(ll, sn); 1931 } 1932 1933 smb_llist_exit(ll); 1934 return (rc); 1935 } 1936 1937 /* See also: libsmb smb_kmod_setcfg */ 1938 static void 1939 smb_server_store_cfg(smb_server_t *sv, smb_ioc_cfg_t *ioc) 1940 { 1941 if (ioc->maxconnections == 0) 1942 ioc->maxconnections = 0xFFFFFFFF; 1943 1944 smb_session_correct_keep_alive_values( 1945 &sv->sv_nbt_daemon.ld_session_list, ioc->keepalive); 1946 smb_session_correct_keep_alive_values( 1947 &sv->sv_tcp_daemon.ld_session_list, ioc->keepalive); 1948 1949 sv->sv_cfg.skc_maxworkers = ioc->maxworkers; 1950 sv->sv_cfg.skc_maxconnections = ioc->maxconnections; 1951 sv->sv_cfg.skc_keepalive = ioc->keepalive; 1952 sv->sv_cfg.skc_restrict_anon = ioc->restrict_anon; 1953 sv->sv_cfg.skc_signing_enable = ioc->signing_enable; 1954 sv->sv_cfg.skc_signing_required = ioc->signing_required; 1955 sv->sv_cfg.skc_oplock_enable = ioc->oplock_enable; 1956 sv->sv_cfg.skc_sync_enable = ioc->sync_enable; 1957 sv->sv_cfg.skc_secmode = ioc->secmode; 1958 sv->sv_cfg.skc_netbios_enable = ioc->netbios_enable; 1959 sv->sv_cfg.skc_ipv6_enable = ioc->ipv6_enable; 1960 sv->sv_cfg.skc_print_enable = ioc->print_enable; 1961 sv->sv_cfg.skc_traverse_mounts = ioc->traverse_mounts; 1962 sv->sv_cfg.skc_max_protocol = ioc->max_protocol; 1963 sv->sv_cfg.skc_execflags = ioc->exec_flags; 1964 sv->sv_cfg.skc_negtok_len = ioc->negtok_len; 1965 sv->sv_cfg.skc_version = ioc->version; 1966 sv->sv_cfg.skc_initial_credits = ioc->initial_credits; 1967 sv->sv_cfg.skc_maximum_credits = ioc->maximum_credits; 1968 1969 (void) memcpy(sv->sv_cfg.skc_machine_uuid, ioc->machine_uuid, 1970 sizeof (uuid_t)); 1971 (void) memcpy(sv->sv_cfg.skc_negtok, ioc->negtok, 1972 sizeof (sv->sv_cfg.skc_negtok)); 1973 (void) memcpy(sv->sv_cfg.skc_native_os, ioc->native_os, 1974 sizeof (sv->sv_cfg.skc_native_os)); 1975 (void) memcpy(sv->sv_cfg.skc_native_lm, ioc->native_lm, 1976 sizeof (sv->sv_cfg.skc_native_lm)); 1977 1978 (void) strlcpy(sv->sv_cfg.skc_nbdomain, ioc->nbdomain, 1979 sizeof (sv->sv_cfg.skc_nbdomain)); 1980 (void) strlcpy(sv->sv_cfg.skc_fqdn, ioc->fqdn, 1981 sizeof (sv->sv_cfg.skc_fqdn)); 1982 (void) strlcpy(sv->sv_cfg.skc_hostname, ioc->hostname, 1983 sizeof (sv->sv_cfg.skc_hostname)); 1984 (void) strlcpy(sv->sv_cfg.skc_system_comment, ioc->system_comment, 1985 sizeof (sv->sv_cfg.skc_system_comment)); 1986 } 1987 1988 static int 1989 smb_server_fsop_start(smb_server_t *sv) 1990 { 1991 int error; 1992 1993 error = smb_node_root_init(sv, &sv->si_root_smb_node); 1994 if (error != 0) 1995 sv->si_root_smb_node = NULL; 1996 1997 return (error); 1998 } 1999 2000 static void 2001 smb_server_fsop_stop(smb_server_t *sv) 2002 { 2003 if (sv->si_root_smb_node != NULL) { 2004 smb_node_release(sv->si_root_smb_node); 2005 sv->si_root_smb_node = NULL; 2006 } 2007 } 2008 2009 smb_event_t * 2010 smb_event_create(smb_server_t *sv, int timeout) 2011 { 2012 smb_event_t *event; 2013 2014 if (smb_server_is_stopping(sv)) 2015 return (NULL); 2016 2017 event = kmem_cache_alloc(smb_cache_event, KM_SLEEP); 2018 2019 bzero(event, sizeof (smb_event_t)); 2020 mutex_init(&event->se_mutex, NULL, MUTEX_DEFAULT, NULL); 2021 cv_init(&event->se_cv, NULL, CV_DEFAULT, NULL); 2022 event->se_magic = SMB_EVENT_MAGIC; 2023 event->se_txid = smb_event_alloc_txid(); 2024 event->se_server = sv; 2025 event->se_timeout = timeout; 2026 2027 smb_llist_enter(&sv->sv_event_list, RW_WRITER); 2028 smb_llist_insert_tail(&sv->sv_event_list, event); 2029 smb_llist_exit(&sv->sv_event_list); 2030 2031 return (event); 2032 } 2033 2034 void 2035 smb_event_destroy(smb_event_t *event) 2036 { 2037 smb_server_t *sv; 2038 2039 if (event == NULL) 2040 return; 2041 2042 SMB_EVENT_VALID(event); 2043 ASSERT(event->se_waittime == 0); 2044 sv = event->se_server; 2045 SMB_SERVER_VALID(sv); 2046 2047 smb_llist_enter(&sv->sv_event_list, RW_WRITER); 2048 smb_llist_remove(&sv->sv_event_list, event); 2049 smb_llist_exit(&sv->sv_event_list); 2050 2051 event->se_magic = (uint32_t)~SMB_EVENT_MAGIC; 2052 cv_destroy(&event->se_cv); 2053 mutex_destroy(&event->se_mutex); 2054 2055 kmem_cache_free(smb_cache_event, event); 2056 } 2057 2058 /* 2059 * Get the txid for the specified event. 2060 */ 2061 uint32_t 2062 smb_event_txid(smb_event_t *event) 2063 { 2064 if (event != NULL) { 2065 SMB_EVENT_VALID(event); 2066 return (event->se_txid); 2067 } 2068 2069 cmn_err(CE_NOTE, "smb_event_txid failed"); 2070 return ((uint32_t)-1); 2071 } 2072 2073 /* 2074 * Wait for event notification. 2075 */ 2076 int 2077 smb_event_wait(smb_event_t *event) 2078 { 2079 int seconds = 1; 2080 int ticks; 2081 int err; 2082 2083 if (event == NULL) 2084 return (EINVAL); 2085 2086 SMB_EVENT_VALID(event); 2087 2088 mutex_enter(&event->se_mutex); 2089 event->se_waittime = 1; 2090 event->se_errno = 0; 2091 2092 while (!(event->se_notified)) { 2093 if (smb_event_debug && ((event->se_waittime % 30) == 0)) 2094 cmn_err(CE_NOTE, "smb_event_wait[%d] (%d sec)", 2095 event->se_txid, event->se_waittime); 2096 2097 if (event->se_errno != 0) 2098 break; 2099 2100 if (event->se_waittime > event->se_timeout) { 2101 event->se_errno = ETIME; 2102 break; 2103 } 2104 2105 ticks = SEC_TO_TICK(seconds); 2106 (void) cv_reltimedwait(&event->se_cv, 2107 &event->se_mutex, (clock_t)ticks, TR_CLOCK_TICK); 2108 ++event->se_waittime; 2109 } 2110 2111 err = event->se_errno; 2112 event->se_waittime = 0; 2113 event->se_notified = B_FALSE; 2114 cv_signal(&event->se_cv); 2115 mutex_exit(&event->se_mutex); 2116 return (err); 2117 } 2118 2119 /* 2120 * If txid is non-zero, cancel the specified event. 2121 * Otherwise, cancel all events. 2122 */ 2123 static void 2124 smb_event_cancel(smb_server_t *sv, uint32_t txid) 2125 { 2126 smb_event_t *event; 2127 smb_llist_t *event_list; 2128 2129 SMB_SERVER_VALID(sv); 2130 2131 event_list = &sv->sv_event_list; 2132 smb_llist_enter(event_list, RW_WRITER); 2133 2134 event = smb_llist_head(event_list); 2135 while (event) { 2136 SMB_EVENT_VALID(event); 2137 2138 if (txid == 0 || event->se_txid == txid) { 2139 mutex_enter(&event->se_mutex); 2140 event->se_errno = ECANCELED; 2141 event->se_notified = B_TRUE; 2142 cv_signal(&event->se_cv); 2143 mutex_exit(&event->se_mutex); 2144 2145 if (txid != 0) 2146 break; 2147 } 2148 2149 event = smb_llist_next(event_list, event); 2150 } 2151 2152 smb_llist_exit(event_list); 2153 } 2154 2155 /* 2156 * If txid is non-zero, notify the specified event. 2157 * Otherwise, notify all events. 2158 */ 2159 void 2160 smb_event_notify(smb_server_t *sv, uint32_t txid) 2161 { 2162 smb_event_t *event; 2163 smb_llist_t *event_list; 2164 2165 SMB_SERVER_VALID(sv); 2166 2167 event_list = &sv->sv_event_list; 2168 smb_llist_enter(event_list, RW_READER); 2169 2170 event = smb_llist_head(event_list); 2171 while (event) { 2172 SMB_EVENT_VALID(event); 2173 2174 if (txid == 0 || event->se_txid == txid) { 2175 mutex_enter(&event->se_mutex); 2176 event->se_notified = B_TRUE; 2177 cv_signal(&event->se_cv); 2178 mutex_exit(&event->se_mutex); 2179 2180 if (txid != 0) 2181 break; 2182 } 2183 2184 event = smb_llist_next(event_list, event); 2185 } 2186 2187 smb_llist_exit(event_list); 2188 } 2189 2190 /* 2191 * Allocate a new transaction id (txid). 2192 * 2193 * 0 or -1 are not assigned because they are used to detect invalid 2194 * conditions or to indicate all open id's. 2195 */ 2196 static uint32_t 2197 smb_event_alloc_txid(void) 2198 { 2199 static kmutex_t txmutex; 2200 static uint32_t txid; 2201 uint32_t txid_ret; 2202 2203 mutex_enter(&txmutex); 2204 2205 if (txid == 0) 2206 txid = ddi_get_lbolt() << 11; 2207 2208 do { 2209 ++txid; 2210 } while (txid == 0 || txid == (uint32_t)-1); 2211 2212 txid_ret = txid; 2213 mutex_exit(&txmutex); 2214 2215 return (txid_ret); 2216 } 2217 2218 /* 2219 * Called by the ioctl to find the corresponding 2220 * spooldoc node. removes node on success 2221 * 2222 * Return values 2223 * rc 2224 * B_FALSE - not found 2225 * B_TRUE - found 2226 * 2227 */ 2228 2229 static boolean_t 2230 smb_spool_lookup_doc_byfid(smb_server_t *sv, uint16_t fid, 2231 smb_kspooldoc_t *spdoc) 2232 { 2233 smb_kspooldoc_t *sp; 2234 smb_llist_t *splist; 2235 2236 splist = &sv->sp_info.sp_list; 2237 smb_llist_enter(splist, RW_WRITER); 2238 sp = smb_llist_head(splist); 2239 while (sp != NULL) { 2240 /* 2241 * check for a matching fid 2242 */ 2243 if (sp->sd_fid == fid) { 2244 *spdoc = *sp; 2245 smb_llist_remove(splist, sp); 2246 smb_llist_exit(splist); 2247 kmem_free(sp, sizeof (smb_kspooldoc_t)); 2248 return (B_TRUE); 2249 } 2250 sp = smb_llist_next(splist, sp); 2251 } 2252 cmn_err(CE_WARN, "smb_spool_lookup_user_byfid: no fid:%d", fid); 2253 smb_llist_exit(splist); 2254 return (B_FALSE); 2255 } 2256 2257 /* 2258 * Adds the spool fid to a linked list to be used 2259 * as a search key in the spooldoc queue 2260 * 2261 * Return values 2262 * rc non-zero error 2263 * rc zero success 2264 * 2265 */ 2266 2267 void 2268 smb_spool_add_fid(smb_server_t *sv, uint16_t fid) 2269 { 2270 smb_llist_t *fidlist; 2271 smb_spoolfid_t *sf; 2272 2273 if (sv->sv_cfg.skc_print_enable == 0) 2274 return; 2275 2276 sf = kmem_zalloc(sizeof (smb_spoolfid_t), KM_SLEEP); 2277 fidlist = &sv->sp_info.sp_fidlist; 2278 smb_llist_enter(fidlist, RW_WRITER); 2279 sf->sf_fid = fid; 2280 smb_llist_insert_tail(fidlist, sf); 2281 smb_llist_exit(fidlist); 2282 cv_broadcast(&sv->sp_info.sp_cv); 2283 } 2284 2285 /* 2286 * Called by the ioctl to get and remove the head of the fid list 2287 * 2288 * Return values 2289 * int fd 2290 * greater than 0 success 2291 * 0 - error 2292 * 2293 */ 2294 2295 static uint16_t 2296 smb_spool_get_fid(smb_server_t *sv) 2297 { 2298 smb_spoolfid_t *spfid; 2299 smb_llist_t *splist; 2300 uint16_t fid; 2301 2302 splist = &sv->sp_info.sp_fidlist; 2303 smb_llist_enter(splist, RW_WRITER); 2304 spfid = smb_llist_head(splist); 2305 if (spfid != NULL) { 2306 fid = spfid->sf_fid; 2307 smb_llist_remove(&sv->sp_info.sp_fidlist, spfid); 2308 kmem_free(spfid, sizeof (smb_spoolfid_t)); 2309 } else { 2310 fid = 0; 2311 } 2312 smb_llist_exit(splist); 2313 return (fid); 2314 } 2315 2316 /* 2317 * Adds the spooldoc to the tail of the spooldoc list 2318 * 2319 * Return values 2320 * rc non-zero error 2321 * rc zero success 2322 */ 2323 int 2324 smb_spool_add_doc(smb_tree_t *tree, smb_kspooldoc_t *sp) 2325 { 2326 smb_llist_t *splist; 2327 smb_server_t *sv = tree->t_server; 2328 int rc = 0; 2329 2330 splist = &sv->sp_info.sp_list; 2331 smb_llist_enter(splist, RW_WRITER); 2332 sp->sd_spool_num = atomic_inc_32_nv(&sv->sp_info.sp_cnt); 2333 smb_llist_insert_tail(splist, sp); 2334 smb_llist_exit(splist); 2335 2336 return (rc); 2337 } 2338 2339 /* 2340 * smb_server_create_session 2341 */ 2342 static void 2343 smb_server_create_session(smb_listener_daemon_t *ld, ksocket_t s_so) 2344 { 2345 smb_session_t *session; 2346 smb_receiver_arg_t *rarg; 2347 taskqid_t tqid; 2348 2349 session = smb_session_create(s_so, ld->ld_port, ld->ld_sv, 2350 ld->ld_family); 2351 2352 if (session == NULL) { 2353 smb_soshutdown(s_so); 2354 smb_sodestroy(s_so); 2355 cmn_err(CE_WARN, "SMB Session: alloc failed"); 2356 return; 2357 } 2358 2359 smb_llist_enter(&ld->ld_session_list, RW_WRITER); 2360 smb_llist_insert_tail(&ld->ld_session_list, session); 2361 smb_llist_exit(&ld->ld_session_list); 2362 2363 rarg = (smb_receiver_arg_t *)smb_mem_alloc( 2364 sizeof (smb_receiver_arg_t)); 2365 rarg->ra_listener = ld; 2366 rarg->ra_session = session; 2367 2368 /* 2369 * These taskq entries must run independently of one another, 2370 * so TQ_NOQUEUE. TQ_SLEEP (==0) just for clarity. 2371 */ 2372 tqid = taskq_dispatch(ld->ld_sv->sv_receiver_pool, 2373 smb_server_receiver, rarg, TQ_NOQUEUE | TQ_SLEEP); 2374 if (tqid == TASKQID_INVALID) { 2375 smb_mem_free(rarg); 2376 smb_session_disconnect(session); 2377 smb_server_destroy_session(ld, session); 2378 cmn_err(CE_WARN, "SMB Session: taskq_dispatch failed"); 2379 return; 2380 } 2381 /* handy for debugging */ 2382 session->s_receiver_tqid = tqid; 2383 } 2384 2385 static void 2386 smb_server_destroy_session(smb_listener_daemon_t *ld, smb_session_t *session) 2387 { 2388 smb_llist_enter(&ld->ld_session_list, RW_WRITER); 2389 smb_llist_remove(&ld->ld_session_list, session); 2390 smb_llist_exit(&ld->ld_session_list); 2391 smb_session_delete(session); 2392 } 2393