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