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