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