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