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