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