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