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