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