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) 2007, 2010, Oracle and/or its affiliates. All rights reserved.
23 * Copyright 2019 Nexenta Systems, Inc.  All rights reserved.
24 */
25/*
26 * SMB Node State Machine
27 * ----------------------
28 *
29 *
30 *		    +----------- Creation/Allocation
31 *		    |
32 *		    | T0
33 *		    |
34 *		    v
35 *    +----------------------------+
36 *    |  SMB_NODE_STATE_AVAILABLE  |
37 *    +----------------------------+
38 *		    |
39 *		    | T1
40 *		    |
41 *		    v
42 *    +-----------------------------+
43 *    |  SMB_NODE_STATE_DESTROYING  |
44 *    +-----------------------------+
45 *		    |
46 *		    |
47 *		    | T2
48 *		    |
49 *		    +----------> Deletion/Free
50 *
51 * Transition T0
52 *
53 *    This transition occurs in smb_node_lookup(). If the node looked for is
54 *    not found in the has table a new node is created. The reference count is
55 *    initialized to 1 and the state initialized to SMB_NODE_STATE_AVAILABLE.
56 *
57 * Transition T1
58 *
59 *    This transition occurs in smb_node_release(). If the reference count
60 *    drops to zero the state is moved to SMB_NODE_STATE_DESTROYING and no more
61 *    reference count will be given out for that node.
62 *
63 * Transition T2
64 *
65 *    This transition occurs in smb_node_release(). The structure is deleted.
66 *
67 * Comments
68 * --------
69 *
70 *    The reason the smb node has 2 states is the following synchronization
71 *    rule:
72 *
73 *    There's a mutex embedded in the node used to protect its fields and
74 *    there's a lock embedded in the bucket of the hash table the node belongs
75 *    to. To increment or to decrement the reference count the mutex must be
76 *    entered. To insert the node into the bucket and to remove it from the
77 *    bucket the lock must be entered in RW_WRITER mode. When both (mutex and
78 *    lock) have to be entered, the lock has always to be entered first then
79 *    the mutex. This prevents a deadlock between smb_node_lookup() and
80 *    smb_node_release() from occurring. However, in smb_node_release() when the
81 *    reference count drops to zero and triggers the deletion of the node, the
82 *    mutex has to be released before entering the lock of the bucket (to
83 *    remove the node). This creates a window during which the node that is
84 *    about to be freed could be given out by smb_node_lookup(). To close that
85 *    window the node is moved to the state SMB_NODE_STATE_DESTROYING before
86 *    releasing the mutex. That way, even if smb_node_lookup() finds it, the
87 *    state will indicate that the node should be treated as non existent (of
88 *    course the state of the node should be tested/updated under the
89 *    protection of the mutex).
90 */
91#include <smbsrv/smb2_kproto.h>
92#include <smbsrv/smb_fsops.h>
93#include <smbsrv/smb_kstat.h>
94#include <sys/ddi.h>
95#include <sys/extdirent.h>
96#include <sys/pathname.h>
97#include <sys/sdt.h>
98#include <sys/nbmlock.h>
99#include <fs/fs_reparse.h>
100
101uint32_t smb_is_executable(char *);
102static void smb_node_create_audit_buf(smb_node_t *, int);
103static void smb_node_destroy_audit_buf(smb_node_t *);
104static void smb_node_audit(smb_node_t *);
105static smb_node_t *smb_node_alloc(char *, vnode_t *, smb_llist_t *, uint32_t);
106static void smb_node_free(smb_node_t *);
107static int smb_node_constructor(void *, void *, int);
108static void smb_node_destructor(void *, void *);
109static smb_llist_t *smb_node_get_hash(fsid_t *, smb_attr_t *, uint32_t *);
110
111static void smb_node_init_reparse(smb_node_t *, smb_attr_t *);
112static void smb_node_init_system(smb_node_t *);
113
114#define	VALIDATE_DIR_NODE(_dir_, _node_) \
115    ASSERT((_dir_)->n_magic == SMB_NODE_MAGIC); \
116    ASSERT(((_dir_)->vp->v_xattrdir) || ((_dir_)->vp->v_type == VDIR)); \
117    ASSERT((_dir_)->n_dnode != (_node_));
118
119/* round sz to DEV_BSIZE block */
120#define	SMB_ALLOCSZ(sz)	(((sz) + DEV_BSIZE-1) & ~(DEV_BSIZE-1))
121
122static kmem_cache_t	*smb_node_cache = NULL;
123static smb_llist_t	smb_node_hash_table[SMBND_HASH_MASK+1];
124static smb_node_t	*smb_root_node;
125
126/*
127 * smb_node_init
128 *
129 * Initialization of the SMB node layer.
130 *
131 * This function is not multi-thread safe. The caller must make sure only one
132 * thread makes the call.
133 */
134void
135smb_node_init(void)
136{
137	smb_attr_t	attr;
138	smb_llist_t	*node_hdr;
139	smb_node_t	*node;
140	uint32_t	hashkey;
141	int		i;
142
143	if (smb_node_cache != NULL)
144		return;
145
146	smb_node_cache = kmem_cache_create(SMBSRV_KSTAT_NODE_CACHE,
147	    sizeof (smb_node_t), 8, smb_node_constructor, smb_node_destructor,
148	    NULL, NULL, NULL, 0);
149
150	for (i = 0; i <= SMBND_HASH_MASK; i++) {
151		smb_llist_constructor(&smb_node_hash_table[i],
152		    sizeof (smb_node_t), offsetof(smb_node_t, n_lnd));
153	}
154
155	/*
156	 * The node cache is shared by all zones, so the smb_root_node
157	 * must represent the real (global zone) rootdir.
158	 * Note intentional use of kcred here.
159	 */
160	attr.sa_mask = SMB_AT_ALL;
161	VERIFY0(smb_vop_getattr(rootdir, NULL, &attr, 0, kcred));
162	node_hdr = smb_node_get_hash(&rootdir->v_vfsp->vfs_fsid, &attr,
163	    &hashkey);
164	node = smb_node_alloc("/", rootdir, node_hdr, hashkey);
165	smb_llist_enter(node_hdr, RW_WRITER);
166	smb_llist_insert_head(node_hdr, node);
167	smb_llist_exit(node_hdr);
168	smb_root_node = node;	/* smb_node_release in smb_node_fini */
169}
170
171/*
172 * smb_node_fini
173 *
174 * This function is not multi-thread safe. The caller must make sure only one
175 * thread makes the call.
176 */
177void
178smb_node_fini(void)
179{
180	int	i;
181
182	if (smb_root_node != NULL) {
183		smb_node_release(smb_root_node);
184		smb_root_node = NULL;
185	}
186
187	if (smb_node_cache == NULL)
188		return;
189
190#ifdef DEBUG
191	for (i = 0; i <= SMBND_HASH_MASK; i++) {
192		smb_llist_t	*bucket;
193		smb_node_t	*node;
194
195		/*
196		 * The following sequence is just intended for sanity check.
197		 * This will have to be modified when the code goes into
198		 * production.
199		 *
200		 * The SMB node hash table should be emtpy at this point. If the
201		 * hash table is not empty a panic will be triggered.
202		 *
203		 * The reason why SMB nodes are still remaining in the hash
204		 * table is problably due to a mismatch between calls to
205		 * smb_node_lookup() and smb_node_release(). You must track that
206		 * down.
207		 */
208		bucket = &smb_node_hash_table[i];
209		node = smb_llist_head(bucket);
210		while (node != NULL) {
211			cmn_err(CE_NOTE, "leaked node: 0x%p %s",
212			    (void *)node, node->od_name);
213			node = smb_llist_next(bucket, node);
214		}
215	}
216#endif
217
218	for (i = 0; i <= SMBND_HASH_MASK; i++) {
219		smb_llist_destructor(&smb_node_hash_table[i]);
220	}
221	kmem_cache_destroy(smb_node_cache);
222	smb_node_cache = NULL;
223}
224
225/*
226 * smb_node_lookup()
227 *
228 * NOTE: This routine should only be called by the file system interface layer,
229 * and not by SMB.
230 *
231 * smb_node_lookup() is called upon successful lookup, mkdir, and create
232 * (for both non-streams and streams).  In each of these cases, a held vnode is
233 * passed into this routine.  If a new smb_node is created it will take its
234 * own hold on the vnode.  The caller's hold therefore still belongs to, and
235 * should be released by, the caller.
236 *
237 * A reference is taken on the smb_node whether found in the hash table
238 * or newly created.
239 *
240 * If an smb_node needs to be created, a reference is also taken on the
241 * dnode (if passed in).
242 *
243 * See smb_node_release() for details on the release of these references.
244 */
245
246/*ARGSUSED*/
247smb_node_t *
248smb_node_lookup(
249    struct smb_request	*sr,
250    struct open_param	*op,
251    cred_t		*cred,
252    vnode_t		*vp,
253    char		*od_name,
254    smb_node_t		*dnode,
255    smb_node_t		*unode)
256{
257	smb_llist_t		*node_hdr;
258	smb_node_t		*node;
259	smb_attr_t		attr;
260	uint32_t		hashkey = 0;
261	fsid_t			fsid;
262	int			error;
263	krw_t			lock_mode;
264	vnode_t			*unnamed_vp = NULL;
265
266	/*
267	 * smb_vop_getattr() is called here instead of smb_fsop_getattr(),
268	 * because the node may not yet exist.  We also do not want to call
269	 * it with the list lock held.
270	 */
271
272	if (unode)
273		unnamed_vp = unode->vp;
274
275	/*
276	 * This getattr is performed on behalf of the server
277	 * that's why kcred is used not the user's cred
278	 */
279	attr.sa_mask = SMB_AT_ALL;
280	error = smb_vop_getattr(vp, unnamed_vp, &attr, 0, zone_kcred());
281	if (error)
282		return (NULL);
283
284	if (sr && sr->tid_tree) {
285		/*
286		 * The fsid for a file is that of the tree, even
287		 * if the file resides in a different mountpoint
288		 * under the share.
289		 */
290		fsid = SMB_TREE_FSID(sr->tid_tree);
291	} else {
292		/*
293		 * This should be getting executed only for the
294		 * tree root smb_node.
295		 */
296		fsid = vp->v_vfsp->vfs_fsid;
297	}
298
299	node_hdr = smb_node_get_hash(&fsid, &attr, &hashkey);
300	lock_mode = RW_READER;
301
302	smb_llist_enter(node_hdr, lock_mode);
303	for (;;) {
304		node = list_head(&node_hdr->ll_list);
305		while (node) {
306			ASSERT(node->n_magic == SMB_NODE_MAGIC);
307			ASSERT(node->n_hash_bucket == node_hdr);
308			if ((node->n_hashkey == hashkey) && (node->vp == vp)) {
309				mutex_enter(&node->n_mutex);
310				DTRACE_PROBE1(smb_node_lookup_hit,
311				    smb_node_t *, node);
312				switch (node->n_state) {
313				case SMB_NODE_STATE_AVAILABLE:
314					/* The node was found. */
315					node->n_refcnt++;
316					if ((node->n_dnode == NULL) &&
317					    (dnode != NULL) &&
318					    (node != dnode) &&
319					    (strcmp(od_name, "..") != 0) &&
320					    (strcmp(od_name, ".") != 0)) {
321						VALIDATE_DIR_NODE(dnode, node);
322						node->n_dnode = dnode;
323						smb_node_ref(dnode);
324					}
325
326					smb_node_audit(node);
327					mutex_exit(&node->n_mutex);
328					smb_llist_exit(node_hdr);
329					return (node);
330
331				case SMB_NODE_STATE_DESTROYING:
332					/*
333					 * Although the node exists it is about
334					 * to be destroyed. We act as it hasn't
335					 * been found.
336					 */
337					mutex_exit(&node->n_mutex);
338					break;
339				default:
340					/*
341					 * Although the node exists it is in an
342					 * unknown state. We act as it hasn't
343					 * been found.
344					 */
345					ASSERT(0);
346					mutex_exit(&node->n_mutex);
347					break;
348				}
349			}
350			node = smb_llist_next(node_hdr, node);
351		}
352		if ((lock_mode == RW_READER) && smb_llist_upgrade(node_hdr)) {
353			lock_mode = RW_WRITER;
354			continue;
355		}
356		break;
357	}
358	node = smb_node_alloc(od_name, vp, node_hdr, hashkey);
359	smb_node_init_reparse(node, &attr);
360
361	if (op)
362		node->flags |= smb_is_executable(op->fqi.fq_last_comp);
363
364	if (dnode) {
365		smb_node_ref(dnode);
366		node->n_dnode = dnode;
367		ASSERT(dnode->n_dnode != node);
368		ASSERT((dnode->vp->v_xattrdir) ||
369		    (dnode->vp->v_type == VDIR));
370	}
371
372	if (unode) {
373		smb_node_ref(unode);
374		node->n_unode = unode;
375	}
376
377	smb_node_init_system(node);
378
379	DTRACE_PROBE1(smb_node_lookup_miss, smb_node_t *, node);
380	smb_node_audit(node);
381	smb_llist_insert_head(node_hdr, node);
382	smb_llist_exit(node_hdr);
383	return (node);
384}
385
386/*
387 * smb_stream_node_lookup()
388 *
389 * Note: stream_name (the name that will be stored in the "od_name" field
390 * of a stream's smb_node) is the same as the on-disk name for the stream
391 * except that it does not have SMB_STREAM_PREFIX prepended.
392 */
393
394smb_node_t *
395smb_stream_node_lookup(smb_request_t *sr, cred_t *cr, smb_node_t *fnode,
396    vnode_t *xattrdirvp, vnode_t *vp, char *stream_name)
397{
398	smb_node_t	*xattrdir_node;
399	smb_node_t	*snode;
400
401	xattrdir_node = smb_node_lookup(sr, NULL, cr, xattrdirvp, XATTR_DIR,
402	    fnode, NULL);
403
404	if (xattrdir_node == NULL)
405		return (NULL);
406
407	snode = smb_node_lookup(sr, NULL, cr, vp, stream_name, xattrdir_node,
408	    fnode);
409
410	(void) smb_node_release(xattrdir_node);
411	return (snode);
412}
413
414
415/*
416 * This function should be called whenever a reference is needed on an
417 * smb_node pointer.  The copy of an smb_node pointer from one non-local
418 * data structure to another requires a reference to be taken on the smb_node
419 * (unless the usage is localized).  Each data structure deallocation routine
420 * will call smb_node_release() on its smb_node pointers.
421 *
422 * In general, an smb_node pointer residing in a structure should never be
423 * stale.  A node pointer may be NULL, however, and care should be taken
424 * prior to calling smb_node_ref(), which ASSERTs that the pointer is valid.
425 * Care also needs to be taken with respect to racing deallocations of a
426 * structure.
427 */
428void
429smb_node_ref(smb_node_t *node)
430{
431	SMB_NODE_VALID(node);
432
433	mutex_enter(&node->n_mutex);
434	switch (node->n_state) {
435	case SMB_NODE_STATE_AVAILABLE:
436		node->n_refcnt++;
437		ASSERT(node->n_refcnt);
438		DTRACE_PROBE1(smb_node_ref_exit, smb_node_t *, node);
439		smb_node_audit(node);
440		break;
441	default:
442		SMB_PANIC();
443	}
444	mutex_exit(&node->n_mutex);
445}
446
447/*
448 * smb_node_lookup() takes a hold on an smb_node, whether found in the
449 * hash table or newly created.  This hold is expected to be released
450 * in the following manner.
451 *
452 * smb_node_lookup() takes an address of an smb_node pointer.  This should
453 * be getting passed down via a lookup (whether path name or component), mkdir,
454 * create.  If the original smb_node pointer resides in a data structure, then
455 * the deallocation routine for the data structure is responsible for calling
456 * smb_node_release() on the smb_node pointer.  Alternatively,
457 * smb_node_release() can be called as soon as the smb_node pointer is no longer
458 * needed.  In this case, callers are responsible for setting an embedded
459 * pointer to NULL if it is known that the last reference is being released.
460 *
461 * If the passed-in address of the smb_node pointer belongs to a local variable,
462 * then the caller with the local variable should call smb_node_release()
463 * directly.
464 *
465 * smb_node_release() itself will call smb_node_release() on a node's n_dnode,
466 * as smb_node_lookup() takes a hold on dnode.
467 */
468void
469smb_node_release(smb_node_t *node)
470{
471	SMB_NODE_VALID(node);
472
473	mutex_enter(&node->n_mutex);
474	ASSERT(node->n_refcnt);
475	DTRACE_PROBE1(smb_node_release, smb_node_t *, node);
476	if (--node->n_refcnt == 0) {
477		switch (node->n_state) {
478
479		case SMB_NODE_STATE_AVAILABLE:
480			node->n_state = SMB_NODE_STATE_DESTROYING;
481			mutex_exit(&node->n_mutex);
482
483			smb_llist_enter(node->n_hash_bucket, RW_WRITER);
484			smb_llist_remove(node->n_hash_bucket, node);
485			smb_llist_exit(node->n_hash_bucket);
486
487			/*
488			 * Check if the file was deleted
489			 */
490			if (node->flags & NODE_FLAGS_DELETE_ON_CLOSE) {
491				smb_node_delete_on_close(node);
492			}
493
494			if (node->n_dnode) {
495				ASSERT(node->n_dnode->n_magic ==
496				    SMB_NODE_MAGIC);
497				smb_node_release(node->n_dnode);
498			}
499
500			if (node->n_unode) {
501				ASSERT(node->n_unode->n_magic ==
502				    SMB_NODE_MAGIC);
503				smb_node_release(node->n_unode);
504			}
505
506			smb_node_free(node);
507			return;
508
509		default:
510			SMB_PANIC();
511		}
512	}
513	smb_node_audit(node);
514	mutex_exit(&node->n_mutex);
515}
516
517void
518smb_node_delete_on_close(smb_node_t *node)
519{
520	smb_node_t	*d_snode;
521	int		rc = 0;
522	uint32_t	flags = 0;
523
524	d_snode = node->n_dnode;
525
526	ASSERT((node->flags & NODE_FLAGS_DELETE_ON_CLOSE) != 0);
527
528	node->flags &= ~NODE_FLAGS_DELETE_ON_CLOSE;
529	node->flags |= NODE_FLAGS_DELETE_COMMITTED;
530	flags = node->n_delete_on_close_flags;
531	ASSERT(node->od_name != NULL);
532
533	if (smb_node_is_dir(node))
534		rc = smb_fsop_rmdir(0, node->delete_on_close_cred,
535		    d_snode, node->od_name, flags);
536	else
537		rc = smb_fsop_remove(0, node->delete_on_close_cred,
538		    d_snode, node->od_name, flags);
539	crfree(node->delete_on_close_cred);
540	node->delete_on_close_cred = NULL;
541
542	if (rc != 0)
543		cmn_err(CE_WARN, "File %s could not be removed, rc=%d\n",
544		    node->od_name, rc);
545	DTRACE_PROBE2(smb_node_delete_on_close, int, rc, smb_node_t *, node);
546}
547
548/*
549 * smb_node_rename()
550 *
551 */
552void
553smb_node_rename(
554    smb_node_t	*from_dnode,
555    smb_node_t	*ret_node,
556    smb_node_t	*to_dnode,
557    char	*to_name)
558{
559	SMB_NODE_VALID(from_dnode);
560	SMB_NODE_VALID(to_dnode);
561	SMB_NODE_VALID(ret_node);
562
563	smb_node_ref(to_dnode);
564	mutex_enter(&ret_node->n_mutex);
565	switch (ret_node->n_state) {
566	case SMB_NODE_STATE_AVAILABLE:
567		ret_node->n_dnode = to_dnode;
568		mutex_exit(&ret_node->n_mutex);
569		ASSERT(to_dnode->n_dnode != ret_node);
570		ASSERT((to_dnode->vp->v_xattrdir) ||
571		    (to_dnode->vp->v_type == VDIR));
572		smb_node_release(from_dnode);
573		(void) strcpy(ret_node->od_name, to_name);
574		/*
575		 * XXX Need to update attributes?
576		 */
577		break;
578	default:
579		SMB_PANIC();
580	}
581}
582
583/*
584 * Find/create an SMB node for the root of this zone and store it
585 * in *svrootp.  Also create nodes leading to this directory.
586 */
587int
588smb_node_root_init(smb_server_t *sv, smb_node_t **svrootp)
589{
590	zone_t		*zone = curzone;
591	int		error;
592
593	ASSERT(zone->zone_id == sv->sv_zid);
594	if (smb_root_node == NULL)
595		return (ENOENT);
596
597	/*
598	 * We're getting smb nodes below the zone root here,
599	 * so need to use kcred, not zone_kcred().
600	 */
601	error = smb_pathname(NULL, zone->zone_rootpath, 0,
602	    smb_root_node, smb_root_node, NULL, svrootp, kcred, NULL);
603
604	return (error);
605}
606
607/*
608 * Helper function for smb_node_set_delete_on_close(). Assumes node is a dir.
609 * Return 0 if this is an empty dir. Otherwise return a NT_STATUS code.
610 * Unfortunately, to find out if a directory is empty, we have to read it
611 * and check for anything other than "." or ".." in the readdir buf.
612 */
613static uint32_t
614smb_rmdir_possible(smb_node_t *n)
615{
616	ASSERT(n->vp->v_type == VDIR);
617	char *buf;
618	char *bufptr;
619	struct dirent64	*dp;
620	uint32_t status = NT_STATUS_SUCCESS;
621	int bsize = SMB_ODIR_BUFSIZE;
622	int eof = 0;
623
624	buf = kmem_alloc(SMB_ODIR_BUFSIZE, KM_SLEEP);
625
626	/* Flags zero: no edirent, no ABE wanted here */
627	if (smb_vop_readdir(n->vp, 0, buf, &bsize, &eof, 0, zone_kcred())) {
628		status = NT_STATUS_INTERNAL_ERROR;
629		goto out;
630	}
631
632	bufptr = buf;
633	while (bsize > 0) {
634		/* LINTED pointer alignment */
635		dp = (struct dirent64 *)bufptr;
636
637		bufptr += dp->d_reclen;
638		bsize  -= dp->d_reclen;
639		if (bsize < 0) {
640			/* partial record */
641			status = NT_STATUS_DIRECTORY_NOT_EMPTY;
642			break;
643		}
644
645		if (strcmp(dp->d_name, ".") != 0 &&
646		    strcmp(dp->d_name, "..") != 0) {
647			status = NT_STATUS_DIRECTORY_NOT_EMPTY;
648			break;
649		}
650	}
651
652out:
653	kmem_free(buf, SMB_ODIR_BUFSIZE);
654	return (status);
655}
656
657/*
658 * When DeleteOnClose is set on an smb_node, the common open code will
659 * reject subsequent open requests for the file. Observation of Windows
660 * 2000 indicates that subsequent opens should be allowed (assuming
661 * there would be no sharing violation) until the file is closed using
662 * the fid on which the DeleteOnClose was requested.
663 *
664 * If there are multiple opens with delete-on-close create options,
665 * whichever the first file handle is closed will trigger the node to be
666 * marked as delete-on-close. The credentials of that ofile will be used
667 * as the delete-on-close credentials of the node.
668 *
669 * Note that "read-only" tests have already happened before this call.
670 */
671uint32_t
672smb_node_set_delete_on_close(smb_node_t *node, cred_t *cr, uint32_t flags)
673{
674	uint32_t status;
675
676	/*
677	 * If the directory is not empty we should fail setting del-on-close
678	 * with STATUS_DIRECTORY_NOT_EMPTY. see MS's
679	 * "File System Behavior Overview" doc section 4.3.2
680	 */
681	if (smb_node_is_dir(node)) {
682		status = smb_rmdir_possible(node);
683		if (status != 0) {
684			return (status);
685		}
686	}
687
688	/* Dataset roots can't be deleted, so don't set DOC */
689	if ((node->flags & NODE_FLAGS_VFSROOT) != 0) {
690		return (NT_STATUS_CANNOT_DELETE);
691	}
692
693	mutex_enter(&node->n_mutex);
694	if (node->flags & NODE_FLAGS_DELETE_ON_CLOSE) {
695		/* It was already marked.  We're done. */
696		mutex_exit(&node->n_mutex);
697		return (NT_STATUS_SUCCESS);
698	}
699
700	crhold(cr);
701	node->delete_on_close_cred = cr;
702	node->n_delete_on_close_flags = flags;
703	node->flags |= NODE_FLAGS_DELETE_ON_CLOSE;
704	mutex_exit(&node->n_mutex);
705
706	/*
707	 * Tell any change notify calls to close their handles
708	 * and get out of the way.  FILE_ACTION_DELETE_PENDING
709	 * is a special, internal-only action for this purpose.
710	 */
711	smb_node_notify_change(node, FILE_ACTION_DELETE_PENDING, NULL);
712
713	return (NT_STATUS_SUCCESS);
714}
715
716void
717smb_node_reset_delete_on_close(smb_node_t *node)
718{
719	mutex_enter(&node->n_mutex);
720	if (node->flags & NODE_FLAGS_DELETE_ON_CLOSE) {
721		node->flags &= ~NODE_FLAGS_DELETE_ON_CLOSE;
722		crfree(node->delete_on_close_cred);
723		node->delete_on_close_cred = NULL;
724		node->n_delete_on_close_flags = 0;
725	}
726	mutex_exit(&node->n_mutex);
727}
728
729/*
730 * smb_node_open_check
731 *
732 * check file sharing rules for current open request
733 * against all existing opens for a file.
734 *
735 * Returns NT_STATUS_SHARING_VIOLATION if there is any
736 * sharing conflict, otherwise returns NT_STATUS_SUCCESS.
737 */
738uint32_t
739smb_node_open_check(smb_node_t *node, uint32_t desired_access,
740    uint32_t share_access)
741{
742	smb_ofile_t *of;
743	uint32_t status;
744
745	SMB_NODE_VALID(node);
746
747	smb_llist_enter(&node->n_ofile_list, RW_READER);
748	of = smb_llist_head(&node->n_ofile_list);
749	while (of) {
750		status = smb_ofile_open_check(of, desired_access, share_access);
751
752		switch (status) {
753		case NT_STATUS_INVALID_HANDLE:
754		case NT_STATUS_SUCCESS:
755			of = smb_llist_next(&node->n_ofile_list, of);
756			break;
757		default:
758			ASSERT(status == NT_STATUS_SHARING_VIOLATION);
759			DTRACE_PROBE3(conflict3,
760			    smb_ofile_t, of,
761			    uint32_t, desired_access,
762			    uint32_t, share_access);
763			smb_llist_exit(&node->n_ofile_list);
764			return (status);
765		}
766	}
767
768	smb_llist_exit(&node->n_ofile_list);
769	return (NT_STATUS_SUCCESS);
770}
771
772uint32_t
773smb_node_rename_check(smb_node_t *node)
774{
775	smb_ofile_t	*of;
776	uint32_t	status;
777
778	SMB_NODE_VALID(node);
779
780	/*
781	 * Intra-CIFS check
782	 */
783	smb_llist_enter(&node->n_ofile_list, RW_READER);
784	of = smb_llist_head(&node->n_ofile_list);
785	while (of) {
786		status = smb_ofile_rename_check(of);
787
788		switch (status) {
789		case NT_STATUS_INVALID_HANDLE:
790		case NT_STATUS_SUCCESS:
791			of = smb_llist_next(&node->n_ofile_list, of);
792			break;
793		default:
794			ASSERT(status == NT_STATUS_SHARING_VIOLATION);
795			DTRACE_PROBE1(conflict1, smb_ofile_t, of);
796			smb_llist_exit(&node->n_ofile_list);
797			return (status);
798		}
799	}
800	smb_llist_exit(&node->n_ofile_list);
801	return (NT_STATUS_SUCCESS);
802}
803
804uint32_t
805smb_node_delete_check(smb_node_t *node)
806{
807	smb_ofile_t	*of;
808	uint32_t	status;
809
810	SMB_NODE_VALID(node);
811
812	if (smb_node_is_dir(node))
813		return (NT_STATUS_SUCCESS);
814
815	if (smb_node_is_reparse(node))
816		return (NT_STATUS_ACCESS_DENIED);
817
818	/*
819	 * intra-CIFS check
820	 */
821	smb_llist_enter(&node->n_ofile_list, RW_READER);
822	of = smb_llist_head(&node->n_ofile_list);
823	while (of) {
824		status = smb_ofile_delete_check(of);
825
826		switch (status) {
827		case NT_STATUS_INVALID_HANDLE:
828		case NT_STATUS_SUCCESS:
829			of = smb_llist_next(&node->n_ofile_list, of);
830			break;
831		default:
832			ASSERT(status == NT_STATUS_SHARING_VIOLATION);
833			DTRACE_PROBE1(conflict1, smb_ofile_t, of);
834			smb_llist_exit(&node->n_ofile_list);
835			return (status);
836		}
837	}
838	smb_llist_exit(&node->n_ofile_list);
839	return (NT_STATUS_SUCCESS);
840}
841
842/*
843 * smb_node_share_check
844 *
845 * Returns: TRUE    - ofiles have non-zero share access
846 *          B_FALSE - ofile with share access NONE.
847 */
848boolean_t
849smb_node_share_check(smb_node_t *node)
850{
851	smb_ofile_t	*of;
852	boolean_t	status = B_TRUE;
853
854	SMB_NODE_VALID(node);
855
856	smb_llist_enter(&node->n_ofile_list, RW_READER);
857	of = smb_llist_head(&node->n_ofile_list);
858	if (of)
859		status = smb_ofile_share_check(of);
860	smb_llist_exit(&node->n_ofile_list);
861
862	return (status);
863}
864
865/*
866 * SMB Change Notification
867 */
868
869void
870smb_node_fcn_subscribe(smb_node_t *node)
871{
872
873	mutex_enter(&node->n_mutex);
874	if (node->n_fcn_count == 0)
875		(void) smb_fem_fcn_install(node);
876	node->n_fcn_count++;
877	mutex_exit(&node->n_mutex);
878}
879
880void
881smb_node_fcn_unsubscribe(smb_node_t *node)
882{
883
884	mutex_enter(&node->n_mutex);
885	node->n_fcn_count--;
886	if (node->n_fcn_count == 0)
887		smb_fem_fcn_uninstall(node);
888	mutex_exit(&node->n_mutex);
889}
890
891void
892smb_node_notify_change(smb_node_t *node, uint_t action, const char *name)
893{
894	smb_ofile_t	*of;
895
896	SMB_NODE_VALID(node);
897
898	smb_llist_enter(&node->n_ofile_list, RW_READER);
899	of = smb_llist_head(&node->n_ofile_list);
900	while (of) {
901		/*
902		 * We'd rather deliver events only to ofiles that have
903		 * subscribed.  There's no explicit synchronization with
904		 * where this flag is set, but other actions cause this
905		 * value to reach visibility soon enough for events to
906		 * start arriving by the time we need them to start.
907		 * Once nc_subscribed is set, it stays set for the
908		 * life of the ofile.
909		 */
910		if (of->f_notify.nc_subscribed)
911			smb_notify_ofile(of, action, name);
912		of = smb_llist_next(&node->n_ofile_list, of);
913	}
914	smb_llist_exit(&node->n_ofile_list);
915
916	/*
917	 * After changes that add or remove a name,
918	 * we know the directory attributes changed,
919	 * and we can tell the immediate parent.
920	 */
921	switch (action) {
922	case FILE_ACTION_ADDED:
923	case FILE_ACTION_REMOVED:
924	case FILE_ACTION_RENAMED_NEW_NAME:
925		/*
926		 * Note: FILE_ACTION_RENAMED_OLD_NAME is intentionally
927		 * omitted, because it's always followed by another
928		 * event with FILE_ACTION_RENAMED_NEW_NAME posted to
929		 * the same directory, and we only need/want one.
930		 */
931		if (node->n_dnode != NULL) {
932			smb_node_notify_change(node->n_dnode,
933			    FILE_ACTION_MODIFIED, node->od_name);
934		}
935		break;
936	}
937
938	/*
939	 * If we wanted to support recursive notify events
940	 * (where a notify call on some directory receives
941	 * events from all objects below that directory),
942	 * we might deliver _SUBDIR_CHANGED to all our
943	 * parents, grandparents etc, here.  However, we
944	 * don't currently subscribe to changes on all the
945	 * child (and grandchild) objects that would be
946	 * needed to make that work. It's prohibitively
947	 * expensive to do that, and support for recursive
948	 * notify is optional anyway, so don't bother.
949	 */
950}
951
952/*
953 * smb_node_start_crit()
954 *
955 * Enter critical region for share reservations.
956 * See comments above smb_fsop_shrlock().
957 */
958void
959smb_node_start_crit(smb_node_t *node, krw_t mode)
960{
961	rw_enter(&node->n_lock, mode);
962	nbl_start_crit(node->vp, mode);
963}
964
965/*
966 * smb_node_end_crit()
967 *
968 * Exit critical region for share reservations.
969 */
970void
971smb_node_end_crit(smb_node_t *node)
972{
973	nbl_end_crit(node->vp);
974	rw_exit(&node->n_lock);
975}
976
977int
978smb_node_in_crit(smb_node_t *node)
979{
980	return (nbl_in_crit(node->vp) && RW_LOCK_HELD(&node->n_lock));
981}
982
983void
984smb_node_rdlock(smb_node_t *node)
985{
986	rw_enter(&node->n_lock, RW_READER);
987}
988
989void
990smb_node_wrlock(smb_node_t *node)
991{
992	rw_enter(&node->n_lock, RW_WRITER);
993}
994
995void
996smb_node_unlock(smb_node_t *node)
997{
998	rw_exit(&node->n_lock);
999}
1000
1001void
1002smb_node_add_ofile(smb_node_t *node, smb_ofile_t *of)
1003{
1004	SMB_NODE_VALID(node);
1005
1006	smb_llist_enter(&node->n_ofile_list, RW_WRITER);
1007	smb_llist_insert_tail(&node->n_ofile_list, of);
1008	smb_llist_exit(&node->n_ofile_list);
1009}
1010
1011void
1012smb_node_rem_ofile(smb_node_t *node, smb_ofile_t *of)
1013{
1014	SMB_NODE_VALID(node);
1015
1016	smb_llist_enter(&node->n_ofile_list, RW_WRITER);
1017	smb_llist_remove(&node->n_ofile_list, of);
1018	smb_llist_exit(&node->n_ofile_list);
1019}
1020
1021/*
1022 * smb_node_inc_open_ofiles
1023 */
1024void
1025smb_node_inc_open_ofiles(smb_node_t *node)
1026{
1027	SMB_NODE_VALID(node);
1028	atomic_inc_32(&node->n_open_count);
1029}
1030
1031/*
1032 * smb_node_dec_open_ofiles
1033 * returns new value
1034 */
1035uint32_t
1036smb_node_dec_open_ofiles(smb_node_t *node)
1037{
1038	SMB_NODE_VALID(node);
1039	return (atomic_dec_32_nv(&node->n_open_count));
1040}
1041
1042/*
1043 * smb_node_inc_opening_count
1044 */
1045void
1046smb_node_inc_opening_count(smb_node_t *node)
1047{
1048	SMB_NODE_VALID(node);
1049	atomic_inc_32(&node->n_opening_count);
1050}
1051
1052/*
1053 * smb_node_dec_opening_count
1054 */
1055void
1056smb_node_dec_opening_count(smb_node_t *node)
1057{
1058	SMB_NODE_VALID(node);
1059	atomic_dec_32(&node->n_opening_count);
1060}
1061
1062/*
1063 * smb_node_getmntpath
1064 */
1065int
1066smb_node_getmntpath(smb_node_t *node, char *buf, uint32_t buflen)
1067{
1068	vnode_t *vp, *root_vp;
1069	vfs_t *vfsp;
1070	int err;
1071
1072	ASSERT(node);
1073	ASSERT(node->vp);
1074	ASSERT(node->vp->v_vfsp);
1075
1076	vp = node->vp;
1077	vfsp = vp->v_vfsp;
1078
1079	if (VFS_ROOT(vfsp, &root_vp))
1080		return (ENOENT);
1081
1082	VN_HOLD(vp);
1083
1084	/* NULL is passed in as we want to start at "/" */
1085	err = vnodetopath(NULL, root_vp, buf, buflen, zone_kcred());
1086
1087	VN_RELE(vp);
1088	VN_RELE(root_vp);
1089	return (err);
1090}
1091
1092/*
1093 * smb_node_getshrpath
1094 *
1095 * Determine the absolute pathname of 'node' within the share (tree).
1096 * For example if the node represents file "test1.txt" in directory
1097 * "dir1" the pathname would be: \dir1\test1.txt
1098 */
1099int
1100smb_node_getshrpath(smb_node_t *node, smb_tree_t *tree,
1101    char *buf, uint32_t buflen)
1102{
1103	int rc;
1104
1105	ASSERT(node);
1106	ASSERT(tree);
1107	ASSERT(tree->t_snode);
1108
1109	rc = smb_node_getpath(node, tree->t_snode->vp, buf, buflen);
1110	(void) strsubst(buf, '/', '\\');
1111	return (rc);
1112}
1113
1114/*
1115 * smb_node_getpath
1116 *
1117 * Determine the absolute pathname of 'node' from 'rootvp'.
1118 *
1119 * Using vnodetopath is only reliable for directory nodes (due to
1120 * its reliance on the DNLC for non-directory nodes). Thus, if node
1121 * represents a file, construct the pathname for the parent dnode
1122 * and append filename.
1123 * If node represents a named stream, construct the pathname for the
1124 * associated unnamed stream and append the stream name.
1125 *
1126 * The pathname returned in buf will be '/' separated.
1127 */
1128int
1129smb_node_getpath(smb_node_t *node, vnode_t *rootvp, char *buf, uint32_t buflen)
1130{
1131	int rc;
1132	vnode_t *vp;
1133	smb_node_t *unode, *dnode;
1134	cred_t *kcr = zone_kcred();
1135
1136	unode = (SMB_IS_STREAM(node)) ? node->n_unode : node;
1137	dnode = (smb_node_is_dir(unode)) ? unode : unode->n_dnode;
1138
1139	/* find path to directory node */
1140	vp = dnode->vp;
1141	VN_HOLD(vp);
1142	if (rootvp) {
1143		VN_HOLD(rootvp);
1144		rc = vnodetopath(rootvp, vp, buf, buflen, kcr);
1145		VN_RELE(rootvp);
1146	} else {
1147		rc = vnodetopath(NULL, vp, buf, buflen, kcr);
1148	}
1149	VN_RELE(vp);
1150
1151	if (rc != 0)
1152		return (rc);
1153
1154	/* append filename if necessary */
1155	if (!smb_node_is_dir(unode)) {
1156		if (buf[strlen(buf) - 1] != '/')
1157			(void) strlcat(buf, "/", buflen);
1158		(void) strlcat(buf, unode->od_name, buflen);
1159	}
1160
1161	/* append named stream name if necessary */
1162	if (SMB_IS_STREAM(node))
1163		(void) strlcat(buf, node->od_name, buflen);
1164
1165	return (rc);
1166}
1167
1168/*
1169 * smb_node_alloc
1170 */
1171static smb_node_t *
1172smb_node_alloc(
1173    char	*od_name,
1174    vnode_t	*vp,
1175    smb_llist_t	*bucket,
1176    uint32_t	hashkey)
1177{
1178	smb_node_t	*node;
1179	vnode_t		*root_vp;
1180
1181	node = kmem_cache_alloc(smb_node_cache, KM_SLEEP);
1182
1183	if (node->n_audit_buf != NULL)
1184		node->n_audit_buf->anb_index = 0;
1185
1186	node->flags = 0;
1187	VN_HOLD(vp);
1188	node->vp = vp;
1189	node->n_refcnt = 1;
1190	node->n_hash_bucket = bucket;
1191	node->n_hashkey = hashkey;
1192	node->n_open_count = 0;
1193	node->n_allocsz = 0;
1194	node->n_dnode = NULL;
1195	node->n_unode = NULL;
1196	node->delete_on_close_cred = NULL;
1197	node->n_delete_on_close_flags = 0;
1198	node->n_oplock.ol_fem = B_FALSE;
1199
1200	(void) strlcpy(node->od_name, od_name, sizeof (node->od_name));
1201	if (strcmp(od_name, XATTR_DIR) == 0)
1202		node->flags |= NODE_XATTR_DIR;
1203
1204	if (VFS_ROOT(vp->v_vfsp, &root_vp) == 0) {
1205		if (vp == root_vp)
1206			node->flags |= NODE_FLAGS_VFSROOT;
1207		VN_RELE(root_vp);
1208	}
1209
1210	node->n_state = SMB_NODE_STATE_AVAILABLE;
1211	node->n_magic = SMB_NODE_MAGIC;
1212
1213	return (node);
1214}
1215
1216/*
1217 * smb_node_free
1218 */
1219static void
1220smb_node_free(smb_node_t *node)
1221{
1222	SMB_NODE_VALID(node);
1223
1224	node->n_magic = 0;
1225	VERIFY(!list_link_active(&node->n_lnd));
1226	VERIFY(node->n_lock_list.ll_count == 0);
1227	VERIFY(node->n_wlock_list.ll_count == 0);
1228	VERIFY(node->n_ofile_list.ll_count == 0);
1229	VERIFY(node->n_oplock.ol_fem == B_FALSE);
1230	VERIFY(MUTEX_NOT_HELD(&node->n_mutex));
1231	VERIFY(!RW_LOCK_HELD(&node->n_lock));
1232	VN_RELE(node->vp);
1233	kmem_cache_free(smb_node_cache, node);
1234}
1235
1236/*
1237 * smb_node_constructor
1238 */
1239static int
1240smb_node_constructor(void *buf, void *un, int kmflags)
1241{
1242	_NOTE(ARGUNUSED(kmflags, un))
1243
1244	smb_node_t	*node = (smb_node_t *)buf;
1245
1246	bzero(node, sizeof (smb_node_t));
1247
1248	smb_llist_constructor(&node->n_ofile_list, sizeof (smb_ofile_t),
1249	    offsetof(smb_ofile_t, f_node_lnd));
1250	smb_llist_constructor(&node->n_lock_list, sizeof (smb_lock_t),
1251	    offsetof(smb_lock_t, l_lnd));
1252	smb_llist_constructor(&node->n_wlock_list, sizeof (smb_lock_t),
1253	    offsetof(smb_lock_t, l_lnd));
1254	mutex_init(&node->n_oplock.ol_mutex, NULL, MUTEX_DEFAULT, NULL);
1255	cv_init(&node->n_oplock.WaitingOpenCV, NULL, CV_DEFAULT, NULL);
1256	rw_init(&node->n_lock, NULL, RW_DEFAULT, NULL);
1257	mutex_init(&node->n_mutex, NULL, MUTEX_DEFAULT, NULL);
1258	smb_node_create_audit_buf(node, kmflags);
1259	return (0);
1260}
1261
1262/*
1263 * smb_node_destructor
1264 */
1265static void
1266smb_node_destructor(void *buf, void *un)
1267{
1268	_NOTE(ARGUNUSED(un))
1269
1270	smb_node_t	*node = (smb_node_t *)buf;
1271
1272	smb_node_destroy_audit_buf(node);
1273	mutex_destroy(&node->n_mutex);
1274	rw_destroy(&node->n_lock);
1275	cv_destroy(&node->n_oplock.WaitingOpenCV);
1276	mutex_destroy(&node->n_oplock.ol_mutex);
1277	smb_llist_destructor(&node->n_lock_list);
1278	smb_llist_destructor(&node->n_wlock_list);
1279	smb_llist_destructor(&node->n_ofile_list);
1280}
1281
1282/*
1283 * smb_node_create_audit_buf
1284 */
1285static void
1286smb_node_create_audit_buf(smb_node_t *node, int kmflags)
1287{
1288	smb_audit_buf_node_t	*abn;
1289
1290	if (smb_audit_flags & SMB_AUDIT_NODE) {
1291		abn = kmem_zalloc(sizeof (smb_audit_buf_node_t), kmflags);
1292		abn->anb_max_index = SMB_AUDIT_BUF_MAX_REC - 1;
1293		node->n_audit_buf = abn;
1294	}
1295}
1296
1297/*
1298 * smb_node_destroy_audit_buf
1299 */
1300static void
1301smb_node_destroy_audit_buf(smb_node_t *node)
1302{
1303	if (node->n_audit_buf != NULL) {
1304		kmem_free(node->n_audit_buf, sizeof (smb_audit_buf_node_t));
1305		node->n_audit_buf = NULL;
1306	}
1307}
1308
1309/*
1310 * smb_node_audit
1311 *
1312 * This function saves the calling stack in the audit buffer of the node passed
1313 * in.
1314 */
1315static void
1316smb_node_audit(smb_node_t *node)
1317{
1318#ifdef	_KERNEL
1319	smb_audit_buf_node_t	*abn;
1320	smb_audit_record_node_t	*anr;
1321
1322	if (node->n_audit_buf) {
1323		abn = node->n_audit_buf;
1324		anr = abn->anb_records;
1325		anr += abn->anb_index;
1326		abn->anb_index++;
1327		abn->anb_index &= abn->anb_max_index;
1328		anr->anr_refcnt = node->n_refcnt;
1329		anr->anr_depth = getpcstack(anr->anr_stack,
1330		    SMB_AUDIT_STACK_DEPTH);
1331	}
1332#else	/* _KERNEL */
1333	_NOTE(ARGUNUSED(node))
1334#endif	/* _KERNEL */
1335}
1336
1337static smb_llist_t *
1338smb_node_get_hash(fsid_t *fsid, smb_attr_t *attr, uint32_t *phashkey)
1339{
1340	uint32_t	hashkey;
1341
1342	hashkey = fsid->val[0] + attr->sa_vattr.va_nodeid;
1343	hashkey += (hashkey >> 24) + (hashkey >> 16) + (hashkey >> 8);
1344	*phashkey = hashkey;
1345	return (&smb_node_hash_table[(hashkey & SMBND_HASH_MASK)]);
1346}
1347
1348boolean_t
1349smb_node_is_file(smb_node_t *node)
1350{
1351	SMB_NODE_VALID(node);
1352	return (node->vp->v_type == VREG);
1353}
1354
1355boolean_t
1356smb_node_is_dir(smb_node_t *node)
1357{
1358	SMB_NODE_VALID(node);
1359	return ((node->vp->v_type == VDIR) ||
1360	    (node->flags & NODE_FLAGS_DFSLINK));
1361}
1362
1363boolean_t
1364smb_node_is_symlink(smb_node_t *node)
1365{
1366	SMB_NODE_VALID(node);
1367	return ((node->vp->v_type == VLNK) &&
1368	    ((node->flags & NODE_FLAGS_REPARSE) == 0));
1369}
1370
1371boolean_t
1372smb_node_is_dfslink(smb_node_t *node)
1373{
1374	SMB_NODE_VALID(node);
1375	return ((node->vp->v_type == VLNK) &&
1376	    (node->flags & NODE_FLAGS_DFSLINK));
1377}
1378
1379boolean_t
1380smb_node_is_reparse(smb_node_t *node)
1381{
1382	SMB_NODE_VALID(node);
1383	return ((node->vp->v_type == VLNK) &&
1384	    (node->flags & NODE_FLAGS_REPARSE));
1385}
1386
1387boolean_t
1388smb_node_is_vfsroot(smb_node_t *node)
1389{
1390	SMB_NODE_VALID(node);
1391	return ((node->flags & NODE_FLAGS_VFSROOT) == NODE_FLAGS_VFSROOT);
1392}
1393
1394boolean_t
1395smb_node_is_system(smb_node_t *node)
1396{
1397	SMB_NODE_VALID(node);
1398	return ((node->flags & NODE_FLAGS_SYSTEM) == NODE_FLAGS_SYSTEM);
1399}
1400
1401/*
1402 * smb_node_file_is_readonly
1403 *
1404 * Checks if the file (which node represents) is marked readonly
1405 * in the filesystem.  Note that there may be handles open with
1406 * modify rights, and those continue to allow access even after
1407 * the DOS read-only flag has been set in the file system.
1408 */
1409boolean_t
1410smb_node_file_is_readonly(smb_node_t *node)
1411{
1412	smb_attr_t attr;
1413
1414	if (node == NULL)
1415		return (B_FALSE);	/* pipes */
1416
1417	bzero(&attr, sizeof (smb_attr_t));
1418	attr.sa_mask = SMB_AT_DOSATTR;
1419	(void) smb_fsop_getattr(NULL, zone_kcred(), node, &attr);
1420	return ((attr.sa_dosattr & FILE_ATTRIBUTE_READONLY) != 0);
1421}
1422
1423/*
1424 * smb_node_setattr
1425 *
1426 * The sr may be NULL, for example when closing an ofile.
1427 * The ofile may be NULL, for example when a client request
1428 * specifies the file by pathname.
1429 *
1430 * Returns: errno
1431 *
1432 * Timestamps
1433 *
1434 * Windows and Unix have different models for timestamp updates.
1435 * [MS-FSA 2.1.5.14 Server Requests Setting of File Information]
1436 *
1437 * An open "handle" in Windows can control whether and when
1438 * any timestamp updates happen for that handle.  For example,
1439 * timestamps set via some handle are no longer updated by I/O
1440 * operations on that handle.  In Unix we don't really have any
1441 * way to avoid the timestamp updates that the file system does.
1442 * Therefore, we need to make some compromises, and simulate the
1443 * more important parts of the Windows file system semantics.
1444 *
1445 * For example, when an SMB client sets file times, set those
1446 * times in the file system (so the change will be visible to
1447 * other clients, at least until they change again) but we also
1448 * make those times "sticky" in our open handle, and reapply
1449 * those times when the handle is closed.  That reapply on close
1450 * simulates the Windows behavior where the timestamp updates
1451 * would be discontinued after they were set.  These "sticky"
1452 * attributes are returned in any query on the handle where
1453 * they are stored.
1454 *
1455 * Other than the above, the file system layer takes care of the
1456 * normal time stamp updates, such as updating the mtime after a
1457 * write, and ctime after an attribute change.
1458 *
1459 * Dos Attributes are stored persistently, but with a twist:
1460 * In Windows, when you set the "read-only" bit on some file,
1461 * existing writable handles to that file continue to have
1462 * write access.  (because access check happens at open)
1463 * If we were to set the read-only bit directly, we would
1464 * cause errors in subsequent writes on any of our open
1465 * (and writable) file handles.  So here too, we have to
1466 * simulate the Windows behavior.  We keep the read-only
1467 * bit "pending" in the smb_node (so it will be visible in
1468 * any new opens of the file) and apply it on close.
1469 *
1470 * File allocation size is also simulated, and not persistent.
1471 * When the file allocation size is set it is first rounded up
1472 * to block size. If the file size is smaller than the allocation
1473 * size the file is truncated by setting the filesize to allocsz.
1474 */
1475int
1476smb_node_setattr(smb_request_t *sr, smb_node_t *node,
1477    cred_t *cr, smb_ofile_t *of, smb_attr_t *attr)
1478{
1479	int rc;
1480	uint_t times_mask;
1481	smb_attr_t tmp_attr;
1482
1483	SMB_NODE_VALID(node);
1484
1485	/* set attributes specified in attr */
1486	if (attr->sa_mask == 0)
1487		return (0);  /* nothing to do (caller bug?) */
1488
1489	/*
1490	 * Allocation size and EOF position interact.
1491	 * We don't persistently store the allocation size
1492	 * but make it look like we do while there are opens.
1493	 * Note: We update the caller's attr in the cases
1494	 * where they're setting only one of allocsz|size.
1495	 */
1496	switch (attr->sa_mask & (SMB_AT_ALLOCSZ | SMB_AT_SIZE)) {
1497
1498	case SMB_AT_ALLOCSZ:
1499		/*
1500		 * Setting the allocation size but not EOF position.
1501		 * Get the current EOF in tmp_attr and (if necessary)
1502		 * truncate to the (rounded up) allocation size.
1503		 * Using kcred here because if we don't have access,
1504		 * we want to fail at setattr below and not here.
1505		 */
1506		bzero(&tmp_attr, sizeof (smb_attr_t));
1507		tmp_attr.sa_mask = SMB_AT_SIZE;
1508		rc = smb_fsop_getattr(NULL, zone_kcred(), node, &tmp_attr);
1509		if (rc != 0)
1510			return (rc);
1511		attr->sa_allocsz = SMB_ALLOCSZ(attr->sa_allocsz);
1512		if (tmp_attr.sa_vattr.va_size > attr->sa_allocsz) {
1513			/* truncate the file to allocsz */
1514			attr->sa_vattr.va_size = attr->sa_allocsz;
1515			attr->sa_mask |= SMB_AT_SIZE;
1516		}
1517		break;
1518
1519	case SMB_AT_SIZE:
1520		/*
1521		 * Setting the EOF position but not allocation size.
1522		 * If the new EOF position would be greater than
1523		 * the allocation size, increase the latter.
1524		 */
1525		if (node->n_allocsz < attr->sa_vattr.va_size) {
1526			attr->sa_mask |= SMB_AT_ALLOCSZ;
1527			attr->sa_allocsz =
1528			    SMB_ALLOCSZ(attr->sa_vattr.va_size);
1529		}
1530		break;
1531
1532	case SMB_AT_ALLOCSZ | SMB_AT_SIZE:
1533		/*
1534		 * Setting both.  Increase alloc size if needed.
1535		 */
1536		if (attr->sa_allocsz < attr->sa_vattr.va_size)
1537			attr->sa_allocsz =
1538			    SMB_ALLOCSZ(attr->sa_vattr.va_size);
1539		break;
1540
1541	default:
1542		break;
1543	}
1544
1545	/*
1546	 * If we have an open file, and we set the size,
1547	 * then set the "written" flag so that at close,
1548	 * we can force an mtime update.
1549	 */
1550	if (of != NULL && (attr->sa_mask & SMB_AT_SIZE) != 0)
1551		of->f_written = B_TRUE;
1552
1553	/*
1554	 * When operating on an open file, some settable attributes
1555	 * become "sticky" in the open file object until close.
1556	 * (see above re. timestamps)
1557	 */
1558	times_mask = attr->sa_mask & SMB_AT_TIMES;
1559	if (of != NULL && times_mask != 0) {
1560		smb_attr_t *pa;
1561
1562		SMB_OFILE_VALID(of);
1563		mutex_enter(&of->f_mutex);
1564		pa = &of->f_pending_attr;
1565
1566		pa->sa_mask |= times_mask;
1567
1568		if (times_mask & SMB_AT_ATIME)
1569			pa->sa_vattr.va_atime =
1570			    attr->sa_vattr.va_atime;
1571		if (times_mask & SMB_AT_MTIME)
1572			pa->sa_vattr.va_mtime =
1573			    attr->sa_vattr.va_mtime;
1574		if (times_mask & SMB_AT_CTIME)
1575			pa->sa_vattr.va_ctime =
1576			    attr->sa_vattr.va_ctime;
1577		if (times_mask & SMB_AT_CRTIME)
1578			pa->sa_crtime =
1579			    attr->sa_crtime;
1580
1581		mutex_exit(&of->f_mutex);
1582
1583		/*
1584		 * The f_pending_attr times are reapplied in
1585		 * smb_ofile_close().
1586		 */
1587
1588		/*
1589		 * If this change is coming directly from a client
1590		 * (sr != NULL) and it's a persistent handle, save
1591		 * the "sticky times" in the handle.
1592		 */
1593		if (sr != NULL && of->dh_persist) {
1594			smb2_dh_update_times(sr, of, attr);
1595		}
1596	}
1597
1598	if ((attr->sa_mask & SMB_AT_ALLOCSZ) != 0) {
1599		mutex_enter(&node->n_mutex);
1600		/*
1601		 * Simulate n_allocsz persistence only while
1602		 * there are opens.  See smb_node_getattr
1603		 */
1604		if (node->n_open_count != 0)
1605			node->n_allocsz = attr->sa_allocsz;
1606		mutex_exit(&node->n_mutex);
1607	}
1608
1609	rc = smb_fsop_setattr(sr, cr, node, attr);
1610	if (rc != 0)
1611		return (rc);
1612
1613	if (node->n_dnode != NULL) {
1614		smb_node_notify_change(node->n_dnode,
1615		    FILE_ACTION_MODIFIED, node->od_name);
1616	}
1617
1618	return (0);
1619}
1620
1621/*
1622 * smb_node_getattr
1623 *
1624 * Get attributes from the file system and apply any smb-specific
1625 * overrides for size, dos attributes and timestamps
1626 *
1627 * When node->n_pending_readonly is set on a node, pretend that
1628 * we've already set this node readonly at the filesystem level.
1629 * We can't actually do that until all writable handles are closed
1630 * or those writable handles would suddenly loose their access.
1631 *
1632 * Returns: errno
1633 */
1634int
1635smb_node_getattr(smb_request_t *sr, smb_node_t *node, cred_t *cr,
1636    smb_ofile_t *of, smb_attr_t *attr)
1637{
1638	int rc;
1639	uint_t want_mask, pend_mask;
1640	boolean_t isdir;
1641
1642	SMB_NODE_VALID(node);
1643
1644	/* Deal with some interdependencies */
1645	if (attr->sa_mask & SMB_AT_ALLOCSZ)
1646		attr->sa_mask |= SMB_AT_SIZE;
1647	if (attr->sa_mask & SMB_AT_DOSATTR)
1648		attr->sa_mask |= SMB_AT_TYPE;
1649
1650	rc = smb_fsop_getattr(sr, cr, node, attr);
1651	if (rc != 0)
1652		return (rc);
1653
1654	isdir = smb_node_is_dir(node);
1655
1656	mutex_enter(&node->n_mutex);
1657
1658	if (attr->sa_mask & SMB_AT_DOSATTR) {
1659		if (attr->sa_dosattr == 0) {
1660			attr->sa_dosattr = (isdir) ?
1661			    FILE_ATTRIBUTE_DIRECTORY:
1662			    FILE_ATTRIBUTE_NORMAL;
1663		}
1664	}
1665
1666	/*
1667	 * Also fix-up sa_allocsz, which is not persistent.
1668	 * When there are no open files, allocsz is faked.
1669	 * While there are open files, we pretend we have a
1670	 * persistent allocation size in n_allocsz, and
1671	 * keep that up-to-date here, increasing it when
1672	 * we see the file size grow past it.
1673	 */
1674	if (attr->sa_mask & SMB_AT_ALLOCSZ) {
1675		if (isdir) {
1676			attr->sa_allocsz = 0;
1677		} else if (node->n_open_count == 0) {
1678			attr->sa_allocsz =
1679			    SMB_ALLOCSZ(attr->sa_vattr.va_size);
1680		} else {
1681			if (node->n_allocsz < attr->sa_vattr.va_size)
1682				node->n_allocsz =
1683				    SMB_ALLOCSZ(attr->sa_vattr.va_size);
1684			attr->sa_allocsz = node->n_allocsz;
1685		}
1686	}
1687
1688	mutex_exit(&node->n_mutex);
1689
1690	if (isdir) {
1691		attr->sa_vattr.va_size = 0;
1692		attr->sa_vattr.va_nlink = 1;
1693	}
1694
1695	/*
1696	 * getattr with an ofile gets any "pending" times that
1697	 * might have been previously set via this ofile.
1698	 * This is what makes these times "sticky".
1699	 */
1700	want_mask = attr->sa_mask & SMB_AT_TIMES;
1701	if (of != NULL && want_mask != 0) {
1702		smb_attr_t *pa;
1703
1704		SMB_OFILE_VALID(of);
1705		mutex_enter(&of->f_mutex);
1706		pa = &of->f_pending_attr;
1707
1708		pend_mask = pa->sa_mask;
1709
1710		if (want_mask & pend_mask & SMB_AT_ATIME)
1711			attr->sa_vattr.va_atime =
1712			    pa->sa_vattr.va_atime;
1713		if (want_mask & pend_mask & SMB_AT_MTIME)
1714			attr->sa_vattr.va_mtime =
1715			    pa->sa_vattr.va_mtime;
1716		if (want_mask & pend_mask & SMB_AT_CTIME)
1717			attr->sa_vattr.va_ctime =
1718			    pa->sa_vattr.va_ctime;
1719		if (want_mask & pend_mask & SMB_AT_CRTIME)
1720			attr->sa_crtime =
1721			    pa->sa_crtime;
1722
1723		mutex_exit(&of->f_mutex);
1724	}
1725
1726
1727	return (0);
1728}
1729
1730
1731#ifndef	_KERNEL
1732extern int reparse_vnode_parse(vnode_t *vp, nvlist_t *nvl);
1733#endif	/* _KERNEL */
1734
1735/*
1736 * Check to see if the node represents a reparse point.
1737 * If yes, whether the reparse point contains a DFS link.
1738 */
1739static void
1740smb_node_init_reparse(smb_node_t *node, smb_attr_t *attr)
1741{
1742	nvlist_t *nvl;
1743	nvpair_t *rec;
1744	char *rec_type;
1745
1746	if ((attr->sa_dosattr & FILE_ATTRIBUTE_REPARSE_POINT) == 0)
1747		return;
1748
1749	if ((nvl = reparse_init()) == NULL)
1750		return;
1751
1752	if (reparse_vnode_parse(node->vp, nvl) != 0) {
1753		reparse_free(nvl);
1754		return;
1755	}
1756
1757	node->flags |= NODE_FLAGS_REPARSE;
1758
1759	rec = nvlist_next_nvpair(nvl, NULL);
1760	while (rec != NULL) {
1761		rec_type = nvpair_name(rec);
1762		if ((rec_type != NULL) &&
1763		    (strcasecmp(rec_type, DFS_REPARSE_SVCTYPE) == 0)) {
1764			node->flags |= NODE_FLAGS_DFSLINK;
1765			break;
1766		}
1767		rec = nvlist_next_nvpair(nvl, rec);
1768	}
1769
1770	reparse_free(nvl);
1771}
1772
1773/*
1774 * smb_node_init_system
1775 *
1776 * If the node represents a special system file set NODE_FLAG_SYSTEM.
1777 * System files:
1778 * - any node whose parent dnode has NODE_FLAG_SYSTEM set
1779 * - any node whose associated unnamed stream node (unode) has
1780 *   NODE_FLAG_SYSTEM set
1781 * - .$EXTEND at root of share (quota management)
1782 */
1783static void
1784smb_node_init_system(smb_node_t *node)
1785{
1786	smb_node_t *dnode = node->n_dnode;
1787	smb_node_t *unode = node->n_unode;
1788
1789	if ((dnode) && (dnode->flags & NODE_FLAGS_SYSTEM)) {
1790		node->flags |= NODE_FLAGS_SYSTEM;
1791		return;
1792	}
1793
1794	if ((unode) && (unode->flags & NODE_FLAGS_SYSTEM)) {
1795		node->flags |= NODE_FLAGS_SYSTEM;
1796		return;
1797	}
1798
1799	if ((dnode) && (smb_node_is_vfsroot(node->n_dnode) &&
1800	    (strcasecmp(node->od_name, ".$EXTEND") == 0))) {
1801		node->flags |= NODE_FLAGS_SYSTEM;
1802	}
1803}
1804