xref: /onnv-gate/usr/src/uts/common/fs/smbsrv/smb_kutil.c (revision 11963:061945695ce1)
1*11963SAfshin.Ardakani@Sun.COM /*
2*11963SAfshin.Ardakani@Sun.COM  * CDDL HEADER START
3*11963SAfshin.Ardakani@Sun.COM  *
4*11963SAfshin.Ardakani@Sun.COM  * The contents of this file are subject to the terms of the
5*11963SAfshin.Ardakani@Sun.COM  * Common Development and Distribution License (the "License").
6*11963SAfshin.Ardakani@Sun.COM  * You may not use this file except in compliance with the License.
7*11963SAfshin.Ardakani@Sun.COM  *
8*11963SAfshin.Ardakani@Sun.COM  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
9*11963SAfshin.Ardakani@Sun.COM  * or http://www.opensolaris.org/os/licensing.
10*11963SAfshin.Ardakani@Sun.COM  * See the License for the specific language governing permissions
11*11963SAfshin.Ardakani@Sun.COM  * and limitations under the License.
12*11963SAfshin.Ardakani@Sun.COM  *
13*11963SAfshin.Ardakani@Sun.COM  * When distributing Covered Code, include this CDDL HEADER in each
14*11963SAfshin.Ardakani@Sun.COM  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
15*11963SAfshin.Ardakani@Sun.COM  * If applicable, add the following below this CDDL HEADER, with the
16*11963SAfshin.Ardakani@Sun.COM  * fields enclosed by brackets "[]" replaced with your own identifying
17*11963SAfshin.Ardakani@Sun.COM  * information: Portions Copyright [yyyy] [name of copyright owner]
18*11963SAfshin.Ardakani@Sun.COM  *
19*11963SAfshin.Ardakani@Sun.COM  * CDDL HEADER END
20*11963SAfshin.Ardakani@Sun.COM  */
21*11963SAfshin.Ardakani@Sun.COM /*
22*11963SAfshin.Ardakani@Sun.COM  * Copyright 2010 Sun Microsystems, Inc.  All rights reserved.
23*11963SAfshin.Ardakani@Sun.COM  * Use is subject to license terms.
24*11963SAfshin.Ardakani@Sun.COM  */
25*11963SAfshin.Ardakani@Sun.COM 
26*11963SAfshin.Ardakani@Sun.COM #include <sys/param.h>
27*11963SAfshin.Ardakani@Sun.COM #include <sys/types.h>
28*11963SAfshin.Ardakani@Sun.COM #include <sys/tzfile.h>
29*11963SAfshin.Ardakani@Sun.COM #include <sys/atomic.h>
30*11963SAfshin.Ardakani@Sun.COM #include <sys/kidmap.h>
31*11963SAfshin.Ardakani@Sun.COM #include <sys/time.h>
32*11963SAfshin.Ardakani@Sun.COM #include <sys/cpuvar.h>
33*11963SAfshin.Ardakani@Sun.COM #include <smbsrv/smb_kproto.h>
34*11963SAfshin.Ardakani@Sun.COM #include <smbsrv/smb_fsops.h>
35*11963SAfshin.Ardakani@Sun.COM #include <smbsrv/smbinfo.h>
36*11963SAfshin.Ardakani@Sun.COM #include <smbsrv/smb_xdr.h>
37*11963SAfshin.Ardakani@Sun.COM #include <smbsrv/smb_vops.h>
38*11963SAfshin.Ardakani@Sun.COM #include <smbsrv/smb_idmap.h>
39*11963SAfshin.Ardakani@Sun.COM 
40*11963SAfshin.Ardakani@Sun.COM #include <sys/sid.h>
41*11963SAfshin.Ardakani@Sun.COM #include <sys/priv_names.h>
42*11963SAfshin.Ardakani@Sun.COM 
43*11963SAfshin.Ardakani@Sun.COM static kmem_cache_t	*smb_dtor_cache;
44*11963SAfshin.Ardakani@Sun.COM static boolean_t	smb_llist_initialized = B_FALSE;
45*11963SAfshin.Ardakani@Sun.COM 
46*11963SAfshin.Ardakani@Sun.COM static void smb_llist_flush(smb_llist_t *);
47*11963SAfshin.Ardakani@Sun.COM static boolean_t smb_thread_continue_timedwait_locked(smb_thread_t *, int);
48*11963SAfshin.Ardakani@Sun.COM 
49*11963SAfshin.Ardakani@Sun.COM time_t tzh_leapcnt = 0;
50*11963SAfshin.Ardakani@Sun.COM 
51*11963SAfshin.Ardakani@Sun.COM struct tm
52*11963SAfshin.Ardakani@Sun.COM *smb_gmtime_r(time_t *clock, struct tm *result);
53*11963SAfshin.Ardakani@Sun.COM 
54*11963SAfshin.Ardakani@Sun.COM time_t
55*11963SAfshin.Ardakani@Sun.COM smb_timegm(struct tm *tm);
56*11963SAfshin.Ardakani@Sun.COM 
57*11963SAfshin.Ardakani@Sun.COM struct	tm {
58*11963SAfshin.Ardakani@Sun.COM 	int	tm_sec;
59*11963SAfshin.Ardakani@Sun.COM 	int	tm_min;
60*11963SAfshin.Ardakani@Sun.COM 	int	tm_hour;
61*11963SAfshin.Ardakani@Sun.COM 	int	tm_mday;
62*11963SAfshin.Ardakani@Sun.COM 	int	tm_mon;
63*11963SAfshin.Ardakani@Sun.COM 	int	tm_year;
64*11963SAfshin.Ardakani@Sun.COM 	int	tm_wday;
65*11963SAfshin.Ardakani@Sun.COM 	int	tm_yday;
66*11963SAfshin.Ardakani@Sun.COM 	int	tm_isdst;
67*11963SAfshin.Ardakani@Sun.COM };
68*11963SAfshin.Ardakani@Sun.COM 
69*11963SAfshin.Ardakani@Sun.COM static int days_in_month[] = {
70*11963SAfshin.Ardakani@Sun.COM 	31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31
71*11963SAfshin.Ardakani@Sun.COM };
72*11963SAfshin.Ardakani@Sun.COM 
73*11963SAfshin.Ardakani@Sun.COM int
74*11963SAfshin.Ardakani@Sun.COM smb_ascii_or_unicode_strlen(struct smb_request *sr, char *str)
75*11963SAfshin.Ardakani@Sun.COM {
76*11963SAfshin.Ardakani@Sun.COM 	if (sr->smb_flg2 & SMB_FLAGS2_UNICODE)
77*11963SAfshin.Ardakani@Sun.COM 		return (smb_wcequiv_strlen(str));
78*11963SAfshin.Ardakani@Sun.COM 	return (strlen(str));
79*11963SAfshin.Ardakani@Sun.COM }
80*11963SAfshin.Ardakani@Sun.COM 
81*11963SAfshin.Ardakani@Sun.COM int
82*11963SAfshin.Ardakani@Sun.COM smb_ascii_or_unicode_strlen_null(struct smb_request *sr, char *str)
83*11963SAfshin.Ardakani@Sun.COM {
84*11963SAfshin.Ardakani@Sun.COM 	if (sr->smb_flg2 & SMB_FLAGS2_UNICODE)
85*11963SAfshin.Ardakani@Sun.COM 		return (smb_wcequiv_strlen(str) + 2);
86*11963SAfshin.Ardakani@Sun.COM 	return (strlen(str) + 1);
87*11963SAfshin.Ardakani@Sun.COM }
88*11963SAfshin.Ardakani@Sun.COM 
89*11963SAfshin.Ardakani@Sun.COM int
90*11963SAfshin.Ardakani@Sun.COM smb_ascii_or_unicode_null_len(struct smb_request *sr)
91*11963SAfshin.Ardakani@Sun.COM {
92*11963SAfshin.Ardakani@Sun.COM 	if (sr->smb_flg2 & SMB_FLAGS2_UNICODE)
93*11963SAfshin.Ardakani@Sun.COM 		return (2);
94*11963SAfshin.Ardakani@Sun.COM 	return (1);
95*11963SAfshin.Ardakani@Sun.COM }
96*11963SAfshin.Ardakani@Sun.COM 
97*11963SAfshin.Ardakani@Sun.COM /*
98*11963SAfshin.Ardakani@Sun.COM  * Return B_TRUE if pattern contains wildcards
99*11963SAfshin.Ardakani@Sun.COM  */
100*11963SAfshin.Ardakani@Sun.COM boolean_t
101*11963SAfshin.Ardakani@Sun.COM smb_contains_wildcards(const char *pattern)
102*11963SAfshin.Ardakani@Sun.COM {
103*11963SAfshin.Ardakani@Sun.COM 	static const char *wildcards = "*?";
104*11963SAfshin.Ardakani@Sun.COM 
105*11963SAfshin.Ardakani@Sun.COM 	return (strpbrk(pattern, wildcards) != NULL);
106*11963SAfshin.Ardakani@Sun.COM }
107*11963SAfshin.Ardakani@Sun.COM 
108*11963SAfshin.Ardakani@Sun.COM /*
109*11963SAfshin.Ardakani@Sun.COM  * When converting wildcards a '.' in a name is treated as a base and
110*11963SAfshin.Ardakani@Sun.COM  * extension separator even if the name is longer than 8.3.
111*11963SAfshin.Ardakani@Sun.COM  *
112*11963SAfshin.Ardakani@Sun.COM  * The '*' character matches an entire part of the name.  For example,
113*11963SAfshin.Ardakani@Sun.COM  * "*.abc" matches any name with an extension of "abc".
114*11963SAfshin.Ardakani@Sun.COM  *
115*11963SAfshin.Ardakani@Sun.COM  * The '?' character matches a single character.
116*11963SAfshin.Ardakani@Sun.COM  * If the base contains all ? (8 or more) then it is treated as *.
117*11963SAfshin.Ardakani@Sun.COM  * If the extension contains all ? (3 or more) then it is treated as *.
118*11963SAfshin.Ardakani@Sun.COM  *
119*11963SAfshin.Ardakani@Sun.COM  * Clients convert ASCII wildcards to Unicode wildcards as follows:
120*11963SAfshin.Ardakani@Sun.COM  *
121*11963SAfshin.Ardakani@Sun.COM  *	? is converted to >
122*11963SAfshin.Ardakani@Sun.COM  *	. is converted to " if it is followed by ? or *
123*11963SAfshin.Ardakani@Sun.COM  *	* is converted to < if it is followed by .
124*11963SAfshin.Ardakani@Sun.COM  *
125*11963SAfshin.Ardakani@Sun.COM  * Note that clients convert "*." to '< and drop the '.' but "*.txt"
126*11963SAfshin.Ardakani@Sun.COM  * is sent as "<.TXT", i.e.
127*11963SAfshin.Ardakani@Sun.COM  *
128*11963SAfshin.Ardakani@Sun.COM  * 	dir *.		->	dir <
129*11963SAfshin.Ardakani@Sun.COM  * 	dir *.txt	->	dir <.TXT
130*11963SAfshin.Ardakani@Sun.COM  *
131*11963SAfshin.Ardakani@Sun.COM  * Since " and < are illegal in Windows file names, we always convert
132*11963SAfshin.Ardakani@Sun.COM  * these Unicode wildcards without checking the following character.
133*11963SAfshin.Ardakani@Sun.COM  */
134*11963SAfshin.Ardakani@Sun.COM void
135*11963SAfshin.Ardakani@Sun.COM smb_convert_wildcards(char *pattern)
136*11963SAfshin.Ardakani@Sun.COM {
137*11963SAfshin.Ardakani@Sun.COM 	static char *match_all[] = {
138*11963SAfshin.Ardakani@Sun.COM 		"*.",
139*11963SAfshin.Ardakani@Sun.COM 		"*.*"
140*11963SAfshin.Ardakani@Sun.COM 	};
141*11963SAfshin.Ardakani@Sun.COM 	char	*extension;
142*11963SAfshin.Ardakani@Sun.COM 	char	*p;
143*11963SAfshin.Ardakani@Sun.COM 	int	len;
144*11963SAfshin.Ardakani@Sun.COM 	int	i;
145*11963SAfshin.Ardakani@Sun.COM 
146*11963SAfshin.Ardakani@Sun.COM 	/*
147*11963SAfshin.Ardakani@Sun.COM 	 * Special case "<" for "dir *.", and fast-track for "*".
148*11963SAfshin.Ardakani@Sun.COM 	 */
149*11963SAfshin.Ardakani@Sun.COM 	if ((*pattern == '<') || (*pattern == '*')) {
150*11963SAfshin.Ardakani@Sun.COM 		if (*(pattern + 1) == '\0') {
151*11963SAfshin.Ardakani@Sun.COM 			*pattern = '*';
152*11963SAfshin.Ardakani@Sun.COM 			return;
153*11963SAfshin.Ardakani@Sun.COM 		}
154*11963SAfshin.Ardakani@Sun.COM 	}
155*11963SAfshin.Ardakani@Sun.COM 
156*11963SAfshin.Ardakani@Sun.COM 	for (p = pattern; *p != '\0'; ++p) {
157*11963SAfshin.Ardakani@Sun.COM 		switch (*p) {
158*11963SAfshin.Ardakani@Sun.COM 		case '<':
159*11963SAfshin.Ardakani@Sun.COM 			*p = '*';
160*11963SAfshin.Ardakani@Sun.COM 			break;
161*11963SAfshin.Ardakani@Sun.COM 		case '>':
162*11963SAfshin.Ardakani@Sun.COM 			*p = '?';
163*11963SAfshin.Ardakani@Sun.COM 			break;
164*11963SAfshin.Ardakani@Sun.COM 		case '\"':
165*11963SAfshin.Ardakani@Sun.COM 			*p = '.';
166*11963SAfshin.Ardakani@Sun.COM 			break;
167*11963SAfshin.Ardakani@Sun.COM 		default:
168*11963SAfshin.Ardakani@Sun.COM 			break;
169*11963SAfshin.Ardakani@Sun.COM 		}
170*11963SAfshin.Ardakani@Sun.COM 	}
171*11963SAfshin.Ardakani@Sun.COM 
172*11963SAfshin.Ardakani@Sun.COM 	/*
173*11963SAfshin.Ardakani@Sun.COM 	 * Replace "????????.ext" with "*.ext".
174*11963SAfshin.Ardakani@Sun.COM 	 */
175*11963SAfshin.Ardakani@Sun.COM 	p = pattern;
176*11963SAfshin.Ardakani@Sun.COM 	p += strspn(p, "?");
177*11963SAfshin.Ardakani@Sun.COM 	if (*p == '.') {
178*11963SAfshin.Ardakani@Sun.COM 		*p = '\0';
179*11963SAfshin.Ardakani@Sun.COM 		len = strlen(pattern);
180*11963SAfshin.Ardakani@Sun.COM 		*p = '.';
181*11963SAfshin.Ardakani@Sun.COM 		if (len >= SMB_NAME83_BASELEN) {
182*11963SAfshin.Ardakani@Sun.COM 			*pattern = '*';
183*11963SAfshin.Ardakani@Sun.COM 			(void) strlcpy(pattern + 1, p, MAXPATHLEN - 1);
184*11963SAfshin.Ardakani@Sun.COM 		}
185*11963SAfshin.Ardakani@Sun.COM 	}
186*11963SAfshin.Ardakani@Sun.COM 
187*11963SAfshin.Ardakani@Sun.COM 	/*
188*11963SAfshin.Ardakani@Sun.COM 	 * Replace "base.???" with 'base.*'.
189*11963SAfshin.Ardakani@Sun.COM 	 */
190*11963SAfshin.Ardakani@Sun.COM 	if ((extension = strrchr(pattern, '.')) != NULL) {
191*11963SAfshin.Ardakani@Sun.COM 		p = ++extension;
192*11963SAfshin.Ardakani@Sun.COM 		p += strspn(p, "?");
193*11963SAfshin.Ardakani@Sun.COM 		if (*p == '\0') {
194*11963SAfshin.Ardakani@Sun.COM 			len = strlen(extension);
195*11963SAfshin.Ardakani@Sun.COM 			if (len >= SMB_NAME83_EXTLEN) {
196*11963SAfshin.Ardakani@Sun.COM 				*extension = '\0';
197*11963SAfshin.Ardakani@Sun.COM 				(void) strlcat(pattern, "*", MAXPATHLEN);
198*11963SAfshin.Ardakani@Sun.COM 			}
199*11963SAfshin.Ardakani@Sun.COM 		}
200*11963SAfshin.Ardakani@Sun.COM 	}
201*11963SAfshin.Ardakani@Sun.COM 
202*11963SAfshin.Ardakani@Sun.COM 	/*
203*11963SAfshin.Ardakani@Sun.COM 	 * Replace anything that matches an entry in match_all with "*".
204*11963SAfshin.Ardakani@Sun.COM 	 */
205*11963SAfshin.Ardakani@Sun.COM 	for (i = 0; i < sizeof (match_all) / sizeof (match_all[0]); ++i) {
206*11963SAfshin.Ardakani@Sun.COM 		if (strcmp(pattern, match_all[i]) == 0) {
207*11963SAfshin.Ardakani@Sun.COM 			(void) strlcpy(pattern, "*", MAXPATHLEN);
208*11963SAfshin.Ardakani@Sun.COM 			break;
209*11963SAfshin.Ardakani@Sun.COM 		}
210*11963SAfshin.Ardakani@Sun.COM 	}
211*11963SAfshin.Ardakani@Sun.COM }
212*11963SAfshin.Ardakani@Sun.COM 
213*11963SAfshin.Ardakani@Sun.COM /*
214*11963SAfshin.Ardakani@Sun.COM  * smb_sattr_check
215*11963SAfshin.Ardakani@Sun.COM  *
216*11963SAfshin.Ardakani@Sun.COM  * Check file attributes against a search attribute (sattr) mask.
217*11963SAfshin.Ardakani@Sun.COM  *
218*11963SAfshin.Ardakani@Sun.COM  * Normal files, which includes READONLY and ARCHIVE, always pass
219*11963SAfshin.Ardakani@Sun.COM  * this check.  If the DIRECTORY, HIDDEN or SYSTEM special attributes
220*11963SAfshin.Ardakani@Sun.COM  * are set then they must appear in the search mask.  The special
221*11963SAfshin.Ardakani@Sun.COM  * attributes are inclusive, i.e. all special attributes that appear
222*11963SAfshin.Ardakani@Sun.COM  * in sattr must also appear in the file attributes for the check to
223*11963SAfshin.Ardakani@Sun.COM  * pass.
224*11963SAfshin.Ardakani@Sun.COM  *
225*11963SAfshin.Ardakani@Sun.COM  * The following examples show how this works:
226*11963SAfshin.Ardakani@Sun.COM  *
227*11963SAfshin.Ardakani@Sun.COM  *		fileA:	READONLY
228*11963SAfshin.Ardakani@Sun.COM  *		fileB:	0 (no attributes = normal file)
229*11963SAfshin.Ardakani@Sun.COM  *		fileC:	READONLY, ARCHIVE
230*11963SAfshin.Ardakani@Sun.COM  *		fileD:	HIDDEN
231*11963SAfshin.Ardakani@Sun.COM  *		fileE:	READONLY, HIDDEN, SYSTEM
232*11963SAfshin.Ardakani@Sun.COM  *		dirA:	DIRECTORY
233*11963SAfshin.Ardakani@Sun.COM  *
234*11963SAfshin.Ardakani@Sun.COM  * search attribute: 0
235*11963SAfshin.Ardakani@Sun.COM  *		Returns: fileA, fileB and fileC.
236*11963SAfshin.Ardakani@Sun.COM  * search attribute: HIDDEN
237*11963SAfshin.Ardakani@Sun.COM  *		Returns: fileA, fileB, fileC and fileD.
238*11963SAfshin.Ardakani@Sun.COM  * search attribute: SYSTEM
239*11963SAfshin.Ardakani@Sun.COM  *		Returns: fileA, fileB and fileC.
240*11963SAfshin.Ardakani@Sun.COM  * search attribute: DIRECTORY
241*11963SAfshin.Ardakani@Sun.COM  *		Returns: fileA, fileB, fileC and dirA.
242*11963SAfshin.Ardakani@Sun.COM  * search attribute: HIDDEN and SYSTEM
243*11963SAfshin.Ardakani@Sun.COM  *		Returns: fileA, fileB, fileC, fileD and fileE.
244*11963SAfshin.Ardakani@Sun.COM  *
245*11963SAfshin.Ardakani@Sun.COM  * Returns true if the file and sattr match; otherwise, returns false.
246*11963SAfshin.Ardakani@Sun.COM  */
247*11963SAfshin.Ardakani@Sun.COM boolean_t
248*11963SAfshin.Ardakani@Sun.COM smb_sattr_check(uint16_t dosattr, uint16_t sattr)
249*11963SAfshin.Ardakani@Sun.COM {
250*11963SAfshin.Ardakani@Sun.COM 	if ((dosattr & FILE_ATTRIBUTE_DIRECTORY) &&
251*11963SAfshin.Ardakani@Sun.COM 	    !(sattr & FILE_ATTRIBUTE_DIRECTORY))
252*11963SAfshin.Ardakani@Sun.COM 		return (B_FALSE);
253*11963SAfshin.Ardakani@Sun.COM 
254*11963SAfshin.Ardakani@Sun.COM 	if ((dosattr & FILE_ATTRIBUTE_HIDDEN) &&
255*11963SAfshin.Ardakani@Sun.COM 	    !(sattr & FILE_ATTRIBUTE_HIDDEN))
256*11963SAfshin.Ardakani@Sun.COM 		return (B_FALSE);
257*11963SAfshin.Ardakani@Sun.COM 
258*11963SAfshin.Ardakani@Sun.COM 	if ((dosattr & FILE_ATTRIBUTE_SYSTEM) &&
259*11963SAfshin.Ardakani@Sun.COM 	    !(sattr & FILE_ATTRIBUTE_SYSTEM))
260*11963SAfshin.Ardakani@Sun.COM 		return (B_FALSE);
261*11963SAfshin.Ardakani@Sun.COM 
262*11963SAfshin.Ardakani@Sun.COM 	return (B_TRUE);
263*11963SAfshin.Ardakani@Sun.COM }
264*11963SAfshin.Ardakani@Sun.COM 
265*11963SAfshin.Ardakani@Sun.COM int
266*11963SAfshin.Ardakani@Sun.COM microtime(timestruc_t *tvp)
267*11963SAfshin.Ardakani@Sun.COM {
268*11963SAfshin.Ardakani@Sun.COM 	tvp->tv_sec = gethrestime_sec();
269*11963SAfshin.Ardakani@Sun.COM 	tvp->tv_nsec = 0;
270*11963SAfshin.Ardakani@Sun.COM 	return (0);
271*11963SAfshin.Ardakani@Sun.COM }
272*11963SAfshin.Ardakani@Sun.COM 
273*11963SAfshin.Ardakani@Sun.COM int32_t
274*11963SAfshin.Ardakani@Sun.COM clock_get_milli_uptime()
275*11963SAfshin.Ardakani@Sun.COM {
276*11963SAfshin.Ardakani@Sun.COM 	return (TICK_TO_MSEC(ddi_get_lbolt()));
277*11963SAfshin.Ardakani@Sun.COM }
278*11963SAfshin.Ardakani@Sun.COM 
279*11963SAfshin.Ardakani@Sun.COM int /*ARGSUSED*/
280*11963SAfshin.Ardakani@Sun.COM smb_noop(void *p, size_t size, int foo)
281*11963SAfshin.Ardakani@Sun.COM {
282*11963SAfshin.Ardakani@Sun.COM 	return (0);
283*11963SAfshin.Ardakani@Sun.COM }
284*11963SAfshin.Ardakani@Sun.COM 
285*11963SAfshin.Ardakani@Sun.COM /*
286*11963SAfshin.Ardakani@Sun.COM  * smb_idpool_increment
287*11963SAfshin.Ardakani@Sun.COM  *
288*11963SAfshin.Ardakani@Sun.COM  * This function increments the ID pool by doubling the current size. This
289*11963SAfshin.Ardakani@Sun.COM  * function assumes the caller entered the mutex of the pool.
290*11963SAfshin.Ardakani@Sun.COM  */
291*11963SAfshin.Ardakani@Sun.COM static int
292*11963SAfshin.Ardakani@Sun.COM smb_idpool_increment(
293*11963SAfshin.Ardakani@Sun.COM     smb_idpool_t	*pool)
294*11963SAfshin.Ardakani@Sun.COM {
295*11963SAfshin.Ardakani@Sun.COM 	uint8_t		*new_pool;
296*11963SAfshin.Ardakani@Sun.COM 	uint32_t	new_size;
297*11963SAfshin.Ardakani@Sun.COM 
298*11963SAfshin.Ardakani@Sun.COM 	ASSERT(pool->id_magic == SMB_IDPOOL_MAGIC);
299*11963SAfshin.Ardakani@Sun.COM 
300*11963SAfshin.Ardakani@Sun.COM 	new_size = pool->id_size * 2;
301*11963SAfshin.Ardakani@Sun.COM 	if (new_size <= SMB_IDPOOL_MAX_SIZE) {
302*11963SAfshin.Ardakani@Sun.COM 		new_pool = kmem_alloc(new_size / 8, KM_NOSLEEP);
303*11963SAfshin.Ardakani@Sun.COM 		if (new_pool) {
304*11963SAfshin.Ardakani@Sun.COM 			bzero(new_pool, new_size / 8);
305*11963SAfshin.Ardakani@Sun.COM 			bcopy(pool->id_pool, new_pool, pool->id_size / 8);
306*11963SAfshin.Ardakani@Sun.COM 			kmem_free(pool->id_pool, pool->id_size / 8);
307*11963SAfshin.Ardakani@Sun.COM 			pool->id_pool = new_pool;
308*11963SAfshin.Ardakani@Sun.COM 			pool->id_free_counter += new_size - pool->id_size;
309*11963SAfshin.Ardakani@Sun.COM 			pool->id_max_free_counter += new_size - pool->id_size;
310*11963SAfshin.Ardakani@Sun.COM 			pool->id_size = new_size;
311*11963SAfshin.Ardakani@Sun.COM 			pool->id_idx_msk = (new_size / 8) - 1;
312*11963SAfshin.Ardakani@Sun.COM 			if (new_size >= SMB_IDPOOL_MAX_SIZE) {
313*11963SAfshin.Ardakani@Sun.COM 				/* id -1 made unavailable */
314*11963SAfshin.Ardakani@Sun.COM 				pool->id_pool[pool->id_idx_msk] = 0x80;
315*11963SAfshin.Ardakani@Sun.COM 				pool->id_free_counter--;
316*11963SAfshin.Ardakani@Sun.COM 				pool->id_max_free_counter--;
317*11963SAfshin.Ardakani@Sun.COM 			}
318*11963SAfshin.Ardakani@Sun.COM 			return (0);
319*11963SAfshin.Ardakani@Sun.COM 		}
320*11963SAfshin.Ardakani@Sun.COM 	}
321*11963SAfshin.Ardakani@Sun.COM 	return (-1);
322*11963SAfshin.Ardakani@Sun.COM }
323*11963SAfshin.Ardakani@Sun.COM 
324*11963SAfshin.Ardakani@Sun.COM /*
325*11963SAfshin.Ardakani@Sun.COM  * smb_idpool_constructor
326*11963SAfshin.Ardakani@Sun.COM  *
327*11963SAfshin.Ardakani@Sun.COM  * This function initializes the pool structure provided.
328*11963SAfshin.Ardakani@Sun.COM  */
329*11963SAfshin.Ardakani@Sun.COM int
330*11963SAfshin.Ardakani@Sun.COM smb_idpool_constructor(
331*11963SAfshin.Ardakani@Sun.COM     smb_idpool_t	*pool)
332*11963SAfshin.Ardakani@Sun.COM {
333*11963SAfshin.Ardakani@Sun.COM 
334*11963SAfshin.Ardakani@Sun.COM 	ASSERT(pool->id_magic != SMB_IDPOOL_MAGIC);
335*11963SAfshin.Ardakani@Sun.COM 
336*11963SAfshin.Ardakani@Sun.COM 	pool->id_size = SMB_IDPOOL_MIN_SIZE;
337*11963SAfshin.Ardakani@Sun.COM 	pool->id_idx_msk = (SMB_IDPOOL_MIN_SIZE / 8) - 1;
338*11963SAfshin.Ardakani@Sun.COM 	pool->id_free_counter = SMB_IDPOOL_MIN_SIZE - 1;
339*11963SAfshin.Ardakani@Sun.COM 	pool->id_max_free_counter = SMB_IDPOOL_MIN_SIZE - 1;
340*11963SAfshin.Ardakani@Sun.COM 	pool->id_bit = 0x02;
341*11963SAfshin.Ardakani@Sun.COM 	pool->id_bit_idx = 1;
342*11963SAfshin.Ardakani@Sun.COM 	pool->id_idx = 0;
343*11963SAfshin.Ardakani@Sun.COM 	pool->id_pool = (uint8_t *)kmem_alloc((SMB_IDPOOL_MIN_SIZE / 8),
344*11963SAfshin.Ardakani@Sun.COM 	    KM_SLEEP);
345*11963SAfshin.Ardakani@Sun.COM 	bzero(pool->id_pool, (SMB_IDPOOL_MIN_SIZE / 8));
346*11963SAfshin.Ardakani@Sun.COM 	/* -1 id made unavailable */
347*11963SAfshin.Ardakani@Sun.COM 	pool->id_pool[0] = 0x01;		/* id 0 made unavailable */
348*11963SAfshin.Ardakani@Sun.COM 	mutex_init(&pool->id_mutex, NULL, MUTEX_DEFAULT, NULL);
349*11963SAfshin.Ardakani@Sun.COM 	pool->id_magic = SMB_IDPOOL_MAGIC;
350*11963SAfshin.Ardakani@Sun.COM 	return (0);
351*11963SAfshin.Ardakani@Sun.COM }
352*11963SAfshin.Ardakani@Sun.COM 
353*11963SAfshin.Ardakani@Sun.COM /*
354*11963SAfshin.Ardakani@Sun.COM  * smb_idpool_destructor
355*11963SAfshin.Ardakani@Sun.COM  *
356*11963SAfshin.Ardakani@Sun.COM  * This function tears down and frees the resources associated with the
357*11963SAfshin.Ardakani@Sun.COM  * pool provided.
358*11963SAfshin.Ardakani@Sun.COM  */
359*11963SAfshin.Ardakani@Sun.COM void
360*11963SAfshin.Ardakani@Sun.COM smb_idpool_destructor(
361*11963SAfshin.Ardakani@Sun.COM     smb_idpool_t	*pool)
362*11963SAfshin.Ardakani@Sun.COM {
363*11963SAfshin.Ardakani@Sun.COM 	ASSERT(pool->id_magic == SMB_IDPOOL_MAGIC);
364*11963SAfshin.Ardakani@Sun.COM 	ASSERT(pool->id_free_counter == pool->id_max_free_counter);
365*11963SAfshin.Ardakani@Sun.COM 	pool->id_magic = (uint32_t)~SMB_IDPOOL_MAGIC;
366*11963SAfshin.Ardakani@Sun.COM 	mutex_destroy(&pool->id_mutex);
367*11963SAfshin.Ardakani@Sun.COM 	kmem_free(pool->id_pool, (size_t)(pool->id_size / 8));
368*11963SAfshin.Ardakani@Sun.COM }
369*11963SAfshin.Ardakani@Sun.COM 
370*11963SAfshin.Ardakani@Sun.COM /*
371*11963SAfshin.Ardakani@Sun.COM  * smb_idpool_alloc
372*11963SAfshin.Ardakani@Sun.COM  *
373*11963SAfshin.Ardakani@Sun.COM  * This function allocates an ID from the pool provided.
374*11963SAfshin.Ardakani@Sun.COM  */
375*11963SAfshin.Ardakani@Sun.COM int
376*11963SAfshin.Ardakani@Sun.COM smb_idpool_alloc(
377*11963SAfshin.Ardakani@Sun.COM     smb_idpool_t	*pool,
378*11963SAfshin.Ardakani@Sun.COM     uint16_t		*id)
379*11963SAfshin.Ardakani@Sun.COM {
380*11963SAfshin.Ardakani@Sun.COM 	uint32_t	i;
381*11963SAfshin.Ardakani@Sun.COM 	uint8_t		bit;
382*11963SAfshin.Ardakani@Sun.COM 	uint8_t		bit_idx;
383*11963SAfshin.Ardakani@Sun.COM 	uint8_t		byte;
384*11963SAfshin.Ardakani@Sun.COM 
385*11963SAfshin.Ardakani@Sun.COM 	ASSERT(pool->id_magic == SMB_IDPOOL_MAGIC);
386*11963SAfshin.Ardakani@Sun.COM 
387*11963SAfshin.Ardakani@Sun.COM 	mutex_enter(&pool->id_mutex);
388*11963SAfshin.Ardakani@Sun.COM 	if ((pool->id_free_counter == 0) && smb_idpool_increment(pool)) {
389*11963SAfshin.Ardakani@Sun.COM 		mutex_exit(&pool->id_mutex);
390*11963SAfshin.Ardakani@Sun.COM 		return (-1);
391*11963SAfshin.Ardakani@Sun.COM 	}
392*11963SAfshin.Ardakani@Sun.COM 
393*11963SAfshin.Ardakani@Sun.COM 	i = pool->id_size;
394*11963SAfshin.Ardakani@Sun.COM 	while (i) {
395*11963SAfshin.Ardakani@Sun.COM 		bit = pool->id_bit;
396*11963SAfshin.Ardakani@Sun.COM 		bit_idx = pool->id_bit_idx;
397*11963SAfshin.Ardakani@Sun.COM 		byte = pool->id_pool[pool->id_idx];
398*11963SAfshin.Ardakani@Sun.COM 		while (bit) {
399*11963SAfshin.Ardakani@Sun.COM 			if (byte & bit) {
400*11963SAfshin.Ardakani@Sun.COM 				bit = bit << 1;
401*11963SAfshin.Ardakani@Sun.COM 				bit_idx++;
402*11963SAfshin.Ardakani@Sun.COM 				continue;
403*11963SAfshin.Ardakani@Sun.COM 			}
404*11963SAfshin.Ardakani@Sun.COM 			pool->id_pool[pool->id_idx] |= bit;
405*11963SAfshin.Ardakani@Sun.COM 			*id = (uint16_t)(pool->id_idx * 8 + (uint32_t)bit_idx);
406*11963SAfshin.Ardakani@Sun.COM 			pool->id_free_counter--;
407*11963SAfshin.Ardakani@Sun.COM 			pool->id_bit = bit;
408*11963SAfshin.Ardakani@Sun.COM 			pool->id_bit_idx = bit_idx;
409*11963SAfshin.Ardakani@Sun.COM 			mutex_exit(&pool->id_mutex);
410*11963SAfshin.Ardakani@Sun.COM 			return (0);
411*11963SAfshin.Ardakani@Sun.COM 		}
412*11963SAfshin.Ardakani@Sun.COM 		pool->id_bit = 1;
413*11963SAfshin.Ardakani@Sun.COM 		pool->id_bit_idx = 0;
414*11963SAfshin.Ardakani@Sun.COM 		pool->id_idx++;
415*11963SAfshin.Ardakani@Sun.COM 		pool->id_idx &= pool->id_idx_msk;
416*11963SAfshin.Ardakani@Sun.COM 		--i;
417*11963SAfshin.Ardakani@Sun.COM 	}
418*11963SAfshin.Ardakani@Sun.COM 	/*
419*11963SAfshin.Ardakani@Sun.COM 	 * This section of code shouldn't be reached. If there are IDs
420*11963SAfshin.Ardakani@Sun.COM 	 * available and none could be found there's a problem.
421*11963SAfshin.Ardakani@Sun.COM 	 */
422*11963SAfshin.Ardakani@Sun.COM 	ASSERT(0);
423*11963SAfshin.Ardakani@Sun.COM 	mutex_exit(&pool->id_mutex);
424*11963SAfshin.Ardakani@Sun.COM 	return (-1);
425*11963SAfshin.Ardakani@Sun.COM }
426*11963SAfshin.Ardakani@Sun.COM 
427*11963SAfshin.Ardakani@Sun.COM /*
428*11963SAfshin.Ardakani@Sun.COM  * smb_idpool_free
429*11963SAfshin.Ardakani@Sun.COM  *
430*11963SAfshin.Ardakani@Sun.COM  * This function frees the ID provided.
431*11963SAfshin.Ardakani@Sun.COM  */
432*11963SAfshin.Ardakani@Sun.COM void
433*11963SAfshin.Ardakani@Sun.COM smb_idpool_free(
434*11963SAfshin.Ardakani@Sun.COM     smb_idpool_t	*pool,
435*11963SAfshin.Ardakani@Sun.COM     uint16_t		id)
436*11963SAfshin.Ardakani@Sun.COM {
437*11963SAfshin.Ardakani@Sun.COM 	ASSERT(pool->id_magic == SMB_IDPOOL_MAGIC);
438*11963SAfshin.Ardakani@Sun.COM 	ASSERT(id != 0);
439*11963SAfshin.Ardakani@Sun.COM 	ASSERT(id != 0xFFFF);
440*11963SAfshin.Ardakani@Sun.COM 
441*11963SAfshin.Ardakani@Sun.COM 	mutex_enter(&pool->id_mutex);
442*11963SAfshin.Ardakani@Sun.COM 	if (pool->id_pool[id >> 3] & (1 << (id & 7))) {
443*11963SAfshin.Ardakani@Sun.COM 		pool->id_pool[id >> 3] &= ~(1 << (id & 7));
444*11963SAfshin.Ardakani@Sun.COM 		pool->id_free_counter++;
445*11963SAfshin.Ardakani@Sun.COM 		ASSERT(pool->id_free_counter <= pool->id_max_free_counter);
446*11963SAfshin.Ardakani@Sun.COM 		mutex_exit(&pool->id_mutex);
447*11963SAfshin.Ardakani@Sun.COM 		return;
448*11963SAfshin.Ardakani@Sun.COM 	}
449*11963SAfshin.Ardakani@Sun.COM 	/* Freeing a free ID. */
450*11963SAfshin.Ardakani@Sun.COM 	ASSERT(0);
451*11963SAfshin.Ardakani@Sun.COM 	mutex_exit(&pool->id_mutex);
452*11963SAfshin.Ardakani@Sun.COM }
453*11963SAfshin.Ardakani@Sun.COM 
454*11963SAfshin.Ardakani@Sun.COM /*
455*11963SAfshin.Ardakani@Sun.COM  * Initialize the llist delete queue object cache.
456*11963SAfshin.Ardakani@Sun.COM  */
457*11963SAfshin.Ardakani@Sun.COM void
458*11963SAfshin.Ardakani@Sun.COM smb_llist_init(void)
459*11963SAfshin.Ardakani@Sun.COM {
460*11963SAfshin.Ardakani@Sun.COM 	if (smb_llist_initialized)
461*11963SAfshin.Ardakani@Sun.COM 		return;
462*11963SAfshin.Ardakani@Sun.COM 
463*11963SAfshin.Ardakani@Sun.COM 	smb_dtor_cache = kmem_cache_create("smb_dtor_cache",
464*11963SAfshin.Ardakani@Sun.COM 	    sizeof (smb_dtor_t), 8, NULL, NULL, NULL, NULL, NULL, 0);
465*11963SAfshin.Ardakani@Sun.COM 
466*11963SAfshin.Ardakani@Sun.COM 	smb_llist_initialized = B_TRUE;
467*11963SAfshin.Ardakani@Sun.COM }
468*11963SAfshin.Ardakani@Sun.COM 
469*11963SAfshin.Ardakani@Sun.COM /*
470*11963SAfshin.Ardakani@Sun.COM  * Destroy the llist delete queue object cache.
471*11963SAfshin.Ardakani@Sun.COM  */
472*11963SAfshin.Ardakani@Sun.COM void
473*11963SAfshin.Ardakani@Sun.COM smb_llist_fini(void)
474*11963SAfshin.Ardakani@Sun.COM {
475*11963SAfshin.Ardakani@Sun.COM 	if (!smb_llist_initialized)
476*11963SAfshin.Ardakani@Sun.COM 		return;
477*11963SAfshin.Ardakani@Sun.COM 
478*11963SAfshin.Ardakani@Sun.COM 	kmem_cache_destroy(smb_dtor_cache);
479*11963SAfshin.Ardakani@Sun.COM 	smb_llist_initialized = B_FALSE;
480*11963SAfshin.Ardakani@Sun.COM }
481*11963SAfshin.Ardakani@Sun.COM 
482*11963SAfshin.Ardakani@Sun.COM /*
483*11963SAfshin.Ardakani@Sun.COM  * smb_llist_constructor
484*11963SAfshin.Ardakani@Sun.COM  *
485*11963SAfshin.Ardakani@Sun.COM  * This function initializes a locked list.
486*11963SAfshin.Ardakani@Sun.COM  */
487*11963SAfshin.Ardakani@Sun.COM void
488*11963SAfshin.Ardakani@Sun.COM smb_llist_constructor(
489*11963SAfshin.Ardakani@Sun.COM     smb_llist_t	*ll,
490*11963SAfshin.Ardakani@Sun.COM     size_t	size,
491*11963SAfshin.Ardakani@Sun.COM     size_t	offset)
492*11963SAfshin.Ardakani@Sun.COM {
493*11963SAfshin.Ardakani@Sun.COM 	rw_init(&ll->ll_lock, NULL, RW_DEFAULT, NULL);
494*11963SAfshin.Ardakani@Sun.COM 	mutex_init(&ll->ll_mutex, NULL, MUTEX_DEFAULT, NULL);
495*11963SAfshin.Ardakani@Sun.COM 	list_create(&ll->ll_list, size, offset);
496*11963SAfshin.Ardakani@Sun.COM 	list_create(&ll->ll_deleteq, sizeof (smb_dtor_t),
497*11963SAfshin.Ardakani@Sun.COM 	    offsetof(smb_dtor_t, dt_lnd));
498*11963SAfshin.Ardakani@Sun.COM 	ll->ll_count = 0;
499*11963SAfshin.Ardakani@Sun.COM 	ll->ll_wrop = 0;
500*11963SAfshin.Ardakani@Sun.COM 	ll->ll_deleteq_count = 0;
501*11963SAfshin.Ardakani@Sun.COM }
502*11963SAfshin.Ardakani@Sun.COM 
503*11963SAfshin.Ardakani@Sun.COM /*
504*11963SAfshin.Ardakani@Sun.COM  * Flush the delete queue and destroy a locked list.
505*11963SAfshin.Ardakani@Sun.COM  */
506*11963SAfshin.Ardakani@Sun.COM void
507*11963SAfshin.Ardakani@Sun.COM smb_llist_destructor(
508*11963SAfshin.Ardakani@Sun.COM     smb_llist_t	*ll)
509*11963SAfshin.Ardakani@Sun.COM {
510*11963SAfshin.Ardakani@Sun.COM 	smb_llist_flush(ll);
511*11963SAfshin.Ardakani@Sun.COM 
512*11963SAfshin.Ardakani@Sun.COM 	ASSERT(ll->ll_count == 0);
513*11963SAfshin.Ardakani@Sun.COM 	ASSERT(ll->ll_deleteq_count == 0);
514*11963SAfshin.Ardakani@Sun.COM 
515*11963SAfshin.Ardakani@Sun.COM 	rw_destroy(&ll->ll_lock);
516*11963SAfshin.Ardakani@Sun.COM 	list_destroy(&ll->ll_list);
517*11963SAfshin.Ardakani@Sun.COM 	list_destroy(&ll->ll_deleteq);
518*11963SAfshin.Ardakani@Sun.COM 	mutex_destroy(&ll->ll_mutex);
519*11963SAfshin.Ardakani@Sun.COM }
520*11963SAfshin.Ardakani@Sun.COM 
521*11963SAfshin.Ardakani@Sun.COM /*
522*11963SAfshin.Ardakani@Sun.COM  * Post an object to the delete queue.  The delete queue will be processed
523*11963SAfshin.Ardakani@Sun.COM  * during list exit or list destruction.  Objects are often posted for
524*11963SAfshin.Ardakani@Sun.COM  * deletion during list iteration (while the list is locked) but that is
525*11963SAfshin.Ardakani@Sun.COM  * not required, and an object can be posted at any time.
526*11963SAfshin.Ardakani@Sun.COM  */
527*11963SAfshin.Ardakani@Sun.COM void
528*11963SAfshin.Ardakani@Sun.COM smb_llist_post(smb_llist_t *ll, void *object, smb_dtorproc_t dtorproc)
529*11963SAfshin.Ardakani@Sun.COM {
530*11963SAfshin.Ardakani@Sun.COM 	smb_dtor_t	*dtor;
531*11963SAfshin.Ardakani@Sun.COM 
532*11963SAfshin.Ardakani@Sun.COM 	ASSERT((object != NULL) && (dtorproc != NULL));
533*11963SAfshin.Ardakani@Sun.COM 
534*11963SAfshin.Ardakani@Sun.COM 	dtor = kmem_cache_alloc(smb_dtor_cache, KM_SLEEP);
535*11963SAfshin.Ardakani@Sun.COM 	bzero(dtor, sizeof (smb_dtor_t));
536*11963SAfshin.Ardakani@Sun.COM 	dtor->dt_magic = SMB_DTOR_MAGIC;
537*11963SAfshin.Ardakani@Sun.COM 	dtor->dt_object = object;
538*11963SAfshin.Ardakani@Sun.COM 	dtor->dt_proc = dtorproc;
539*11963SAfshin.Ardakani@Sun.COM 
540*11963SAfshin.Ardakani@Sun.COM 	mutex_enter(&ll->ll_mutex);
541*11963SAfshin.Ardakani@Sun.COM 	list_insert_tail(&ll->ll_deleteq, dtor);
542*11963SAfshin.Ardakani@Sun.COM 	++ll->ll_deleteq_count;
543*11963SAfshin.Ardakani@Sun.COM 	mutex_exit(&ll->ll_mutex);
544*11963SAfshin.Ardakani@Sun.COM }
545*11963SAfshin.Ardakani@Sun.COM 
546*11963SAfshin.Ardakani@Sun.COM /*
547*11963SAfshin.Ardakani@Sun.COM  * Exit the list lock and process the delete queue.
548*11963SAfshin.Ardakani@Sun.COM  */
549*11963SAfshin.Ardakani@Sun.COM void
550*11963SAfshin.Ardakani@Sun.COM smb_llist_exit(smb_llist_t *ll)
551*11963SAfshin.Ardakani@Sun.COM {
552*11963SAfshin.Ardakani@Sun.COM 	rw_exit(&ll->ll_lock);
553*11963SAfshin.Ardakani@Sun.COM 	smb_llist_flush(ll);
554*11963SAfshin.Ardakani@Sun.COM }
555*11963SAfshin.Ardakani@Sun.COM 
556*11963SAfshin.Ardakani@Sun.COM /*
557*11963SAfshin.Ardakani@Sun.COM  * Flush the list delete queue.  The mutex is dropped across the destructor
558*11963SAfshin.Ardakani@Sun.COM  * call in case this leads to additional objects being posted to the delete
559*11963SAfshin.Ardakani@Sun.COM  * queue.
560*11963SAfshin.Ardakani@Sun.COM  */
561*11963SAfshin.Ardakani@Sun.COM static void
562*11963SAfshin.Ardakani@Sun.COM smb_llist_flush(smb_llist_t *ll)
563*11963SAfshin.Ardakani@Sun.COM {
564*11963SAfshin.Ardakani@Sun.COM 	smb_dtor_t    *dtor;
565*11963SAfshin.Ardakani@Sun.COM 
566*11963SAfshin.Ardakani@Sun.COM 	mutex_enter(&ll->ll_mutex);
567*11963SAfshin.Ardakani@Sun.COM 
568*11963SAfshin.Ardakani@Sun.COM 	dtor = list_head(&ll->ll_deleteq);
569*11963SAfshin.Ardakani@Sun.COM 	while (dtor != NULL) {
570*11963SAfshin.Ardakani@Sun.COM 		SMB_DTOR_VALID(dtor);
571*11963SAfshin.Ardakani@Sun.COM 		ASSERT((dtor->dt_object != NULL) && (dtor->dt_proc != NULL));
572*11963SAfshin.Ardakani@Sun.COM 		list_remove(&ll->ll_deleteq, dtor);
573*11963SAfshin.Ardakani@Sun.COM 		--ll->ll_deleteq_count;
574*11963SAfshin.Ardakani@Sun.COM 		mutex_exit(&ll->ll_mutex);
575*11963SAfshin.Ardakani@Sun.COM 
576*11963SAfshin.Ardakani@Sun.COM 		dtor->dt_proc(dtor->dt_object);
577*11963SAfshin.Ardakani@Sun.COM 
578*11963SAfshin.Ardakani@Sun.COM 		dtor->dt_magic = (uint32_t)~SMB_DTOR_MAGIC;
579*11963SAfshin.Ardakani@Sun.COM 		kmem_cache_free(smb_dtor_cache, dtor);
580*11963SAfshin.Ardakani@Sun.COM 		mutex_enter(&ll->ll_mutex);
581*11963SAfshin.Ardakani@Sun.COM 		dtor = list_head(&ll->ll_deleteq);
582*11963SAfshin.Ardakani@Sun.COM 	}
583*11963SAfshin.Ardakani@Sun.COM 
584*11963SAfshin.Ardakani@Sun.COM 	mutex_exit(&ll->ll_mutex);
585*11963SAfshin.Ardakani@Sun.COM }
586*11963SAfshin.Ardakani@Sun.COM 
587*11963SAfshin.Ardakani@Sun.COM /*
588*11963SAfshin.Ardakani@Sun.COM  * smb_llist_upgrade
589*11963SAfshin.Ardakani@Sun.COM  *
590*11963SAfshin.Ardakani@Sun.COM  * This function tries to upgrade the lock of the locked list. It assumes the
591*11963SAfshin.Ardakani@Sun.COM  * locked has already been entered in RW_READER mode. It first tries using the
592*11963SAfshin.Ardakani@Sun.COM  * Solaris function rw_tryupgrade(). If that call fails the lock is released
593*11963SAfshin.Ardakani@Sun.COM  * and reentered in RW_WRITER mode. In that last case a window is opened during
594*11963SAfshin.Ardakani@Sun.COM  * which the contents of the list may have changed. The return code indicates
595*11963SAfshin.Ardakani@Sun.COM  * whether or not the list was modified when the lock was exited.
596*11963SAfshin.Ardakani@Sun.COM  */
597*11963SAfshin.Ardakani@Sun.COM int smb_llist_upgrade(
598*11963SAfshin.Ardakani@Sun.COM     smb_llist_t *ll)
599*11963SAfshin.Ardakani@Sun.COM {
600*11963SAfshin.Ardakani@Sun.COM 	uint64_t	wrop;
601*11963SAfshin.Ardakani@Sun.COM 
602*11963SAfshin.Ardakani@Sun.COM 	if (rw_tryupgrade(&ll->ll_lock) != 0) {
603*11963SAfshin.Ardakani@Sun.COM 		return (0);
604*11963SAfshin.Ardakani@Sun.COM 	}
605*11963SAfshin.Ardakani@Sun.COM 	wrop = ll->ll_wrop;
606*11963SAfshin.Ardakani@Sun.COM 	rw_exit(&ll->ll_lock);
607*11963SAfshin.Ardakani@Sun.COM 	rw_enter(&ll->ll_lock, RW_WRITER);
608*11963SAfshin.Ardakani@Sun.COM 	return (wrop != ll->ll_wrop);
609*11963SAfshin.Ardakani@Sun.COM }
610*11963SAfshin.Ardakani@Sun.COM 
611*11963SAfshin.Ardakani@Sun.COM /*
612*11963SAfshin.Ardakani@Sun.COM  * smb_llist_insert_head
613*11963SAfshin.Ardakani@Sun.COM  *
614*11963SAfshin.Ardakani@Sun.COM  * This function inserts the object passed a the beginning of the list. This
615*11963SAfshin.Ardakani@Sun.COM  * function assumes the lock of the list has already been entered.
616*11963SAfshin.Ardakani@Sun.COM  */
617*11963SAfshin.Ardakani@Sun.COM void
618*11963SAfshin.Ardakani@Sun.COM smb_llist_insert_head(
619*11963SAfshin.Ardakani@Sun.COM     smb_llist_t	*ll,
620*11963SAfshin.Ardakani@Sun.COM     void	*obj)
621*11963SAfshin.Ardakani@Sun.COM {
622*11963SAfshin.Ardakani@Sun.COM 	list_insert_head(&ll->ll_list, obj);
623*11963SAfshin.Ardakani@Sun.COM 	++ll->ll_wrop;
624*11963SAfshin.Ardakani@Sun.COM 	++ll->ll_count;
625*11963SAfshin.Ardakani@Sun.COM }
626*11963SAfshin.Ardakani@Sun.COM 
627*11963SAfshin.Ardakani@Sun.COM /*
628*11963SAfshin.Ardakani@Sun.COM  * smb_llist_insert_tail
629*11963SAfshin.Ardakani@Sun.COM  *
630*11963SAfshin.Ardakani@Sun.COM  * This function appends to the object passed to the list. This function assumes
631*11963SAfshin.Ardakani@Sun.COM  * the lock of the list has already been entered.
632*11963SAfshin.Ardakani@Sun.COM  *
633*11963SAfshin.Ardakani@Sun.COM  */
634*11963SAfshin.Ardakani@Sun.COM void
635*11963SAfshin.Ardakani@Sun.COM smb_llist_insert_tail(
636*11963SAfshin.Ardakani@Sun.COM     smb_llist_t	*ll,
637*11963SAfshin.Ardakani@Sun.COM     void	*obj)
638*11963SAfshin.Ardakani@Sun.COM {
639*11963SAfshin.Ardakani@Sun.COM 	list_insert_tail(&ll->ll_list, obj);
640*11963SAfshin.Ardakani@Sun.COM 	++ll->ll_wrop;
641*11963SAfshin.Ardakani@Sun.COM 	++ll->ll_count;
642*11963SAfshin.Ardakani@Sun.COM }
643*11963SAfshin.Ardakani@Sun.COM 
644*11963SAfshin.Ardakani@Sun.COM /*
645*11963SAfshin.Ardakani@Sun.COM  * smb_llist_remove
646*11963SAfshin.Ardakani@Sun.COM  *
647*11963SAfshin.Ardakani@Sun.COM  * This function removes the object passed from the list. This function assumes
648*11963SAfshin.Ardakani@Sun.COM  * the lock of the list has already been entered.
649*11963SAfshin.Ardakani@Sun.COM  */
650*11963SAfshin.Ardakani@Sun.COM void
651*11963SAfshin.Ardakani@Sun.COM smb_llist_remove(
652*11963SAfshin.Ardakani@Sun.COM     smb_llist_t	*ll,
653*11963SAfshin.Ardakani@Sun.COM     void	*obj)
654*11963SAfshin.Ardakani@Sun.COM {
655*11963SAfshin.Ardakani@Sun.COM 	list_remove(&ll->ll_list, obj);
656*11963SAfshin.Ardakani@Sun.COM 	++ll->ll_wrop;
657*11963SAfshin.Ardakani@Sun.COM 	--ll->ll_count;
658*11963SAfshin.Ardakani@Sun.COM }
659*11963SAfshin.Ardakani@Sun.COM 
660*11963SAfshin.Ardakani@Sun.COM /*
661*11963SAfshin.Ardakani@Sun.COM  * smb_llist_get_count
662*11963SAfshin.Ardakani@Sun.COM  *
663*11963SAfshin.Ardakani@Sun.COM  * This function returns the number of elements in the specified list.
664*11963SAfshin.Ardakani@Sun.COM  */
665*11963SAfshin.Ardakani@Sun.COM uint32_t
666*11963SAfshin.Ardakani@Sun.COM smb_llist_get_count(
667*11963SAfshin.Ardakani@Sun.COM     smb_llist_t *ll)
668*11963SAfshin.Ardakani@Sun.COM {
669*11963SAfshin.Ardakani@Sun.COM 	return (ll->ll_count);
670*11963SAfshin.Ardakani@Sun.COM }
671*11963SAfshin.Ardakani@Sun.COM 
672*11963SAfshin.Ardakani@Sun.COM /*
673*11963SAfshin.Ardakani@Sun.COM  * smb_slist_constructor
674*11963SAfshin.Ardakani@Sun.COM  *
675*11963SAfshin.Ardakani@Sun.COM  * Synchronized list constructor.
676*11963SAfshin.Ardakani@Sun.COM  */
677*11963SAfshin.Ardakani@Sun.COM void
678*11963SAfshin.Ardakani@Sun.COM smb_slist_constructor(
679*11963SAfshin.Ardakani@Sun.COM     smb_slist_t	*sl,
680*11963SAfshin.Ardakani@Sun.COM     size_t	size,
681*11963SAfshin.Ardakani@Sun.COM     size_t	offset)
682*11963SAfshin.Ardakani@Sun.COM {
683*11963SAfshin.Ardakani@Sun.COM 	mutex_init(&sl->sl_mutex, NULL, MUTEX_DEFAULT, NULL);
684*11963SAfshin.Ardakani@Sun.COM 	cv_init(&sl->sl_cv, NULL, CV_DEFAULT, NULL);
685*11963SAfshin.Ardakani@Sun.COM 	list_create(&sl->sl_list, size, offset);
686*11963SAfshin.Ardakani@Sun.COM 	sl->sl_count = 0;
687*11963SAfshin.Ardakani@Sun.COM 	sl->sl_waiting = B_FALSE;
688*11963SAfshin.Ardakani@Sun.COM }
689*11963SAfshin.Ardakani@Sun.COM 
690*11963SAfshin.Ardakani@Sun.COM /*
691*11963SAfshin.Ardakani@Sun.COM  * smb_slist_destructor
692*11963SAfshin.Ardakani@Sun.COM  *
693*11963SAfshin.Ardakani@Sun.COM  * Synchronized list destructor.
694*11963SAfshin.Ardakani@Sun.COM  */
695*11963SAfshin.Ardakani@Sun.COM void
696*11963SAfshin.Ardakani@Sun.COM smb_slist_destructor(
697*11963SAfshin.Ardakani@Sun.COM     smb_slist_t	*sl)
698*11963SAfshin.Ardakani@Sun.COM {
699*11963SAfshin.Ardakani@Sun.COM 	ASSERT(sl->sl_count == 0);
700*11963SAfshin.Ardakani@Sun.COM 
701*11963SAfshin.Ardakani@Sun.COM 	mutex_destroy(&sl->sl_mutex);
702*11963SAfshin.Ardakani@Sun.COM 	cv_destroy(&sl->sl_cv);
703*11963SAfshin.Ardakani@Sun.COM 	list_destroy(&sl->sl_list);
704*11963SAfshin.Ardakani@Sun.COM }
705*11963SAfshin.Ardakani@Sun.COM 
706*11963SAfshin.Ardakani@Sun.COM /*
707*11963SAfshin.Ardakani@Sun.COM  * smb_slist_insert_head
708*11963SAfshin.Ardakani@Sun.COM  *
709*11963SAfshin.Ardakani@Sun.COM  * This function inserts the object passed a the beginning of the list.
710*11963SAfshin.Ardakani@Sun.COM  */
711*11963SAfshin.Ardakani@Sun.COM void
712*11963SAfshin.Ardakani@Sun.COM smb_slist_insert_head(
713*11963SAfshin.Ardakani@Sun.COM     smb_slist_t	*sl,
714*11963SAfshin.Ardakani@Sun.COM     void	*obj)
715*11963SAfshin.Ardakani@Sun.COM {
716*11963SAfshin.Ardakani@Sun.COM 	mutex_enter(&sl->sl_mutex);
717*11963SAfshin.Ardakani@Sun.COM 	list_insert_head(&sl->sl_list, obj);
718*11963SAfshin.Ardakani@Sun.COM 	++sl->sl_count;
719*11963SAfshin.Ardakani@Sun.COM 	mutex_exit(&sl->sl_mutex);
720*11963SAfshin.Ardakani@Sun.COM }
721*11963SAfshin.Ardakani@Sun.COM 
722*11963SAfshin.Ardakani@Sun.COM /*
723*11963SAfshin.Ardakani@Sun.COM  * smb_slist_insert_tail
724*11963SAfshin.Ardakani@Sun.COM  *
725*11963SAfshin.Ardakani@Sun.COM  * This function appends the object passed to the list.
726*11963SAfshin.Ardakani@Sun.COM  */
727*11963SAfshin.Ardakani@Sun.COM void
728*11963SAfshin.Ardakani@Sun.COM smb_slist_insert_tail(
729*11963SAfshin.Ardakani@Sun.COM     smb_slist_t	*sl,
730*11963SAfshin.Ardakani@Sun.COM     void	*obj)
731*11963SAfshin.Ardakani@Sun.COM {
732*11963SAfshin.Ardakani@Sun.COM 	mutex_enter(&sl->sl_mutex);
733*11963SAfshin.Ardakani@Sun.COM 	list_insert_tail(&sl->sl_list, obj);
734*11963SAfshin.Ardakani@Sun.COM 	++sl->sl_count;
735*11963SAfshin.Ardakani@Sun.COM 	mutex_exit(&sl->sl_mutex);
736*11963SAfshin.Ardakani@Sun.COM }
737*11963SAfshin.Ardakani@Sun.COM 
738*11963SAfshin.Ardakani@Sun.COM /*
739*11963SAfshin.Ardakani@Sun.COM  * smb_llist_remove
740*11963SAfshin.Ardakani@Sun.COM  *
741*11963SAfshin.Ardakani@Sun.COM  * This function removes the object passed by the caller from the list.
742*11963SAfshin.Ardakani@Sun.COM  */
743*11963SAfshin.Ardakani@Sun.COM void
744*11963SAfshin.Ardakani@Sun.COM smb_slist_remove(
745*11963SAfshin.Ardakani@Sun.COM     smb_slist_t	*sl,
746*11963SAfshin.Ardakani@Sun.COM     void	*obj)
747*11963SAfshin.Ardakani@Sun.COM {
748*11963SAfshin.Ardakani@Sun.COM 	mutex_enter(&sl->sl_mutex);
749*11963SAfshin.Ardakani@Sun.COM 	list_remove(&sl->sl_list, obj);
750*11963SAfshin.Ardakani@Sun.COM 	if ((--sl->sl_count == 0) && (sl->sl_waiting)) {
751*11963SAfshin.Ardakani@Sun.COM 		sl->sl_waiting = B_FALSE;
752*11963SAfshin.Ardakani@Sun.COM 		cv_broadcast(&sl->sl_cv);
753*11963SAfshin.Ardakani@Sun.COM 	}
754*11963SAfshin.Ardakani@Sun.COM 	mutex_exit(&sl->sl_mutex);
755*11963SAfshin.Ardakani@Sun.COM }
756*11963SAfshin.Ardakani@Sun.COM 
757*11963SAfshin.Ardakani@Sun.COM /*
758*11963SAfshin.Ardakani@Sun.COM  * smb_slist_move_tail
759*11963SAfshin.Ardakani@Sun.COM  *
760*11963SAfshin.Ardakani@Sun.COM  * This function transfers all the contents of the synchronized list to the
761*11963SAfshin.Ardakani@Sun.COM  * list_t provided. It returns the number of objects transferred.
762*11963SAfshin.Ardakani@Sun.COM  */
763*11963SAfshin.Ardakani@Sun.COM uint32_t
764*11963SAfshin.Ardakani@Sun.COM smb_slist_move_tail(
765*11963SAfshin.Ardakani@Sun.COM     list_t	*lst,
766*11963SAfshin.Ardakani@Sun.COM     smb_slist_t	*sl)
767*11963SAfshin.Ardakani@Sun.COM {
768*11963SAfshin.Ardakani@Sun.COM 	uint32_t	rv;
769*11963SAfshin.Ardakani@Sun.COM 
770*11963SAfshin.Ardakani@Sun.COM 	mutex_enter(&sl->sl_mutex);
771*11963SAfshin.Ardakani@Sun.COM 	rv = sl->sl_count;
772*11963SAfshin.Ardakani@Sun.COM 	if (sl->sl_count) {
773*11963SAfshin.Ardakani@Sun.COM 		list_move_tail(lst, &sl->sl_list);
774*11963SAfshin.Ardakani@Sun.COM 		sl->sl_count = 0;
775*11963SAfshin.Ardakani@Sun.COM 		if (sl->sl_waiting) {
776*11963SAfshin.Ardakani@Sun.COM 			sl->sl_waiting = B_FALSE;
777*11963SAfshin.Ardakani@Sun.COM 			cv_broadcast(&sl->sl_cv);
778*11963SAfshin.Ardakani@Sun.COM 		}
779*11963SAfshin.Ardakani@Sun.COM 	}
780*11963SAfshin.Ardakani@Sun.COM 	mutex_exit(&sl->sl_mutex);
781*11963SAfshin.Ardakani@Sun.COM 	return (rv);
782*11963SAfshin.Ardakani@Sun.COM }
783*11963SAfshin.Ardakani@Sun.COM 
784*11963SAfshin.Ardakani@Sun.COM /*
785*11963SAfshin.Ardakani@Sun.COM  * smb_slist_obj_move
786*11963SAfshin.Ardakani@Sun.COM  *
787*11963SAfshin.Ardakani@Sun.COM  * This function moves an object from one list to the end of the other list. It
788*11963SAfshin.Ardakani@Sun.COM  * assumes the mutex of each list has been entered.
789*11963SAfshin.Ardakani@Sun.COM  */
790*11963SAfshin.Ardakani@Sun.COM void
791*11963SAfshin.Ardakani@Sun.COM smb_slist_obj_move(
792*11963SAfshin.Ardakani@Sun.COM     smb_slist_t	*dst,
793*11963SAfshin.Ardakani@Sun.COM     smb_slist_t	*src,
794*11963SAfshin.Ardakani@Sun.COM     void	*obj)
795*11963SAfshin.Ardakani@Sun.COM {
796*11963SAfshin.Ardakani@Sun.COM 	ASSERT(dst->sl_list.list_offset == src->sl_list.list_offset);
797*11963SAfshin.Ardakani@Sun.COM 	ASSERT(dst->sl_list.list_size == src->sl_list.list_size);
798*11963SAfshin.Ardakani@Sun.COM 
799*11963SAfshin.Ardakani@Sun.COM 	list_remove(&src->sl_list, obj);
800*11963SAfshin.Ardakani@Sun.COM 	list_insert_tail(&dst->sl_list, obj);
801*11963SAfshin.Ardakani@Sun.COM 	dst->sl_count++;
802*11963SAfshin.Ardakani@Sun.COM 	src->sl_count--;
803*11963SAfshin.Ardakani@Sun.COM 	if ((src->sl_count == 0) && (src->sl_waiting)) {
804*11963SAfshin.Ardakani@Sun.COM 		src->sl_waiting = B_FALSE;
805*11963SAfshin.Ardakani@Sun.COM 		cv_broadcast(&src->sl_cv);
806*11963SAfshin.Ardakani@Sun.COM 	}
807*11963SAfshin.Ardakani@Sun.COM }
808*11963SAfshin.Ardakani@Sun.COM 
809*11963SAfshin.Ardakani@Sun.COM /*
810*11963SAfshin.Ardakani@Sun.COM  * smb_slist_wait_for_empty
811*11963SAfshin.Ardakani@Sun.COM  *
812*11963SAfshin.Ardakani@Sun.COM  * This function waits for a list to be emptied.
813*11963SAfshin.Ardakani@Sun.COM  */
814*11963SAfshin.Ardakani@Sun.COM void
815*11963SAfshin.Ardakani@Sun.COM smb_slist_wait_for_empty(
816*11963SAfshin.Ardakani@Sun.COM     smb_slist_t	*sl)
817*11963SAfshin.Ardakani@Sun.COM {
818*11963SAfshin.Ardakani@Sun.COM 	mutex_enter(&sl->sl_mutex);
819*11963SAfshin.Ardakani@Sun.COM 	while (sl->sl_count) {
820*11963SAfshin.Ardakani@Sun.COM 		sl->sl_waiting = B_TRUE;
821*11963SAfshin.Ardakani@Sun.COM 		cv_wait(&sl->sl_cv, &sl->sl_mutex);
822*11963SAfshin.Ardakani@Sun.COM 	}
823*11963SAfshin.Ardakani@Sun.COM 	mutex_exit(&sl->sl_mutex);
824*11963SAfshin.Ardakani@Sun.COM }
825*11963SAfshin.Ardakani@Sun.COM 
826*11963SAfshin.Ardakani@Sun.COM /*
827*11963SAfshin.Ardakani@Sun.COM  * smb_slist_exit
828*11963SAfshin.Ardakani@Sun.COM  *
829*11963SAfshin.Ardakani@Sun.COM  * This function exits the muetx of the list and signal the condition variable
830*11963SAfshin.Ardakani@Sun.COM  * if the list is empty.
831*11963SAfshin.Ardakani@Sun.COM  */
832*11963SAfshin.Ardakani@Sun.COM void
833*11963SAfshin.Ardakani@Sun.COM smb_slist_exit(smb_slist_t *sl)
834*11963SAfshin.Ardakani@Sun.COM {
835*11963SAfshin.Ardakani@Sun.COM 	if ((sl->sl_count == 0) && (sl->sl_waiting)) {
836*11963SAfshin.Ardakani@Sun.COM 		sl->sl_waiting = B_FALSE;
837*11963SAfshin.Ardakani@Sun.COM 		cv_broadcast(&sl->sl_cv);
838*11963SAfshin.Ardakani@Sun.COM 	}
839*11963SAfshin.Ardakani@Sun.COM 	mutex_exit(&sl->sl_mutex);
840*11963SAfshin.Ardakani@Sun.COM }
841*11963SAfshin.Ardakani@Sun.COM 
842*11963SAfshin.Ardakani@Sun.COM /*
843*11963SAfshin.Ardakani@Sun.COM  * smb_thread_entry_point
844*11963SAfshin.Ardakani@Sun.COM  *
845*11963SAfshin.Ardakani@Sun.COM  * Common entry point for all the threads created through smb_thread_start.
846*11963SAfshin.Ardakani@Sun.COM  * The state of the thread is set to "running" at the beginning and moved to
847*11963SAfshin.Ardakani@Sun.COM  * "exiting" just before calling thread_exit(). The condition variable is
848*11963SAfshin.Ardakani@Sun.COM  *  also signaled.
849*11963SAfshin.Ardakani@Sun.COM  */
850*11963SAfshin.Ardakani@Sun.COM static void
851*11963SAfshin.Ardakani@Sun.COM smb_thread_entry_point(
852*11963SAfshin.Ardakani@Sun.COM     smb_thread_t	*thread)
853*11963SAfshin.Ardakani@Sun.COM {
854*11963SAfshin.Ardakani@Sun.COM 	ASSERT(thread->sth_magic == SMB_THREAD_MAGIC);
855*11963SAfshin.Ardakani@Sun.COM 	mutex_enter(&thread->sth_mtx);
856*11963SAfshin.Ardakani@Sun.COM 	ASSERT(thread->sth_state == SMB_THREAD_STATE_STARTING);
857*11963SAfshin.Ardakani@Sun.COM 	thread->sth_th = curthread;
858*11963SAfshin.Ardakani@Sun.COM 	thread->sth_did = thread->sth_th->t_did;
859*11963SAfshin.Ardakani@Sun.COM 
860*11963SAfshin.Ardakani@Sun.COM 	if (!thread->sth_kill) {
861*11963SAfshin.Ardakani@Sun.COM 		thread->sth_state = SMB_THREAD_STATE_RUNNING;
862*11963SAfshin.Ardakani@Sun.COM 		cv_signal(&thread->sth_cv);
863*11963SAfshin.Ardakani@Sun.COM 		mutex_exit(&thread->sth_mtx);
864*11963SAfshin.Ardakani@Sun.COM 		thread->sth_ep(thread, thread->sth_ep_arg);
865*11963SAfshin.Ardakani@Sun.COM 		mutex_enter(&thread->sth_mtx);
866*11963SAfshin.Ardakani@Sun.COM 	}
867*11963SAfshin.Ardakani@Sun.COM 	thread->sth_th = NULL;
868*11963SAfshin.Ardakani@Sun.COM 	thread->sth_state = SMB_THREAD_STATE_EXITING;
869*11963SAfshin.Ardakani@Sun.COM 	cv_broadcast(&thread->sth_cv);
870*11963SAfshin.Ardakani@Sun.COM 	mutex_exit(&thread->sth_mtx);
871*11963SAfshin.Ardakani@Sun.COM 	thread_exit();
872*11963SAfshin.Ardakani@Sun.COM }
873*11963SAfshin.Ardakani@Sun.COM 
874*11963SAfshin.Ardakani@Sun.COM /*
875*11963SAfshin.Ardakani@Sun.COM  * smb_thread_init
876*11963SAfshin.Ardakani@Sun.COM  */
877*11963SAfshin.Ardakani@Sun.COM void
878*11963SAfshin.Ardakani@Sun.COM smb_thread_init(
879*11963SAfshin.Ardakani@Sun.COM     smb_thread_t	*thread,
880*11963SAfshin.Ardakani@Sun.COM     char		*name,
881*11963SAfshin.Ardakani@Sun.COM     smb_thread_ep_t	ep,
882*11963SAfshin.Ardakani@Sun.COM     void		*ep_arg,
883*11963SAfshin.Ardakani@Sun.COM     smb_thread_aw_t	aw,
884*11963SAfshin.Ardakani@Sun.COM     void		*aw_arg)
885*11963SAfshin.Ardakani@Sun.COM {
886*11963SAfshin.Ardakani@Sun.COM 	ASSERT(thread->sth_magic != SMB_THREAD_MAGIC);
887*11963SAfshin.Ardakani@Sun.COM 
888*11963SAfshin.Ardakani@Sun.COM 	bzero(thread, sizeof (*thread));
889*11963SAfshin.Ardakani@Sun.COM 
890*11963SAfshin.Ardakani@Sun.COM 	(void) strlcpy(thread->sth_name, name, sizeof (thread->sth_name));
891*11963SAfshin.Ardakani@Sun.COM 	thread->sth_ep = ep;
892*11963SAfshin.Ardakani@Sun.COM 	thread->sth_ep_arg = ep_arg;
893*11963SAfshin.Ardakani@Sun.COM 	thread->sth_aw = aw;
894*11963SAfshin.Ardakani@Sun.COM 	thread->sth_aw_arg = aw_arg;
895*11963SAfshin.Ardakani@Sun.COM 	thread->sth_state = SMB_THREAD_STATE_EXITED;
896*11963SAfshin.Ardakani@Sun.COM 	mutex_init(&thread->sth_mtx, NULL, MUTEX_DEFAULT, NULL);
897*11963SAfshin.Ardakani@Sun.COM 	cv_init(&thread->sth_cv, NULL, CV_DEFAULT, NULL);
898*11963SAfshin.Ardakani@Sun.COM 	thread->sth_magic = SMB_THREAD_MAGIC;
899*11963SAfshin.Ardakani@Sun.COM }
900*11963SAfshin.Ardakani@Sun.COM 
901*11963SAfshin.Ardakani@Sun.COM /*
902*11963SAfshin.Ardakani@Sun.COM  * smb_thread_destroy
903*11963SAfshin.Ardakani@Sun.COM  */
904*11963SAfshin.Ardakani@Sun.COM void
905*11963SAfshin.Ardakani@Sun.COM smb_thread_destroy(
906*11963SAfshin.Ardakani@Sun.COM     smb_thread_t	*thread)
907*11963SAfshin.Ardakani@Sun.COM {
908*11963SAfshin.Ardakani@Sun.COM 	ASSERT(thread->sth_magic == SMB_THREAD_MAGIC);
909*11963SAfshin.Ardakani@Sun.COM 	ASSERT(thread->sth_state == SMB_THREAD_STATE_EXITED);
910*11963SAfshin.Ardakani@Sun.COM 	thread->sth_magic = 0;
911*11963SAfshin.Ardakani@Sun.COM 	mutex_destroy(&thread->sth_mtx);
912*11963SAfshin.Ardakani@Sun.COM 	cv_destroy(&thread->sth_cv);
913*11963SAfshin.Ardakani@Sun.COM }
914*11963SAfshin.Ardakani@Sun.COM 
915*11963SAfshin.Ardakani@Sun.COM /*
916*11963SAfshin.Ardakani@Sun.COM  * smb_thread_start
917*11963SAfshin.Ardakani@Sun.COM  *
918*11963SAfshin.Ardakani@Sun.COM  * This function starts a thread with the parameters provided. It waits until
919*11963SAfshin.Ardakani@Sun.COM  * the state of the thread has been moved to running.
920*11963SAfshin.Ardakani@Sun.COM  */
921*11963SAfshin.Ardakani@Sun.COM /*ARGSUSED*/
922*11963SAfshin.Ardakani@Sun.COM int
923*11963SAfshin.Ardakani@Sun.COM smb_thread_start(
924*11963SAfshin.Ardakani@Sun.COM     smb_thread_t	*thread)
925*11963SAfshin.Ardakani@Sun.COM {
926*11963SAfshin.Ardakani@Sun.COM 	int		rc = 0;
927*11963SAfshin.Ardakani@Sun.COM 	kthread_t	*tmpthread;
928*11963SAfshin.Ardakani@Sun.COM 
929*11963SAfshin.Ardakani@Sun.COM 	ASSERT(thread->sth_magic == SMB_THREAD_MAGIC);
930*11963SAfshin.Ardakani@Sun.COM 
931*11963SAfshin.Ardakani@Sun.COM 	mutex_enter(&thread->sth_mtx);
932*11963SAfshin.Ardakani@Sun.COM 	switch (thread->sth_state) {
933*11963SAfshin.Ardakani@Sun.COM 	case SMB_THREAD_STATE_EXITED:
934*11963SAfshin.Ardakani@Sun.COM 		thread->sth_state = SMB_THREAD_STATE_STARTING;
935*11963SAfshin.Ardakani@Sun.COM 		mutex_exit(&thread->sth_mtx);
936*11963SAfshin.Ardakani@Sun.COM 		tmpthread = thread_create(NULL, 0, smb_thread_entry_point,
937*11963SAfshin.Ardakani@Sun.COM 		    thread, 0, &p0, TS_RUN, minclsyspri);
938*11963SAfshin.Ardakani@Sun.COM 		ASSERT(tmpthread != NULL);
939*11963SAfshin.Ardakani@Sun.COM 		mutex_enter(&thread->sth_mtx);
940*11963SAfshin.Ardakani@Sun.COM 		while (thread->sth_state == SMB_THREAD_STATE_STARTING)
941*11963SAfshin.Ardakani@Sun.COM 			cv_wait(&thread->sth_cv, &thread->sth_mtx);
942*11963SAfshin.Ardakani@Sun.COM 		if (thread->sth_state != SMB_THREAD_STATE_RUNNING)
943*11963SAfshin.Ardakani@Sun.COM 			rc = -1;
944*11963SAfshin.Ardakani@Sun.COM 		break;
945*11963SAfshin.Ardakani@Sun.COM 	default:
946*11963SAfshin.Ardakani@Sun.COM 		ASSERT(0);
947*11963SAfshin.Ardakani@Sun.COM 		rc = -1;
948*11963SAfshin.Ardakani@Sun.COM 		break;
949*11963SAfshin.Ardakani@Sun.COM 	}
950*11963SAfshin.Ardakani@Sun.COM 	mutex_exit(&thread->sth_mtx);
951*11963SAfshin.Ardakani@Sun.COM 	return (rc);
952*11963SAfshin.Ardakani@Sun.COM }
953*11963SAfshin.Ardakani@Sun.COM 
954*11963SAfshin.Ardakani@Sun.COM /*
955*11963SAfshin.Ardakani@Sun.COM  * smb_thread_stop
956*11963SAfshin.Ardakani@Sun.COM  *
957*11963SAfshin.Ardakani@Sun.COM  * This function signals a thread to kill itself and waits until the "exiting"
958*11963SAfshin.Ardakani@Sun.COM  * state has been reached.
959*11963SAfshin.Ardakani@Sun.COM  */
960*11963SAfshin.Ardakani@Sun.COM void
961*11963SAfshin.Ardakani@Sun.COM smb_thread_stop(
962*11963SAfshin.Ardakani@Sun.COM     smb_thread_t	*thread)
963*11963SAfshin.Ardakani@Sun.COM {
964*11963SAfshin.Ardakani@Sun.COM 	ASSERT(thread->sth_magic == SMB_THREAD_MAGIC);
965*11963SAfshin.Ardakani@Sun.COM 
966*11963SAfshin.Ardakani@Sun.COM 	mutex_enter(&thread->sth_mtx);
967*11963SAfshin.Ardakani@Sun.COM 	switch (thread->sth_state) {
968*11963SAfshin.Ardakani@Sun.COM 	case SMB_THREAD_STATE_RUNNING:
969*11963SAfshin.Ardakani@Sun.COM 	case SMB_THREAD_STATE_STARTING:
970*11963SAfshin.Ardakani@Sun.COM 		if (!thread->sth_kill) {
971*11963SAfshin.Ardakani@Sun.COM 			thread->sth_kill = B_TRUE;
972*11963SAfshin.Ardakani@Sun.COM 			if (thread->sth_aw)
973*11963SAfshin.Ardakani@Sun.COM 				thread->sth_aw(thread, thread->sth_aw_arg);
974*11963SAfshin.Ardakani@Sun.COM 			cv_broadcast(&thread->sth_cv);
975*11963SAfshin.Ardakani@Sun.COM 			while (thread->sth_state != SMB_THREAD_STATE_EXITING)
976*11963SAfshin.Ardakani@Sun.COM 				cv_wait(&thread->sth_cv, &thread->sth_mtx);
977*11963SAfshin.Ardakani@Sun.COM 			mutex_exit(&thread->sth_mtx);
978*11963SAfshin.Ardakani@Sun.COM 			thread_join(thread->sth_did);
979*11963SAfshin.Ardakani@Sun.COM 			mutex_enter(&thread->sth_mtx);
980*11963SAfshin.Ardakani@Sun.COM 			thread->sth_state = SMB_THREAD_STATE_EXITED;
981*11963SAfshin.Ardakani@Sun.COM 			thread->sth_did = 0;
982*11963SAfshin.Ardakani@Sun.COM 			thread->sth_kill = B_FALSE;
983*11963SAfshin.Ardakani@Sun.COM 			cv_broadcast(&thread->sth_cv);
984*11963SAfshin.Ardakani@Sun.COM 			break;
985*11963SAfshin.Ardakani@Sun.COM 		}
986*11963SAfshin.Ardakani@Sun.COM 		/*FALLTHRU*/
987*11963SAfshin.Ardakani@Sun.COM 
988*11963SAfshin.Ardakani@Sun.COM 	case SMB_THREAD_STATE_EXITING:
989*11963SAfshin.Ardakani@Sun.COM 		if (thread->sth_kill) {
990*11963SAfshin.Ardakani@Sun.COM 			while (thread->sth_state != SMB_THREAD_STATE_EXITED)
991*11963SAfshin.Ardakani@Sun.COM 				cv_wait(&thread->sth_cv, &thread->sth_mtx);
992*11963SAfshin.Ardakani@Sun.COM 		} else {
993*11963SAfshin.Ardakani@Sun.COM 			thread->sth_state = SMB_THREAD_STATE_EXITED;
994*11963SAfshin.Ardakani@Sun.COM 			thread->sth_did = 0;
995*11963SAfshin.Ardakani@Sun.COM 		}
996*11963SAfshin.Ardakani@Sun.COM 		break;
997*11963SAfshin.Ardakani@Sun.COM 
998*11963SAfshin.Ardakani@Sun.COM 	case SMB_THREAD_STATE_EXITED:
999*11963SAfshin.Ardakani@Sun.COM 		break;
1000*11963SAfshin.Ardakani@Sun.COM 
1001*11963SAfshin.Ardakani@Sun.COM 	default:
1002*11963SAfshin.Ardakani@Sun.COM 		ASSERT(0);
1003*11963SAfshin.Ardakani@Sun.COM 		break;
1004*11963SAfshin.Ardakani@Sun.COM 	}
1005*11963SAfshin.Ardakani@Sun.COM 	mutex_exit(&thread->sth_mtx);
1006*11963SAfshin.Ardakani@Sun.COM }
1007*11963SAfshin.Ardakani@Sun.COM 
1008*11963SAfshin.Ardakani@Sun.COM /*
1009*11963SAfshin.Ardakani@Sun.COM  * smb_thread_signal
1010*11963SAfshin.Ardakani@Sun.COM  *
1011*11963SAfshin.Ardakani@Sun.COM  * This function signals a thread.
1012*11963SAfshin.Ardakani@Sun.COM  */
1013*11963SAfshin.Ardakani@Sun.COM void
1014*11963SAfshin.Ardakani@Sun.COM smb_thread_signal(
1015*11963SAfshin.Ardakani@Sun.COM     smb_thread_t	*thread)
1016*11963SAfshin.Ardakani@Sun.COM {
1017*11963SAfshin.Ardakani@Sun.COM 	ASSERT(thread->sth_magic == SMB_THREAD_MAGIC);
1018*11963SAfshin.Ardakani@Sun.COM 
1019*11963SAfshin.Ardakani@Sun.COM 	mutex_enter(&thread->sth_mtx);
1020*11963SAfshin.Ardakani@Sun.COM 	switch (thread->sth_state) {
1021*11963SAfshin.Ardakani@Sun.COM 	case SMB_THREAD_STATE_RUNNING:
1022*11963SAfshin.Ardakani@Sun.COM 		if (thread->sth_aw)
1023*11963SAfshin.Ardakani@Sun.COM 			thread->sth_aw(thread, thread->sth_aw_arg);
1024*11963SAfshin.Ardakani@Sun.COM 		cv_signal(&thread->sth_cv);
1025*11963SAfshin.Ardakani@Sun.COM 		break;
1026*11963SAfshin.Ardakani@Sun.COM 
1027*11963SAfshin.Ardakani@Sun.COM 	default:
1028*11963SAfshin.Ardakani@Sun.COM 		break;
1029*11963SAfshin.Ardakani@Sun.COM 	}
1030*11963SAfshin.Ardakani@Sun.COM 	mutex_exit(&thread->sth_mtx);
1031*11963SAfshin.Ardakani@Sun.COM }
1032*11963SAfshin.Ardakani@Sun.COM 
1033*11963SAfshin.Ardakani@Sun.COM boolean_t
1034*11963SAfshin.Ardakani@Sun.COM smb_thread_continue(smb_thread_t *thread)
1035*11963SAfshin.Ardakani@Sun.COM {
1036*11963SAfshin.Ardakani@Sun.COM 	boolean_t result;
1037*11963SAfshin.Ardakani@Sun.COM 
1038*11963SAfshin.Ardakani@Sun.COM 	ASSERT(thread->sth_magic == SMB_THREAD_MAGIC);
1039*11963SAfshin.Ardakani@Sun.COM 
1040*11963SAfshin.Ardakani@Sun.COM 	mutex_enter(&thread->sth_mtx);
1041*11963SAfshin.Ardakani@Sun.COM 	result = smb_thread_continue_timedwait_locked(thread, 0);
1042*11963SAfshin.Ardakani@Sun.COM 	mutex_exit(&thread->sth_mtx);
1043*11963SAfshin.Ardakani@Sun.COM 
1044*11963SAfshin.Ardakani@Sun.COM 	return (result);
1045*11963SAfshin.Ardakani@Sun.COM }
1046*11963SAfshin.Ardakani@Sun.COM 
1047*11963SAfshin.Ardakani@Sun.COM boolean_t
1048*11963SAfshin.Ardakani@Sun.COM smb_thread_continue_nowait(smb_thread_t *thread)
1049*11963SAfshin.Ardakani@Sun.COM {
1050*11963SAfshin.Ardakani@Sun.COM 	boolean_t result;
1051*11963SAfshin.Ardakani@Sun.COM 
1052*11963SAfshin.Ardakani@Sun.COM 	ASSERT(thread->sth_magic == SMB_THREAD_MAGIC);
1053*11963SAfshin.Ardakani@Sun.COM 
1054*11963SAfshin.Ardakani@Sun.COM 	mutex_enter(&thread->sth_mtx);
1055*11963SAfshin.Ardakani@Sun.COM 	/*
1056*11963SAfshin.Ardakani@Sun.COM 	 * Setting ticks=-1 requests a non-blocking check.  We will
1057*11963SAfshin.Ardakani@Sun.COM 	 * still block if the thread is in "suspend" state.
1058*11963SAfshin.Ardakani@Sun.COM 	 */
1059*11963SAfshin.Ardakani@Sun.COM 	result = smb_thread_continue_timedwait_locked(thread, -1);
1060*11963SAfshin.Ardakani@Sun.COM 	mutex_exit(&thread->sth_mtx);
1061*11963SAfshin.Ardakani@Sun.COM 
1062*11963SAfshin.Ardakani@Sun.COM 	return (result);
1063*11963SAfshin.Ardakani@Sun.COM }
1064*11963SAfshin.Ardakani@Sun.COM 
1065*11963SAfshin.Ardakani@Sun.COM boolean_t
1066*11963SAfshin.Ardakani@Sun.COM smb_thread_continue_timedwait(smb_thread_t *thread, int seconds)
1067*11963SAfshin.Ardakani@Sun.COM {
1068*11963SAfshin.Ardakani@Sun.COM 	boolean_t result;
1069*11963SAfshin.Ardakani@Sun.COM 
1070*11963SAfshin.Ardakani@Sun.COM 	ASSERT(thread->sth_magic == SMB_THREAD_MAGIC);
1071*11963SAfshin.Ardakani@Sun.COM 
1072*11963SAfshin.Ardakani@Sun.COM 	mutex_enter(&thread->sth_mtx);
1073*11963SAfshin.Ardakani@Sun.COM 	result = smb_thread_continue_timedwait_locked(thread,
1074*11963SAfshin.Ardakani@Sun.COM 	    SEC_TO_TICK(seconds));
1075*11963SAfshin.Ardakani@Sun.COM 	mutex_exit(&thread->sth_mtx);
1076*11963SAfshin.Ardakani@Sun.COM 
1077*11963SAfshin.Ardakani@Sun.COM 	return (result);
1078*11963SAfshin.Ardakani@Sun.COM }
1079*11963SAfshin.Ardakani@Sun.COM 
1080*11963SAfshin.Ardakani@Sun.COM /*
1081*11963SAfshin.Ardakani@Sun.COM  * smb_thread_continue_timedwait_locked
1082*11963SAfshin.Ardakani@Sun.COM  *
1083*11963SAfshin.Ardakani@Sun.COM  * Internal only.  Ticks==-1 means don't block, Ticks == 0 means wait
1084*11963SAfshin.Ardakani@Sun.COM  * indefinitely
1085*11963SAfshin.Ardakani@Sun.COM  */
1086*11963SAfshin.Ardakani@Sun.COM static boolean_t
1087*11963SAfshin.Ardakani@Sun.COM smb_thread_continue_timedwait_locked(smb_thread_t *thread, int ticks)
1088*11963SAfshin.Ardakani@Sun.COM {
1089*11963SAfshin.Ardakani@Sun.COM 	boolean_t	result;
1090*11963SAfshin.Ardakani@Sun.COM 
1091*11963SAfshin.Ardakani@Sun.COM 	/* -1 means don't block */
1092*11963SAfshin.Ardakani@Sun.COM 	if (ticks != -1 && !thread->sth_kill) {
1093*11963SAfshin.Ardakani@Sun.COM 		if (ticks == 0) {
1094*11963SAfshin.Ardakani@Sun.COM 			cv_wait(&thread->sth_cv, &thread->sth_mtx);
1095*11963SAfshin.Ardakani@Sun.COM 		} else {
1096*11963SAfshin.Ardakani@Sun.COM 			(void) cv_reltimedwait(&thread->sth_cv,
1097*11963SAfshin.Ardakani@Sun.COM 			    &thread->sth_mtx, (clock_t)ticks, TR_CLOCK_TICK);
1098*11963SAfshin.Ardakani@Sun.COM 		}
1099*11963SAfshin.Ardakani@Sun.COM 	}
1100*11963SAfshin.Ardakani@Sun.COM 	result = (thread->sth_kill == 0);
1101*11963SAfshin.Ardakani@Sun.COM 
1102*11963SAfshin.Ardakani@Sun.COM 	return (result);
1103*11963SAfshin.Ardakani@Sun.COM }
1104*11963SAfshin.Ardakani@Sun.COM 
1105*11963SAfshin.Ardakani@Sun.COM void
1106*11963SAfshin.Ardakani@Sun.COM smb_thread_set_awaken(smb_thread_t *thread, smb_thread_aw_t new_aw_fn,
1107*11963SAfshin.Ardakani@Sun.COM     void *new_aw_arg)
1108*11963SAfshin.Ardakani@Sun.COM {
1109*11963SAfshin.Ardakani@Sun.COM 	ASSERT(thread->sth_magic == SMB_THREAD_MAGIC);
1110*11963SAfshin.Ardakani@Sun.COM 
1111*11963SAfshin.Ardakani@Sun.COM 	mutex_enter(&thread->sth_mtx);
1112*11963SAfshin.Ardakani@Sun.COM 	thread->sth_aw = new_aw_fn;
1113*11963SAfshin.Ardakani@Sun.COM 	thread->sth_aw_arg = new_aw_arg;
1114*11963SAfshin.Ardakani@Sun.COM 	mutex_exit(&thread->sth_mtx);
1115*11963SAfshin.Ardakani@Sun.COM }
1116*11963SAfshin.Ardakani@Sun.COM 
1117*11963SAfshin.Ardakani@Sun.COM /*
1118*11963SAfshin.Ardakani@Sun.COM  * smb_rwx_init
1119*11963SAfshin.Ardakani@Sun.COM  */
1120*11963SAfshin.Ardakani@Sun.COM void
1121*11963SAfshin.Ardakani@Sun.COM smb_rwx_init(
1122*11963SAfshin.Ardakani@Sun.COM     smb_rwx_t	*rwx)
1123*11963SAfshin.Ardakani@Sun.COM {
1124*11963SAfshin.Ardakani@Sun.COM 	bzero(rwx, sizeof (smb_rwx_t));
1125*11963SAfshin.Ardakani@Sun.COM 	cv_init(&rwx->rwx_cv, NULL, CV_DEFAULT, NULL);
1126*11963SAfshin.Ardakani@Sun.COM 	mutex_init(&rwx->rwx_mutex, NULL, MUTEX_DEFAULT, NULL);
1127*11963SAfshin.Ardakani@Sun.COM 	rw_init(&rwx->rwx_lock, NULL, RW_DEFAULT, NULL);
1128*11963SAfshin.Ardakani@Sun.COM }
1129*11963SAfshin.Ardakani@Sun.COM 
1130*11963SAfshin.Ardakani@Sun.COM /*
1131*11963SAfshin.Ardakani@Sun.COM  * smb_rwx_destroy
1132*11963SAfshin.Ardakani@Sun.COM  */
1133*11963SAfshin.Ardakani@Sun.COM void
1134*11963SAfshin.Ardakani@Sun.COM smb_rwx_destroy(
1135*11963SAfshin.Ardakani@Sun.COM     smb_rwx_t	*rwx)
1136*11963SAfshin.Ardakani@Sun.COM {
1137*11963SAfshin.Ardakani@Sun.COM 	mutex_destroy(&rwx->rwx_mutex);
1138*11963SAfshin.Ardakani@Sun.COM 	cv_destroy(&rwx->rwx_cv);
1139*11963SAfshin.Ardakani@Sun.COM 	rw_destroy(&rwx->rwx_lock);
1140*11963SAfshin.Ardakani@Sun.COM }
1141*11963SAfshin.Ardakani@Sun.COM 
1142*11963SAfshin.Ardakani@Sun.COM /*
1143*11963SAfshin.Ardakani@Sun.COM  * smb_rwx_rwexit
1144*11963SAfshin.Ardakani@Sun.COM  */
1145*11963SAfshin.Ardakani@Sun.COM void
1146*11963SAfshin.Ardakani@Sun.COM smb_rwx_rwexit(
1147*11963SAfshin.Ardakani@Sun.COM     smb_rwx_t	*rwx)
1148*11963SAfshin.Ardakani@Sun.COM {
1149*11963SAfshin.Ardakani@Sun.COM 	if (rw_write_held(&rwx->rwx_lock)) {
1150*11963SAfshin.Ardakani@Sun.COM 		ASSERT(rw_owner(&rwx->rwx_lock) == curthread);
1151*11963SAfshin.Ardakani@Sun.COM 		mutex_enter(&rwx->rwx_mutex);
1152*11963SAfshin.Ardakani@Sun.COM 		if (rwx->rwx_waiting) {
1153*11963SAfshin.Ardakani@Sun.COM 			rwx->rwx_waiting = B_FALSE;
1154*11963SAfshin.Ardakani@Sun.COM 			cv_broadcast(&rwx->rwx_cv);
1155*11963SAfshin.Ardakani@Sun.COM 		}
1156*11963SAfshin.Ardakani@Sun.COM 		mutex_exit(&rwx->rwx_mutex);
1157*11963SAfshin.Ardakani@Sun.COM 	}
1158*11963SAfshin.Ardakani@Sun.COM 	rw_exit(&rwx->rwx_lock);
1159*11963SAfshin.Ardakani@Sun.COM }
1160*11963SAfshin.Ardakani@Sun.COM 
1161*11963SAfshin.Ardakani@Sun.COM /*
1162*11963SAfshin.Ardakani@Sun.COM  * smb_rwx_rwupgrade
1163*11963SAfshin.Ardakani@Sun.COM  */
1164*11963SAfshin.Ardakani@Sun.COM krw_t
1165*11963SAfshin.Ardakani@Sun.COM smb_rwx_rwupgrade(
1166*11963SAfshin.Ardakani@Sun.COM     smb_rwx_t	*rwx)
1167*11963SAfshin.Ardakani@Sun.COM {
1168*11963SAfshin.Ardakani@Sun.COM 	if (rw_write_held(&rwx->rwx_lock)) {
1169*11963SAfshin.Ardakani@Sun.COM 		ASSERT(rw_owner(&rwx->rwx_lock) == curthread);
1170*11963SAfshin.Ardakani@Sun.COM 		return (RW_WRITER);
1171*11963SAfshin.Ardakani@Sun.COM 	}
1172*11963SAfshin.Ardakani@Sun.COM 	if (!rw_tryupgrade(&rwx->rwx_lock)) {
1173*11963SAfshin.Ardakani@Sun.COM 		rw_exit(&rwx->rwx_lock);
1174*11963SAfshin.Ardakani@Sun.COM 		rw_enter(&rwx->rwx_lock, RW_WRITER);
1175*11963SAfshin.Ardakani@Sun.COM 	}
1176*11963SAfshin.Ardakani@Sun.COM 	return (RW_READER);
1177*11963SAfshin.Ardakani@Sun.COM }
1178*11963SAfshin.Ardakani@Sun.COM 
1179*11963SAfshin.Ardakani@Sun.COM /*
1180*11963SAfshin.Ardakani@Sun.COM  * smb_rwx_rwrestore
1181*11963SAfshin.Ardakani@Sun.COM  */
1182*11963SAfshin.Ardakani@Sun.COM void
1183*11963SAfshin.Ardakani@Sun.COM smb_rwx_rwdowngrade(
1184*11963SAfshin.Ardakani@Sun.COM     smb_rwx_t	*rwx,
1185*11963SAfshin.Ardakani@Sun.COM     krw_t	mode)
1186*11963SAfshin.Ardakani@Sun.COM {
1187*11963SAfshin.Ardakani@Sun.COM 	ASSERT(rw_write_held(&rwx->rwx_lock));
1188*11963SAfshin.Ardakani@Sun.COM 	ASSERT(rw_owner(&rwx->rwx_lock) == curthread);
1189*11963SAfshin.Ardakani@Sun.COM 
1190*11963SAfshin.Ardakani@Sun.COM 	if (mode == RW_WRITER) {
1191*11963SAfshin.Ardakani@Sun.COM 		return;
1192*11963SAfshin.Ardakani@Sun.COM 	}
1193*11963SAfshin.Ardakani@Sun.COM 	ASSERT(mode == RW_READER);
1194*11963SAfshin.Ardakani@Sun.COM 	mutex_enter(&rwx->rwx_mutex);
1195*11963SAfshin.Ardakani@Sun.COM 	if (rwx->rwx_waiting) {
1196*11963SAfshin.Ardakani@Sun.COM 		rwx->rwx_waiting = B_FALSE;
1197*11963SAfshin.Ardakani@Sun.COM 		cv_broadcast(&rwx->rwx_cv);
1198*11963SAfshin.Ardakani@Sun.COM 	}
1199*11963SAfshin.Ardakani@Sun.COM 	mutex_exit(&rwx->rwx_mutex);
1200*11963SAfshin.Ardakani@Sun.COM 	rw_downgrade(&rwx->rwx_lock);
1201*11963SAfshin.Ardakani@Sun.COM }
1202*11963SAfshin.Ardakani@Sun.COM 
1203*11963SAfshin.Ardakani@Sun.COM /*
1204*11963SAfshin.Ardakani@Sun.COM  * smb_rwx_wait
1205*11963SAfshin.Ardakani@Sun.COM  *
1206*11963SAfshin.Ardakani@Sun.COM  * This function assumes the smb_rwx lock was enter in RW_READER or RW_WRITER
1207*11963SAfshin.Ardakani@Sun.COM  * mode. It will:
1208*11963SAfshin.Ardakani@Sun.COM  *
1209*11963SAfshin.Ardakani@Sun.COM  *	1) release the lock and save its current mode.
1210*11963SAfshin.Ardakani@Sun.COM  *	2) wait until the condition variable is signaled. This can happen for
1211*11963SAfshin.Ardakani@Sun.COM  *	   2 reasons: When a writer releases the lock or when the time out (if
1212*11963SAfshin.Ardakani@Sun.COM  *	   provided) expires.
1213*11963SAfshin.Ardakani@Sun.COM  *	3) re-acquire the lock in the mode saved in (1).
1214*11963SAfshin.Ardakani@Sun.COM  */
1215*11963SAfshin.Ardakani@Sun.COM int
1216*11963SAfshin.Ardakani@Sun.COM smb_rwx_rwwait(
1217*11963SAfshin.Ardakani@Sun.COM     smb_rwx_t	*rwx,
1218*11963SAfshin.Ardakani@Sun.COM     clock_t	timeout)
1219*11963SAfshin.Ardakani@Sun.COM {
1220*11963SAfshin.Ardakani@Sun.COM 	int	rc;
1221*11963SAfshin.Ardakani@Sun.COM 	krw_t	mode;
1222*11963SAfshin.Ardakani@Sun.COM 
1223*11963SAfshin.Ardakani@Sun.COM 	mutex_enter(&rwx->rwx_mutex);
1224*11963SAfshin.Ardakani@Sun.COM 	rwx->rwx_waiting = B_TRUE;
1225*11963SAfshin.Ardakani@Sun.COM 	mutex_exit(&rwx->rwx_mutex);
1226*11963SAfshin.Ardakani@Sun.COM 
1227*11963SAfshin.Ardakani@Sun.COM 	if (rw_write_held(&rwx->rwx_lock)) {
1228*11963SAfshin.Ardakani@Sun.COM 		ASSERT(rw_owner(&rwx->rwx_lock) == curthread);
1229*11963SAfshin.Ardakani@Sun.COM 		mode = RW_WRITER;
1230*11963SAfshin.Ardakani@Sun.COM 	} else {
1231*11963SAfshin.Ardakani@Sun.COM 		ASSERT(rw_read_held(&rwx->rwx_lock));
1232*11963SAfshin.Ardakani@Sun.COM 		mode = RW_READER;
1233*11963SAfshin.Ardakani@Sun.COM 	}
1234*11963SAfshin.Ardakani@Sun.COM 	rw_exit(&rwx->rwx_lock);
1235*11963SAfshin.Ardakani@Sun.COM 
1236*11963SAfshin.Ardakani@Sun.COM 	mutex_enter(&rwx->rwx_mutex);
1237*11963SAfshin.Ardakani@Sun.COM 	if (rwx->rwx_waiting) {
1238*11963SAfshin.Ardakani@Sun.COM 		if (timeout == -1) {
1239*11963SAfshin.Ardakani@Sun.COM 			rc = 1;
1240*11963SAfshin.Ardakani@Sun.COM 			cv_wait(&rwx->rwx_cv, &rwx->rwx_mutex);
1241*11963SAfshin.Ardakani@Sun.COM 		} else {
1242*11963SAfshin.Ardakani@Sun.COM 			rc = cv_reltimedwait(&rwx->rwx_cv, &rwx->rwx_mutex,
1243*11963SAfshin.Ardakani@Sun.COM 			    timeout, TR_CLOCK_TICK);
1244*11963SAfshin.Ardakani@Sun.COM 		}
1245*11963SAfshin.Ardakani@Sun.COM 	}
1246*11963SAfshin.Ardakani@Sun.COM 	mutex_exit(&rwx->rwx_mutex);
1247*11963SAfshin.Ardakani@Sun.COM 
1248*11963SAfshin.Ardakani@Sun.COM 	rw_enter(&rwx->rwx_lock, mode);
1249*11963SAfshin.Ardakani@Sun.COM 	return (rc);
1250*11963SAfshin.Ardakani@Sun.COM }
1251*11963SAfshin.Ardakani@Sun.COM 
1252*11963SAfshin.Ardakani@Sun.COM /*
1253*11963SAfshin.Ardakani@Sun.COM  * SMB ID mapping
1254*11963SAfshin.Ardakani@Sun.COM  *
1255*11963SAfshin.Ardakani@Sun.COM  * Solaris ID mapping service (aka Winchester) works with domain SIDs
1256*11963SAfshin.Ardakani@Sun.COM  * and RIDs where domain SIDs are in string format. CIFS service works
1257*11963SAfshin.Ardakani@Sun.COM  * with binary SIDs understandable by CIFS clients. A layer of SMB ID
1258*11963SAfshin.Ardakani@Sun.COM  * mapping functions are implemeted to hide the SID conversion details
1259*11963SAfshin.Ardakani@Sun.COM  * and also hide the handling of array of batch mapping requests.
1260*11963SAfshin.Ardakani@Sun.COM  *
1261*11963SAfshin.Ardakani@Sun.COM  * IMPORTANT NOTE The Winchester API requires a zone. Because CIFS server
1262*11963SAfshin.Ardakani@Sun.COM  * currently only runs in the global zone the global zone is specified.
1263*11963SAfshin.Ardakani@Sun.COM  * This needs to be fixed when the CIFS server supports zones.
1264*11963SAfshin.Ardakani@Sun.COM  */
1265*11963SAfshin.Ardakani@Sun.COM 
1266*11963SAfshin.Ardakani@Sun.COM static int smb_idmap_batch_binsid(smb_idmap_batch_t *sib);
1267*11963SAfshin.Ardakani@Sun.COM 
1268*11963SAfshin.Ardakani@Sun.COM /*
1269*11963SAfshin.Ardakani@Sun.COM  * smb_idmap_getid
1270*11963SAfshin.Ardakani@Sun.COM  *
1271*11963SAfshin.Ardakani@Sun.COM  * Maps the given Windows SID to a Solaris ID using the
1272*11963SAfshin.Ardakani@Sun.COM  * simple mapping API.
1273*11963SAfshin.Ardakani@Sun.COM  */
1274*11963SAfshin.Ardakani@Sun.COM idmap_stat
1275*11963SAfshin.Ardakani@Sun.COM smb_idmap_getid(smb_sid_t *sid, uid_t *id, int *idtype)
1276*11963SAfshin.Ardakani@Sun.COM {
1277*11963SAfshin.Ardakani@Sun.COM 	smb_idmap_t sim;
1278*11963SAfshin.Ardakani@Sun.COM 	char sidstr[SMB_SID_STRSZ];
1279*11963SAfshin.Ardakani@Sun.COM 
1280*11963SAfshin.Ardakani@Sun.COM 	smb_sid_tostr(sid, sidstr);
1281*11963SAfshin.Ardakani@Sun.COM 	if (smb_sid_splitstr(sidstr, &sim.sim_rid) != 0)
1282*11963SAfshin.Ardakani@Sun.COM 		return (IDMAP_ERR_SID);
1283*11963SAfshin.Ardakani@Sun.COM 	sim.sim_domsid = sidstr;
1284*11963SAfshin.Ardakani@Sun.COM 	sim.sim_id = id;
1285*11963SAfshin.Ardakani@Sun.COM 
1286*11963SAfshin.Ardakani@Sun.COM 	switch (*idtype) {
1287*11963SAfshin.Ardakani@Sun.COM 	case SMB_IDMAP_USER:
1288*11963SAfshin.Ardakani@Sun.COM 		sim.sim_stat = kidmap_getuidbysid(global_zone, sim.sim_domsid,
1289*11963SAfshin.Ardakani@Sun.COM 		    sim.sim_rid, sim.sim_id);
1290*11963SAfshin.Ardakani@Sun.COM 		break;
1291*11963SAfshin.Ardakani@Sun.COM 
1292*11963SAfshin.Ardakani@Sun.COM 	case SMB_IDMAP_GROUP:
1293*11963SAfshin.Ardakani@Sun.COM 		sim.sim_stat = kidmap_getgidbysid(global_zone, sim.sim_domsid,
1294*11963SAfshin.Ardakani@Sun.COM 		    sim.sim_rid, sim.sim_id);
1295*11963SAfshin.Ardakani@Sun.COM 		break;
1296*11963SAfshin.Ardakani@Sun.COM 
1297*11963SAfshin.Ardakani@Sun.COM 	case SMB_IDMAP_UNKNOWN:
1298*11963SAfshin.Ardakani@Sun.COM 		sim.sim_stat = kidmap_getpidbysid(global_zone, sim.sim_domsid,
1299*11963SAfshin.Ardakani@Sun.COM 		    sim.sim_rid, sim.sim_id, &sim.sim_idtype);
1300*11963SAfshin.Ardakani@Sun.COM 		break;
1301*11963SAfshin.Ardakani@Sun.COM 
1302*11963SAfshin.Ardakani@Sun.COM 	default:
1303*11963SAfshin.Ardakani@Sun.COM 		ASSERT(0);
1304*11963SAfshin.Ardakani@Sun.COM 		return (IDMAP_ERR_ARG);
1305*11963SAfshin.Ardakani@Sun.COM 	}
1306*11963SAfshin.Ardakani@Sun.COM 
1307*11963SAfshin.Ardakani@Sun.COM 	*idtype = sim.sim_idtype;
1308*11963SAfshin.Ardakani@Sun.COM 
1309*11963SAfshin.Ardakani@Sun.COM 	return (sim.sim_stat);
1310*11963SAfshin.Ardakani@Sun.COM }
1311*11963SAfshin.Ardakani@Sun.COM 
1312*11963SAfshin.Ardakani@Sun.COM /*
1313*11963SAfshin.Ardakani@Sun.COM  * smb_idmap_getsid
1314*11963SAfshin.Ardakani@Sun.COM  *
1315*11963SAfshin.Ardakani@Sun.COM  * Maps the given Solaris ID to a Windows SID using the
1316*11963SAfshin.Ardakani@Sun.COM  * simple mapping API.
1317*11963SAfshin.Ardakani@Sun.COM  */
1318*11963SAfshin.Ardakani@Sun.COM idmap_stat
1319*11963SAfshin.Ardakani@Sun.COM smb_idmap_getsid(uid_t id, int idtype, smb_sid_t **sid)
1320*11963SAfshin.Ardakani@Sun.COM {
1321*11963SAfshin.Ardakani@Sun.COM 	smb_idmap_t sim;
1322*11963SAfshin.Ardakani@Sun.COM 
1323*11963SAfshin.Ardakani@Sun.COM 	switch (idtype) {
1324*11963SAfshin.Ardakani@Sun.COM 	case SMB_IDMAP_USER:
1325*11963SAfshin.Ardakani@Sun.COM 		sim.sim_stat = kidmap_getsidbyuid(global_zone, id,
1326*11963SAfshin.Ardakani@Sun.COM 		    (const char **)&sim.sim_domsid, &sim.sim_rid);
1327*11963SAfshin.Ardakani@Sun.COM 		break;
1328*11963SAfshin.Ardakani@Sun.COM 
1329*11963SAfshin.Ardakani@Sun.COM 	case SMB_IDMAP_GROUP:
1330*11963SAfshin.Ardakani@Sun.COM 		sim.sim_stat = kidmap_getsidbygid(global_zone, id,
1331*11963SAfshin.Ardakani@Sun.COM 		    (const char **)&sim.sim_domsid, &sim.sim_rid);
1332*11963SAfshin.Ardakani@Sun.COM 		break;
1333*11963SAfshin.Ardakani@Sun.COM 
1334*11963SAfshin.Ardakani@Sun.COM 	case SMB_IDMAP_EVERYONE:
1335*11963SAfshin.Ardakani@Sun.COM 		/* Everyone S-1-1-0 */
1336*11963SAfshin.Ardakani@Sun.COM 		sim.sim_domsid = "S-1-1";
1337*11963SAfshin.Ardakani@Sun.COM 		sim.sim_rid = 0;
1338*11963SAfshin.Ardakani@Sun.COM 		sim.sim_stat = IDMAP_SUCCESS;
1339*11963SAfshin.Ardakani@Sun.COM 		break;
1340*11963SAfshin.Ardakani@Sun.COM 
1341*11963SAfshin.Ardakani@Sun.COM 	default:
1342*11963SAfshin.Ardakani@Sun.COM 		ASSERT(0);
1343*11963SAfshin.Ardakani@Sun.COM 		return (IDMAP_ERR_ARG);
1344*11963SAfshin.Ardakani@Sun.COM 	}
1345*11963SAfshin.Ardakani@Sun.COM 
1346*11963SAfshin.Ardakani@Sun.COM 	if (sim.sim_stat != IDMAP_SUCCESS)
1347*11963SAfshin.Ardakani@Sun.COM 		return (sim.sim_stat);
1348*11963SAfshin.Ardakani@Sun.COM 
1349*11963SAfshin.Ardakani@Sun.COM 	if (sim.sim_domsid == NULL)
1350*11963SAfshin.Ardakani@Sun.COM 		return (IDMAP_ERR_NOMAPPING);
1351*11963SAfshin.Ardakani@Sun.COM 
1352*11963SAfshin.Ardakani@Sun.COM 	sim.sim_sid = smb_sid_fromstr(sim.sim_domsid);
1353*11963SAfshin.Ardakani@Sun.COM 	if (sim.sim_sid == NULL)
1354*11963SAfshin.Ardakani@Sun.COM 		return (IDMAP_ERR_INTERNAL);
1355*11963SAfshin.Ardakani@Sun.COM 
1356*11963SAfshin.Ardakani@Sun.COM 	*sid = smb_sid_splice(sim.sim_sid, sim.sim_rid);
1357*11963SAfshin.Ardakani@Sun.COM 	smb_sid_free(sim.sim_sid);
1358*11963SAfshin.Ardakani@Sun.COM 	if (*sid == NULL)
1359*11963SAfshin.Ardakani@Sun.COM 		sim.sim_stat = IDMAP_ERR_INTERNAL;
1360*11963SAfshin.Ardakani@Sun.COM 
1361*11963SAfshin.Ardakani@Sun.COM 	return (sim.sim_stat);
1362*11963SAfshin.Ardakani@Sun.COM }
1363*11963SAfshin.Ardakani@Sun.COM 
1364*11963SAfshin.Ardakani@Sun.COM /*
1365*11963SAfshin.Ardakani@Sun.COM  * smb_idmap_batch_create
1366*11963SAfshin.Ardakani@Sun.COM  *
1367*11963SAfshin.Ardakani@Sun.COM  * Creates and initializes the context for batch ID mapping.
1368*11963SAfshin.Ardakani@Sun.COM  */
1369*11963SAfshin.Ardakani@Sun.COM idmap_stat
1370*11963SAfshin.Ardakani@Sun.COM smb_idmap_batch_create(smb_idmap_batch_t *sib, uint16_t nmap, int flags)
1371*11963SAfshin.Ardakani@Sun.COM {
1372*11963SAfshin.Ardakani@Sun.COM 	ASSERT(sib);
1373*11963SAfshin.Ardakani@Sun.COM 
1374*11963SAfshin.Ardakani@Sun.COM 	bzero(sib, sizeof (smb_idmap_batch_t));
1375*11963SAfshin.Ardakani@Sun.COM 
1376*11963SAfshin.Ardakani@Sun.COM 	sib->sib_idmaph = kidmap_get_create(global_zone);
1377*11963SAfshin.Ardakani@Sun.COM 
1378*11963SAfshin.Ardakani@Sun.COM 	sib->sib_flags = flags;
1379*11963SAfshin.Ardakani@Sun.COM 	sib->sib_nmap = nmap;
1380*11963SAfshin.Ardakani@Sun.COM 	sib->sib_size = nmap * sizeof (smb_idmap_t);
1381*11963SAfshin.Ardakani@Sun.COM 	sib->sib_maps = kmem_zalloc(sib->sib_size, KM_SLEEP);
1382*11963SAfshin.Ardakani@Sun.COM 
1383*11963SAfshin.Ardakani@Sun.COM 	return (IDMAP_SUCCESS);
1384*11963SAfshin.Ardakani@Sun.COM }
1385*11963SAfshin.Ardakani@Sun.COM 
1386*11963SAfshin.Ardakani@Sun.COM /*
1387*11963SAfshin.Ardakani@Sun.COM  * smb_idmap_batch_destroy
1388*11963SAfshin.Ardakani@Sun.COM  *
1389*11963SAfshin.Ardakani@Sun.COM  * Frees the batch ID mapping context.
1390*11963SAfshin.Ardakani@Sun.COM  * If ID mapping is Solaris -> Windows it frees memories
1391*11963SAfshin.Ardakani@Sun.COM  * allocated for binary SIDs.
1392*11963SAfshin.Ardakani@Sun.COM  */
1393*11963SAfshin.Ardakani@Sun.COM void
1394*11963SAfshin.Ardakani@Sun.COM smb_idmap_batch_destroy(smb_idmap_batch_t *sib)
1395*11963SAfshin.Ardakani@Sun.COM {
1396*11963SAfshin.Ardakani@Sun.COM 	char *domsid;
1397*11963SAfshin.Ardakani@Sun.COM 	int i;
1398*11963SAfshin.Ardakani@Sun.COM 
1399*11963SAfshin.Ardakani@Sun.COM 	ASSERT(sib);
1400*11963SAfshin.Ardakani@Sun.COM 	ASSERT(sib->sib_maps);
1401*11963SAfshin.Ardakani@Sun.COM 
1402*11963SAfshin.Ardakani@Sun.COM 	if (sib->sib_idmaph)
1403*11963SAfshin.Ardakani@Sun.COM 		kidmap_get_destroy(sib->sib_idmaph);
1404*11963SAfshin.Ardakani@Sun.COM 
1405*11963SAfshin.Ardakani@Sun.COM 	if (sib->sib_flags & SMB_IDMAP_ID2SID) {
1406*11963SAfshin.Ardakani@Sun.COM 		/*
1407*11963SAfshin.Ardakani@Sun.COM 		 * SIDs are allocated only when mapping
1408*11963SAfshin.Ardakani@Sun.COM 		 * UID/GID to SIDs
1409*11963SAfshin.Ardakani@Sun.COM 		 */
1410*11963SAfshin.Ardakani@Sun.COM 		for (i = 0; i < sib->sib_nmap; i++)
1411*11963SAfshin.Ardakani@Sun.COM 			smb_sid_free(sib->sib_maps[i].sim_sid);
1412*11963SAfshin.Ardakani@Sun.COM 	} else if (sib->sib_flags & SMB_IDMAP_SID2ID) {
1413*11963SAfshin.Ardakani@Sun.COM 		/*
1414*11963SAfshin.Ardakani@Sun.COM 		 * SID prefixes are allocated only when mapping
1415*11963SAfshin.Ardakani@Sun.COM 		 * SIDs to UID/GID
1416*11963SAfshin.Ardakani@Sun.COM 		 */
1417*11963SAfshin.Ardakani@Sun.COM 		for (i = 0; i < sib->sib_nmap; i++) {
1418*11963SAfshin.Ardakani@Sun.COM 			domsid = sib->sib_maps[i].sim_domsid;
1419*11963SAfshin.Ardakani@Sun.COM 			if (domsid)
1420*11963SAfshin.Ardakani@Sun.COM 				smb_mem_free(domsid);
1421*11963SAfshin.Ardakani@Sun.COM 		}
1422*11963SAfshin.Ardakani@Sun.COM 	}
1423*11963SAfshin.Ardakani@Sun.COM 
1424*11963SAfshin.Ardakani@Sun.COM 	if (sib->sib_size && sib->sib_maps)
1425*11963SAfshin.Ardakani@Sun.COM 		kmem_free(sib->sib_maps, sib->sib_size);
1426*11963SAfshin.Ardakani@Sun.COM }
1427*11963SAfshin.Ardakani@Sun.COM 
1428*11963SAfshin.Ardakani@Sun.COM /*
1429*11963SAfshin.Ardakani@Sun.COM  * smb_idmap_batch_getid
1430*11963SAfshin.Ardakani@Sun.COM  *
1431*11963SAfshin.Ardakani@Sun.COM  * Queue a request to map the given SID to a UID or GID.
1432*11963SAfshin.Ardakani@Sun.COM  *
1433*11963SAfshin.Ardakani@Sun.COM  * sim->sim_id should point to variable that's supposed to
1434*11963SAfshin.Ardakani@Sun.COM  * hold the returned UID/GID. This needs to be setup by caller
1435*11963SAfshin.Ardakani@Sun.COM  * of this function.
1436*11963SAfshin.Ardakani@Sun.COM  *
1437*11963SAfshin.Ardakani@Sun.COM  * If requested ID type is known, it's passed as 'idtype',
1438*11963SAfshin.Ardakani@Sun.COM  * if it's unknown it'll be returned in sim->sim_idtype.
1439*11963SAfshin.Ardakani@Sun.COM  */
1440*11963SAfshin.Ardakani@Sun.COM idmap_stat
1441*11963SAfshin.Ardakani@Sun.COM smb_idmap_batch_getid(idmap_get_handle_t *idmaph, smb_idmap_t *sim,
1442*11963SAfshin.Ardakani@Sun.COM     smb_sid_t *sid, int idtype)
1443*11963SAfshin.Ardakani@Sun.COM {
1444*11963SAfshin.Ardakani@Sun.COM 	char strsid[SMB_SID_STRSZ];
1445*11963SAfshin.Ardakani@Sun.COM 	idmap_stat idm_stat;
1446*11963SAfshin.Ardakani@Sun.COM 
1447*11963SAfshin.Ardakani@Sun.COM 	ASSERT(idmaph);
1448*11963SAfshin.Ardakani@Sun.COM 	ASSERT(sim);
1449*11963SAfshin.Ardakani@Sun.COM 	ASSERT(sid);
1450*11963SAfshin.Ardakani@Sun.COM 
1451*11963SAfshin.Ardakani@Sun.COM 	smb_sid_tostr(sid, strsid);
1452*11963SAfshin.Ardakani@Sun.COM 	if (smb_sid_splitstr(strsid, &sim->sim_rid) != 0)
1453*11963SAfshin.Ardakani@Sun.COM 		return (IDMAP_ERR_SID);
1454*11963SAfshin.Ardakani@Sun.COM 	sim->sim_domsid = smb_mem_strdup(strsid);
1455*11963SAfshin.Ardakani@Sun.COM 
1456*11963SAfshin.Ardakani@Sun.COM 	switch (idtype) {
1457*11963SAfshin.Ardakani@Sun.COM 	case SMB_IDMAP_USER:
1458*11963SAfshin.Ardakani@Sun.COM 		idm_stat = kidmap_batch_getuidbysid(idmaph, sim->sim_domsid,
1459*11963SAfshin.Ardakani@Sun.COM 		    sim->sim_rid, sim->sim_id, &sim->sim_stat);
1460*11963SAfshin.Ardakani@Sun.COM 		break;
1461*11963SAfshin.Ardakani@Sun.COM 
1462*11963SAfshin.Ardakani@Sun.COM 	case SMB_IDMAP_GROUP:
1463*11963SAfshin.Ardakani@Sun.COM 		idm_stat = kidmap_batch_getgidbysid(idmaph, sim->sim_domsid,
1464*11963SAfshin.Ardakani@Sun.COM 		    sim->sim_rid, sim->sim_id, &sim->sim_stat);
1465*11963SAfshin.Ardakani@Sun.COM 		break;
1466*11963SAfshin.Ardakani@Sun.COM 
1467*11963SAfshin.Ardakani@Sun.COM 	case SMB_IDMAP_UNKNOWN:
1468*11963SAfshin.Ardakani@Sun.COM 		idm_stat = kidmap_batch_getpidbysid(idmaph, sim->sim_domsid,
1469*11963SAfshin.Ardakani@Sun.COM 		    sim->sim_rid, sim->sim_id, &sim->sim_idtype,
1470*11963SAfshin.Ardakani@Sun.COM 		    &sim->sim_stat);
1471*11963SAfshin.Ardakani@Sun.COM 		break;
1472*11963SAfshin.Ardakani@Sun.COM 
1473*11963SAfshin.Ardakani@Sun.COM 	default:
1474*11963SAfshin.Ardakani@Sun.COM 		ASSERT(0);
1475*11963SAfshin.Ardakani@Sun.COM 		return (IDMAP_ERR_ARG);
1476*11963SAfshin.Ardakani@Sun.COM 	}
1477*11963SAfshin.Ardakani@Sun.COM 
1478*11963SAfshin.Ardakani@Sun.COM 	return (idm_stat);
1479*11963SAfshin.Ardakani@Sun.COM }
1480*11963SAfshin.Ardakani@Sun.COM 
1481*11963SAfshin.Ardakani@Sun.COM /*
1482*11963SAfshin.Ardakani@Sun.COM  * smb_idmap_batch_getsid
1483*11963SAfshin.Ardakani@Sun.COM  *
1484*11963SAfshin.Ardakani@Sun.COM  * Queue a request to map the given UID/GID to a SID.
1485*11963SAfshin.Ardakani@Sun.COM  *
1486*11963SAfshin.Ardakani@Sun.COM  * sim->sim_domsid and sim->sim_rid will contain the mapping
1487*11963SAfshin.Ardakani@Sun.COM  * result upon successful process of the batched request.
1488*11963SAfshin.Ardakani@Sun.COM  */
1489*11963SAfshin.Ardakani@Sun.COM idmap_stat
1490*11963SAfshin.Ardakani@Sun.COM smb_idmap_batch_getsid(idmap_get_handle_t *idmaph, smb_idmap_t *sim,
1491*11963SAfshin.Ardakani@Sun.COM     uid_t id, int idtype)
1492*11963SAfshin.Ardakani@Sun.COM {
1493*11963SAfshin.Ardakani@Sun.COM 	idmap_stat idm_stat;
1494*11963SAfshin.Ardakani@Sun.COM 
1495*11963SAfshin.Ardakani@Sun.COM 	switch (idtype) {
1496*11963SAfshin.Ardakani@Sun.COM 	case SMB_IDMAP_USER:
1497*11963SAfshin.Ardakani@Sun.COM 		idm_stat = kidmap_batch_getsidbyuid(idmaph, id,
1498*11963SAfshin.Ardakani@Sun.COM 		    (const char **)&sim->sim_domsid, &sim->sim_rid,
1499*11963SAfshin.Ardakani@Sun.COM 		    &sim->sim_stat);
1500*11963SAfshin.Ardakani@Sun.COM 		break;
1501*11963SAfshin.Ardakani@Sun.COM 
1502*11963SAfshin.Ardakani@Sun.COM 	case SMB_IDMAP_GROUP:
1503*11963SAfshin.Ardakani@Sun.COM 		idm_stat = kidmap_batch_getsidbygid(idmaph, id,
1504*11963SAfshin.Ardakani@Sun.COM 		    (const char **)&sim->sim_domsid, &sim->sim_rid,
1505*11963SAfshin.Ardakani@Sun.COM 		    &sim->sim_stat);
1506*11963SAfshin.Ardakani@Sun.COM 		break;
1507*11963SAfshin.Ardakani@Sun.COM 
1508*11963SAfshin.Ardakani@Sun.COM 	case SMB_IDMAP_OWNERAT:
1509*11963SAfshin.Ardakani@Sun.COM 		/* Current Owner S-1-5-32-766 */
1510*11963SAfshin.Ardakani@Sun.COM 		sim->sim_domsid = NT_BUILTIN_DOMAIN_SIDSTR;
1511*11963SAfshin.Ardakani@Sun.COM 		sim->sim_rid = SECURITY_CURRENT_OWNER_RID;
1512*11963SAfshin.Ardakani@Sun.COM 		sim->sim_stat = IDMAP_SUCCESS;
1513*11963SAfshin.Ardakani@Sun.COM 		idm_stat = IDMAP_SUCCESS;
1514*11963SAfshin.Ardakani@Sun.COM 		break;
1515*11963SAfshin.Ardakani@Sun.COM 
1516*11963SAfshin.Ardakani@Sun.COM 	case SMB_IDMAP_GROUPAT:
1517*11963SAfshin.Ardakani@Sun.COM 		/* Current Group S-1-5-32-767 */
1518*11963SAfshin.Ardakani@Sun.COM 		sim->sim_domsid = NT_BUILTIN_DOMAIN_SIDSTR;
1519*11963SAfshin.Ardakani@Sun.COM 		sim->sim_rid = SECURITY_CURRENT_GROUP_RID;
1520*11963SAfshin.Ardakani@Sun.COM 		sim->sim_stat = IDMAP_SUCCESS;
1521*11963SAfshin.Ardakani@Sun.COM 		idm_stat = IDMAP_SUCCESS;
1522*11963SAfshin.Ardakani@Sun.COM 		break;
1523*11963SAfshin.Ardakani@Sun.COM 
1524*11963SAfshin.Ardakani@Sun.COM 	case SMB_IDMAP_EVERYONE:
1525*11963SAfshin.Ardakani@Sun.COM 		/* Everyone S-1-1-0 */
1526*11963SAfshin.Ardakani@Sun.COM 		sim->sim_domsid = NT_WORLD_AUTH_SIDSTR;
1527*11963SAfshin.Ardakani@Sun.COM 		sim->sim_rid = 0;
1528*11963SAfshin.Ardakani@Sun.COM 		sim->sim_stat = IDMAP_SUCCESS;
1529*11963SAfshin.Ardakani@Sun.COM 		idm_stat = IDMAP_SUCCESS;
1530*11963SAfshin.Ardakani@Sun.COM 		break;
1531*11963SAfshin.Ardakani@Sun.COM 
1532*11963SAfshin.Ardakani@Sun.COM 	default:
1533*11963SAfshin.Ardakani@Sun.COM 		ASSERT(0);
1534*11963SAfshin.Ardakani@Sun.COM 		return (IDMAP_ERR_ARG);
1535*11963SAfshin.Ardakani@Sun.COM 	}
1536*11963SAfshin.Ardakani@Sun.COM 
1537*11963SAfshin.Ardakani@Sun.COM 	return (idm_stat);
1538*11963SAfshin.Ardakani@Sun.COM }
1539*11963SAfshin.Ardakani@Sun.COM 
1540*11963SAfshin.Ardakani@Sun.COM /*
1541*11963SAfshin.Ardakani@Sun.COM  * smb_idmap_batch_binsid
1542*11963SAfshin.Ardakani@Sun.COM  *
1543*11963SAfshin.Ardakani@Sun.COM  * Convert sidrids to binary sids
1544*11963SAfshin.Ardakani@Sun.COM  *
1545*11963SAfshin.Ardakani@Sun.COM  * Returns 0 if successful and non-zero upon failure.
1546*11963SAfshin.Ardakani@Sun.COM  */
1547*11963SAfshin.Ardakani@Sun.COM static int
1548*11963SAfshin.Ardakani@Sun.COM smb_idmap_batch_binsid(smb_idmap_batch_t *sib)
1549*11963SAfshin.Ardakani@Sun.COM {
1550*11963SAfshin.Ardakani@Sun.COM 	smb_sid_t *sid;
1551*11963SAfshin.Ardakani@Sun.COM 	smb_idmap_t *sim;
1552*11963SAfshin.Ardakani@Sun.COM 	int i;
1553*11963SAfshin.Ardakani@Sun.COM 
1554*11963SAfshin.Ardakani@Sun.COM 	if (sib->sib_flags & SMB_IDMAP_SID2ID)
1555*11963SAfshin.Ardakani@Sun.COM 		/* This operation is not required */
1556*11963SAfshin.Ardakani@Sun.COM 		return (0);
1557*11963SAfshin.Ardakani@Sun.COM 
1558*11963SAfshin.Ardakani@Sun.COM 	sim = sib->sib_maps;
1559*11963SAfshin.Ardakani@Sun.COM 	for (i = 0; i < sib->sib_nmap; sim++, i++) {
1560*11963SAfshin.Ardakani@Sun.COM 		ASSERT(sim->sim_domsid);
1561*11963SAfshin.Ardakani@Sun.COM 		if (sim->sim_domsid == NULL)
1562*11963SAfshin.Ardakani@Sun.COM 			return (1);
1563*11963SAfshin.Ardakani@Sun.COM 
1564*11963SAfshin.Ardakani@Sun.COM 		if ((sid = smb_sid_fromstr(sim->sim_domsid)) == NULL)
1565*11963SAfshin.Ardakani@Sun.COM 			return (1);
1566*11963SAfshin.Ardakani@Sun.COM 
1567*11963SAfshin.Ardakani@Sun.COM 		sim->sim_sid = smb_sid_splice(sid, sim->sim_rid);
1568*11963SAfshin.Ardakani@Sun.COM 		smb_sid_free(sid);
1569*11963SAfshin.Ardakani@Sun.COM 	}
1570*11963SAfshin.Ardakani@Sun.COM 
1571*11963SAfshin.Ardakani@Sun.COM 	return (0);
1572*11963SAfshin.Ardakani@Sun.COM }
1573*11963SAfshin.Ardakani@Sun.COM 
1574*11963SAfshin.Ardakani@Sun.COM /*
1575*11963SAfshin.Ardakani@Sun.COM  * smb_idmap_batch_getmappings
1576*11963SAfshin.Ardakani@Sun.COM  *
1577*11963SAfshin.Ardakani@Sun.COM  * trigger ID mapping service to get the mappings for queued
1578*11963SAfshin.Ardakani@Sun.COM  * requests.
1579*11963SAfshin.Ardakani@Sun.COM  *
1580*11963SAfshin.Ardakani@Sun.COM  * Checks the result of all the queued requests.
1581*11963SAfshin.Ardakani@Sun.COM  * If this is a Solaris -> Windows mapping it generates
1582*11963SAfshin.Ardakani@Sun.COM  * binary SIDs from returned (domsid, rid) pairs.
1583*11963SAfshin.Ardakani@Sun.COM  */
1584*11963SAfshin.Ardakani@Sun.COM idmap_stat
1585*11963SAfshin.Ardakani@Sun.COM smb_idmap_batch_getmappings(smb_idmap_batch_t *sib)
1586*11963SAfshin.Ardakani@Sun.COM {
1587*11963SAfshin.Ardakani@Sun.COM 	idmap_stat idm_stat = IDMAP_SUCCESS;
1588*11963SAfshin.Ardakani@Sun.COM 	int i;
1589*11963SAfshin.Ardakani@Sun.COM 
1590*11963SAfshin.Ardakani@Sun.COM 	idm_stat = kidmap_get_mappings(sib->sib_idmaph);
1591*11963SAfshin.Ardakani@Sun.COM 	if (idm_stat != IDMAP_SUCCESS)
1592*11963SAfshin.Ardakani@Sun.COM 		return (idm_stat);
1593*11963SAfshin.Ardakani@Sun.COM 
1594*11963SAfshin.Ardakani@Sun.COM 	/*
1595*11963SAfshin.Ardakani@Sun.COM 	 * Check the status for all the queued requests
1596*11963SAfshin.Ardakani@Sun.COM 	 */
1597*11963SAfshin.Ardakani@Sun.COM 	for (i = 0; i < sib->sib_nmap; i++) {
1598*11963SAfshin.Ardakani@Sun.COM 		if (sib->sib_maps[i].sim_stat != IDMAP_SUCCESS)
1599*11963SAfshin.Ardakani@Sun.COM 			return (sib->sib_maps[i].sim_stat);
1600*11963SAfshin.Ardakani@Sun.COM 	}
1601*11963SAfshin.Ardakani@Sun.COM 
1602*11963SAfshin.Ardakani@Sun.COM 	if (smb_idmap_batch_binsid(sib) != 0)
1603*11963SAfshin.Ardakani@Sun.COM 		idm_stat = IDMAP_ERR_OTHER;
1604*11963SAfshin.Ardakani@Sun.COM 
1605*11963SAfshin.Ardakani@Sun.COM 	return (idm_stat);
1606*11963SAfshin.Ardakani@Sun.COM }
1607*11963SAfshin.Ardakani@Sun.COM 
1608*11963SAfshin.Ardakani@Sun.COM uint64_t
1609*11963SAfshin.Ardakani@Sun.COM smb_time_unix_to_nt(timestruc_t *unix_time)
1610*11963SAfshin.Ardakani@Sun.COM {
1611*11963SAfshin.Ardakani@Sun.COM 	uint64_t nt_time;
1612*11963SAfshin.Ardakani@Sun.COM 
1613*11963SAfshin.Ardakani@Sun.COM 	if ((unix_time->tv_sec == 0) && (unix_time->tv_nsec == 0))
1614*11963SAfshin.Ardakani@Sun.COM 		return (0);
1615*11963SAfshin.Ardakani@Sun.COM 
1616*11963SAfshin.Ardakani@Sun.COM 	nt_time = unix_time->tv_sec;
1617*11963SAfshin.Ardakani@Sun.COM 	nt_time *= 10000000;  /* seconds to 100ns */
1618*11963SAfshin.Ardakani@Sun.COM 	nt_time += unix_time->tv_nsec / 100;
1619*11963SAfshin.Ardakani@Sun.COM 	return (nt_time + NT_TIME_BIAS);
1620*11963SAfshin.Ardakani@Sun.COM }
1621*11963SAfshin.Ardakani@Sun.COM 
1622*11963SAfshin.Ardakani@Sun.COM void
1623*11963SAfshin.Ardakani@Sun.COM smb_time_nt_to_unix(uint64_t nt_time, timestruc_t *unix_time)
1624*11963SAfshin.Ardakani@Sun.COM {
1625*11963SAfshin.Ardakani@Sun.COM 	uint32_t seconds;
1626*11963SAfshin.Ardakani@Sun.COM 
1627*11963SAfshin.Ardakani@Sun.COM 	ASSERT(unix_time);
1628*11963SAfshin.Ardakani@Sun.COM 
1629*11963SAfshin.Ardakani@Sun.COM 	if ((nt_time == 0) || (nt_time == -1)) {
1630*11963SAfshin.Ardakani@Sun.COM 		unix_time->tv_sec = 0;
1631*11963SAfshin.Ardakani@Sun.COM 		unix_time->tv_nsec = 0;
1632*11963SAfshin.Ardakani@Sun.COM 		return;
1633*11963SAfshin.Ardakani@Sun.COM 	}
1634*11963SAfshin.Ardakani@Sun.COM 
1635*11963SAfshin.Ardakani@Sun.COM 	nt_time -= NT_TIME_BIAS;
1636*11963SAfshin.Ardakani@Sun.COM 	seconds = nt_time / 10000000;
1637*11963SAfshin.Ardakani@Sun.COM 	unix_time->tv_sec = seconds;
1638*11963SAfshin.Ardakani@Sun.COM 	unix_time->tv_nsec = (nt_time  % 10000000) * 100;
1639*11963SAfshin.Ardakani@Sun.COM }
1640*11963SAfshin.Ardakani@Sun.COM 
1641*11963SAfshin.Ardakani@Sun.COM /*
1642*11963SAfshin.Ardakani@Sun.COM  * smb_time_gmt_to_local, smb_time_local_to_gmt
1643*11963SAfshin.Ardakani@Sun.COM  *
1644*11963SAfshin.Ardakani@Sun.COM  * Apply the gmt offset to convert between local time and gmt
1645*11963SAfshin.Ardakani@Sun.COM  */
1646*11963SAfshin.Ardakani@Sun.COM int32_t
1647*11963SAfshin.Ardakani@Sun.COM smb_time_gmt_to_local(smb_request_t *sr, int32_t gmt)
1648*11963SAfshin.Ardakani@Sun.COM {
1649*11963SAfshin.Ardakani@Sun.COM 	if ((gmt == 0) || (gmt == -1))
1650*11963SAfshin.Ardakani@Sun.COM 		return (0);
1651*11963SAfshin.Ardakani@Sun.COM 
1652*11963SAfshin.Ardakani@Sun.COM 	return (gmt - sr->sr_gmtoff);
1653*11963SAfshin.Ardakani@Sun.COM }
1654*11963SAfshin.Ardakani@Sun.COM 
1655*11963SAfshin.Ardakani@Sun.COM int32_t
1656*11963SAfshin.Ardakani@Sun.COM smb_time_local_to_gmt(smb_request_t *sr, int32_t local)
1657*11963SAfshin.Ardakani@Sun.COM {
1658*11963SAfshin.Ardakani@Sun.COM 	if ((local == 0) || (local == -1))
1659*11963SAfshin.Ardakani@Sun.COM 		return (0);
1660*11963SAfshin.Ardakani@Sun.COM 
1661*11963SAfshin.Ardakani@Sun.COM 	return (local + sr->sr_gmtoff);
1662*11963SAfshin.Ardakani@Sun.COM }
1663*11963SAfshin.Ardakani@Sun.COM 
1664*11963SAfshin.Ardakani@Sun.COM 
1665*11963SAfshin.Ardakani@Sun.COM /*
1666*11963SAfshin.Ardakani@Sun.COM  * smb_time_dos_to_unix
1667*11963SAfshin.Ardakani@Sun.COM  *
1668*11963SAfshin.Ardakani@Sun.COM  * Convert SMB_DATE & SMB_TIME values to a unix timestamp.
1669*11963SAfshin.Ardakani@Sun.COM  *
1670*11963SAfshin.Ardakani@Sun.COM  * A date/time field of 0 means that that server file system
1671*11963SAfshin.Ardakani@Sun.COM  * assigned value need not be changed. The behaviour when the
1672*11963SAfshin.Ardakani@Sun.COM  * date/time field is set to -1 is not documented but is
1673*11963SAfshin.Ardakani@Sun.COM  * generally treated like 0.
1674*11963SAfshin.Ardakani@Sun.COM  * If date or time is 0 or -1 the unix time is returned as 0
1675*11963SAfshin.Ardakani@Sun.COM  * so that the caller can identify and handle this special case.
1676*11963SAfshin.Ardakani@Sun.COM  */
1677*11963SAfshin.Ardakani@Sun.COM int32_t
1678*11963SAfshin.Ardakani@Sun.COM smb_time_dos_to_unix(int16_t date, int16_t time)
1679*11963SAfshin.Ardakani@Sun.COM {
1680*11963SAfshin.Ardakani@Sun.COM 	struct tm	atm;
1681*11963SAfshin.Ardakani@Sun.COM 
1682*11963SAfshin.Ardakani@Sun.COM 	if (((date == 0) || (time == 0)) ||
1683*11963SAfshin.Ardakani@Sun.COM 	    ((date == -1) || (time == -1))) {
1684*11963SAfshin.Ardakani@Sun.COM 		return (0);
1685*11963SAfshin.Ardakani@Sun.COM 	}
1686*11963SAfshin.Ardakani@Sun.COM 
1687*11963SAfshin.Ardakani@Sun.COM 	atm.tm_year = ((date >>  9) & 0x3F) + 80;
1688*11963SAfshin.Ardakani@Sun.COM 	atm.tm_mon  = ((date >>  5) & 0x0F) - 1;
1689*11963SAfshin.Ardakani@Sun.COM 	atm.tm_mday = ((date >>  0) & 0x1F);
1690*11963SAfshin.Ardakani@Sun.COM 	atm.tm_hour = ((time >> 11) & 0x1F);
1691*11963SAfshin.Ardakani@Sun.COM 	atm.tm_min  = ((time >>  5) & 0x3F);
1692*11963SAfshin.Ardakani@Sun.COM 	atm.tm_sec  = ((time >>  0) & 0x1F) << 1;
1693*11963SAfshin.Ardakani@Sun.COM 
1694*11963SAfshin.Ardakani@Sun.COM 	return (smb_timegm(&atm));
1695*11963SAfshin.Ardakani@Sun.COM }
1696*11963SAfshin.Ardakani@Sun.COM 
1697*11963SAfshin.Ardakani@Sun.COM void
1698*11963SAfshin.Ardakani@Sun.COM smb_time_unix_to_dos(int32_t ux_time, int16_t *date_p, int16_t *time_p)
1699*11963SAfshin.Ardakani@Sun.COM {
1700*11963SAfshin.Ardakani@Sun.COM 	struct tm	atm;
1701*11963SAfshin.Ardakani@Sun.COM 	int		i;
1702*11963SAfshin.Ardakani@Sun.COM 	time_t		tmp_time;
1703*11963SAfshin.Ardakani@Sun.COM 
1704*11963SAfshin.Ardakani@Sun.COM 	if (ux_time == 0) {
1705*11963SAfshin.Ardakani@Sun.COM 		*date_p = 0;
1706*11963SAfshin.Ardakani@Sun.COM 		*time_p = 0;
1707*11963SAfshin.Ardakani@Sun.COM 		return;
1708*11963SAfshin.Ardakani@Sun.COM 	}
1709*11963SAfshin.Ardakani@Sun.COM 
1710*11963SAfshin.Ardakani@Sun.COM 	tmp_time = (time_t)ux_time;
1711*11963SAfshin.Ardakani@Sun.COM 	(void) smb_gmtime_r(&tmp_time, &atm);
1712*11963SAfshin.Ardakani@Sun.COM 
1713*11963SAfshin.Ardakani@Sun.COM 	if (date_p) {
1714*11963SAfshin.Ardakani@Sun.COM 		i = 0;
1715*11963SAfshin.Ardakani@Sun.COM 		i += atm.tm_year - 80;
1716*11963SAfshin.Ardakani@Sun.COM 		i <<= 4;
1717*11963SAfshin.Ardakani@Sun.COM 		i += atm.tm_mon + 1;
1718*11963SAfshin.Ardakani@Sun.COM 		i <<= 5;
1719*11963SAfshin.Ardakani@Sun.COM 		i += atm.tm_mday;
1720*11963SAfshin.Ardakani@Sun.COM 
1721*11963SAfshin.Ardakani@Sun.COM 		*date_p = (short)i;
1722*11963SAfshin.Ardakani@Sun.COM 	}
1723*11963SAfshin.Ardakani@Sun.COM 	if (time_p) {
1724*11963SAfshin.Ardakani@Sun.COM 		i = 0;
1725*11963SAfshin.Ardakani@Sun.COM 		i += atm.tm_hour;
1726*11963SAfshin.Ardakani@Sun.COM 		i <<= 6;
1727*11963SAfshin.Ardakani@Sun.COM 		i += atm.tm_min;
1728*11963SAfshin.Ardakani@Sun.COM 		i <<= 5;
1729*11963SAfshin.Ardakani@Sun.COM 		i += atm.tm_sec >> 1;
1730*11963SAfshin.Ardakani@Sun.COM 
1731*11963SAfshin.Ardakani@Sun.COM 		*time_p = (short)i;
1732*11963SAfshin.Ardakani@Sun.COM 	}
1733*11963SAfshin.Ardakani@Sun.COM }
1734*11963SAfshin.Ardakani@Sun.COM 
1735*11963SAfshin.Ardakani@Sun.COM 
1736*11963SAfshin.Ardakani@Sun.COM /*
1737*11963SAfshin.Ardakani@Sun.COM  * smb_gmtime_r
1738*11963SAfshin.Ardakani@Sun.COM  *
1739*11963SAfshin.Ardakani@Sun.COM  * Thread-safe version of smb_gmtime. Returns a null pointer if either
1740*11963SAfshin.Ardakani@Sun.COM  * input parameter is a null pointer. Otherwise returns a pointer
1741*11963SAfshin.Ardakani@Sun.COM  * to result.
1742*11963SAfshin.Ardakani@Sun.COM  *
1743*11963SAfshin.Ardakani@Sun.COM  * Day of the week calculation: the Epoch was a thursday.
1744*11963SAfshin.Ardakani@Sun.COM  *
1745*11963SAfshin.Ardakani@Sun.COM  * There are no timezone corrections so tm_isdst and tm_gmtoff are
1746*11963SAfshin.Ardakani@Sun.COM  * always zero, and the zone is always WET.
1747*11963SAfshin.Ardakani@Sun.COM  */
1748*11963SAfshin.Ardakani@Sun.COM struct tm *
1749*11963SAfshin.Ardakani@Sun.COM smb_gmtime_r(time_t *clock, struct tm *result)
1750*11963SAfshin.Ardakani@Sun.COM {
1751*11963SAfshin.Ardakani@Sun.COM 	time_t tsec;
1752*11963SAfshin.Ardakani@Sun.COM 	int year;
1753*11963SAfshin.Ardakani@Sun.COM 	int month;
1754*11963SAfshin.Ardakani@Sun.COM 	int sec_per_month;
1755*11963SAfshin.Ardakani@Sun.COM 
1756*11963SAfshin.Ardakani@Sun.COM 	if (clock == 0 || result == 0)
1757*11963SAfshin.Ardakani@Sun.COM 		return (0);
1758*11963SAfshin.Ardakani@Sun.COM 
1759*11963SAfshin.Ardakani@Sun.COM 	bzero(result, sizeof (struct tm));
1760*11963SAfshin.Ardakani@Sun.COM 	tsec = *clock;
1761*11963SAfshin.Ardakani@Sun.COM 	tsec -= tzh_leapcnt;
1762*11963SAfshin.Ardakani@Sun.COM 
1763*11963SAfshin.Ardakani@Sun.COM 	result->tm_wday = tsec / SECSPERDAY;
1764*11963SAfshin.Ardakani@Sun.COM 	result->tm_wday = (result->tm_wday + TM_THURSDAY) % DAYSPERWEEK;
1765*11963SAfshin.Ardakani@Sun.COM 
1766*11963SAfshin.Ardakani@Sun.COM 	year = EPOCH_YEAR;
1767*11963SAfshin.Ardakani@Sun.COM 	while (tsec >= (isleap(year) ? (SECSPERDAY * DAYSPERLYEAR) :
1768*11963SAfshin.Ardakani@Sun.COM 	    (SECSPERDAY * DAYSPERNYEAR))) {
1769*11963SAfshin.Ardakani@Sun.COM 		if (isleap(year))
1770*11963SAfshin.Ardakani@Sun.COM 			tsec -= SECSPERDAY * DAYSPERLYEAR;
1771*11963SAfshin.Ardakani@Sun.COM 		else
1772*11963SAfshin.Ardakani@Sun.COM 			tsec -= SECSPERDAY * DAYSPERNYEAR;
1773*11963SAfshin.Ardakani@Sun.COM 
1774*11963SAfshin.Ardakani@Sun.COM 		++year;
1775*11963SAfshin.Ardakani@Sun.COM 	}
1776*11963SAfshin.Ardakani@Sun.COM 
1777*11963SAfshin.Ardakani@Sun.COM 	result->tm_year = year - TM_YEAR_BASE;
1778*11963SAfshin.Ardakani@Sun.COM 	result->tm_yday = tsec / SECSPERDAY;
1779*11963SAfshin.Ardakani@Sun.COM 
1780*11963SAfshin.Ardakani@Sun.COM 	for (month = TM_JANUARY; month <= TM_DECEMBER; ++month) {
1781*11963SAfshin.Ardakani@Sun.COM 		sec_per_month = days_in_month[month] * SECSPERDAY;
1782*11963SAfshin.Ardakani@Sun.COM 
1783*11963SAfshin.Ardakani@Sun.COM 		if (month == TM_FEBRUARY && isleap(year))
1784*11963SAfshin.Ardakani@Sun.COM 			sec_per_month += SECSPERDAY;
1785*11963SAfshin.Ardakani@Sun.COM 
1786*11963SAfshin.Ardakani@Sun.COM 		if (tsec < sec_per_month)
1787*11963SAfshin.Ardakani@Sun.COM 			break;
1788*11963SAfshin.Ardakani@Sun.COM 
1789*11963SAfshin.Ardakani@Sun.COM 		tsec -= sec_per_month;
1790*11963SAfshin.Ardakani@Sun.COM 	}
1791*11963SAfshin.Ardakani@Sun.COM 
1792*11963SAfshin.Ardakani@Sun.COM 	result->tm_mon = month;
1793*11963SAfshin.Ardakani@Sun.COM 	result->tm_mday = (tsec / SECSPERDAY) + 1;
1794*11963SAfshin.Ardakani@Sun.COM 	tsec %= SECSPERDAY;
1795*11963SAfshin.Ardakani@Sun.COM 	result->tm_sec = tsec % 60;
1796*11963SAfshin.Ardakani@Sun.COM 	tsec /= 60;
1797*11963SAfshin.Ardakani@Sun.COM 	result->tm_min = tsec % 60;
1798*11963SAfshin.Ardakani@Sun.COM 	tsec /= 60;
1799*11963SAfshin.Ardakani@Sun.COM 	result->tm_hour = (int)tsec;
1800*11963SAfshin.Ardakani@Sun.COM 
1801*11963SAfshin.Ardakani@Sun.COM 	return (result);
1802*11963SAfshin.Ardakani@Sun.COM }
1803*11963SAfshin.Ardakani@Sun.COM 
1804*11963SAfshin.Ardakani@Sun.COM 
1805*11963SAfshin.Ardakani@Sun.COM /*
1806*11963SAfshin.Ardakani@Sun.COM  * smb_timegm
1807*11963SAfshin.Ardakani@Sun.COM  *
1808*11963SAfshin.Ardakani@Sun.COM  * Converts the broken-down time in tm to a time value, i.e. the number
1809*11963SAfshin.Ardakani@Sun.COM  * of seconds since the Epoch (00:00:00 UTC, January 1, 1970). This is
1810*11963SAfshin.Ardakani@Sun.COM  * not a POSIX or ANSI function. Per the man page, the input values of
1811*11963SAfshin.Ardakani@Sun.COM  * tm_wday and tm_yday are ignored and, as the input data is assumed to
1812*11963SAfshin.Ardakani@Sun.COM  * represent GMT, we force tm_isdst and tm_gmtoff to 0.
1813*11963SAfshin.Ardakani@Sun.COM  *
1814*11963SAfshin.Ardakani@Sun.COM  * Before returning the clock time, we use smb_gmtime_r to set up tm_wday
1815*11963SAfshin.Ardakani@Sun.COM  * and tm_yday, and bring the other fields within normal range. I don't
1816*11963SAfshin.Ardakani@Sun.COM  * think this is really how it should be done but it's convenient for
1817*11963SAfshin.Ardakani@Sun.COM  * now.
1818*11963SAfshin.Ardakani@Sun.COM  */
1819*11963SAfshin.Ardakani@Sun.COM time_t
1820*11963SAfshin.Ardakani@Sun.COM smb_timegm(struct tm *tm)
1821*11963SAfshin.Ardakani@Sun.COM {
1822*11963SAfshin.Ardakani@Sun.COM 	time_t tsec;
1823*11963SAfshin.Ardakani@Sun.COM 	int dd;
1824*11963SAfshin.Ardakani@Sun.COM 	int mm;
1825*11963SAfshin.Ardakani@Sun.COM 	int yy;
1826*11963SAfshin.Ardakani@Sun.COM 	int year;
1827*11963SAfshin.Ardakani@Sun.COM 
1828*11963SAfshin.Ardakani@Sun.COM 	if (tm == 0)
1829*11963SAfshin.Ardakani@Sun.COM 		return (-1);
1830*11963SAfshin.Ardakani@Sun.COM 
1831*11963SAfshin.Ardakani@Sun.COM 	year = tm->tm_year + TM_YEAR_BASE;
1832*11963SAfshin.Ardakani@Sun.COM 	tsec = tzh_leapcnt;
1833*11963SAfshin.Ardakani@Sun.COM 
1834*11963SAfshin.Ardakani@Sun.COM 	for (yy = EPOCH_YEAR; yy < year; ++yy) {
1835*11963SAfshin.Ardakani@Sun.COM 		if (isleap(yy))
1836*11963SAfshin.Ardakani@Sun.COM 			tsec += SECSPERDAY * DAYSPERLYEAR;
1837*11963SAfshin.Ardakani@Sun.COM 		else
1838*11963SAfshin.Ardakani@Sun.COM 			tsec += SECSPERDAY * DAYSPERNYEAR;
1839*11963SAfshin.Ardakani@Sun.COM 	}
1840*11963SAfshin.Ardakani@Sun.COM 
1841*11963SAfshin.Ardakani@Sun.COM 	for (mm = TM_JANUARY; mm < tm->tm_mon; ++mm) {
1842*11963SAfshin.Ardakani@Sun.COM 		dd = days_in_month[mm] * SECSPERDAY;
1843*11963SAfshin.Ardakani@Sun.COM 
1844*11963SAfshin.Ardakani@Sun.COM 		if (mm == TM_FEBRUARY && isleap(year))
1845*11963SAfshin.Ardakani@Sun.COM 			dd += SECSPERDAY;
1846*11963SAfshin.Ardakani@Sun.COM 
1847*11963SAfshin.Ardakani@Sun.COM 		tsec += dd;
1848*11963SAfshin.Ardakani@Sun.COM 	}
1849*11963SAfshin.Ardakani@Sun.COM 
1850*11963SAfshin.Ardakani@Sun.COM 	tsec += (tm->tm_mday - 1) * SECSPERDAY;
1851*11963SAfshin.Ardakani@Sun.COM 	tsec += tm->tm_sec;
1852*11963SAfshin.Ardakani@Sun.COM 	tsec += tm->tm_min * SECSPERMIN;
1853*11963SAfshin.Ardakani@Sun.COM 	tsec += tm->tm_hour * SECSPERHOUR;
1854*11963SAfshin.Ardakani@Sun.COM 
1855*11963SAfshin.Ardakani@Sun.COM 	tm->tm_isdst = 0;
1856*11963SAfshin.Ardakani@Sun.COM 	(void) smb_gmtime_r(&tsec, tm);
1857*11963SAfshin.Ardakani@Sun.COM 	return (tsec);
1858*11963SAfshin.Ardakani@Sun.COM }
1859*11963SAfshin.Ardakani@Sun.COM 
1860*11963SAfshin.Ardakani@Sun.COM /*
1861*11963SAfshin.Ardakani@Sun.COM  * smb_cred_set_sid
1862*11963SAfshin.Ardakani@Sun.COM  *
1863*11963SAfshin.Ardakani@Sun.COM  * Initialize the ksid based on the given smb_id_t.
1864*11963SAfshin.Ardakani@Sun.COM  */
1865*11963SAfshin.Ardakani@Sun.COM static void
1866*11963SAfshin.Ardakani@Sun.COM smb_cred_set_sid(smb_id_t *id, ksid_t *ksid)
1867*11963SAfshin.Ardakani@Sun.COM {
1868*11963SAfshin.Ardakani@Sun.COM 	char sidstr[SMB_SID_STRSZ];
1869*11963SAfshin.Ardakani@Sun.COM 	int rc;
1870*11963SAfshin.Ardakani@Sun.COM 
1871*11963SAfshin.Ardakani@Sun.COM 	ASSERT(id);
1872*11963SAfshin.Ardakani@Sun.COM 	ASSERT(id->i_sid);
1873*11963SAfshin.Ardakani@Sun.COM 
1874*11963SAfshin.Ardakani@Sun.COM 	ksid->ks_id = id->i_id;
1875*11963SAfshin.Ardakani@Sun.COM 	smb_sid_tostr(id->i_sid, sidstr);
1876*11963SAfshin.Ardakani@Sun.COM 	rc = smb_sid_splitstr(sidstr, &ksid->ks_rid);
1877*11963SAfshin.Ardakani@Sun.COM 	ASSERT(rc == 0);
1878*11963SAfshin.Ardakani@Sun.COM 
1879*11963SAfshin.Ardakani@Sun.COM 	ksid->ks_attr = id->i_attrs;
1880*11963SAfshin.Ardakani@Sun.COM 	ksid->ks_domain = ksid_lookupdomain(sidstr);
1881*11963SAfshin.Ardakani@Sun.COM }
1882*11963SAfshin.Ardakani@Sun.COM 
1883*11963SAfshin.Ardakani@Sun.COM /*
1884*11963SAfshin.Ardakani@Sun.COM  * smb_cred_set_sidlist
1885*11963SAfshin.Ardakani@Sun.COM  *
1886*11963SAfshin.Ardakani@Sun.COM  * Allocate and initialize the ksidlist based on the Windows group list of the
1887*11963SAfshin.Ardakani@Sun.COM  * access token.
1888*11963SAfshin.Ardakani@Sun.COM  */
1889*11963SAfshin.Ardakani@Sun.COM static ksidlist_t *
1890*11963SAfshin.Ardakani@Sun.COM smb_cred_set_sidlist(smb_ids_t *token_grps)
1891*11963SAfshin.Ardakani@Sun.COM {
1892*11963SAfshin.Ardakani@Sun.COM 	int i;
1893*11963SAfshin.Ardakani@Sun.COM 	ksidlist_t *lp;
1894*11963SAfshin.Ardakani@Sun.COM 
1895*11963SAfshin.Ardakani@Sun.COM 	lp = kmem_zalloc(KSIDLIST_MEM(token_grps->i_cnt), KM_SLEEP);
1896*11963SAfshin.Ardakani@Sun.COM 	lp->ksl_ref = 1;
1897*11963SAfshin.Ardakani@Sun.COM 	lp->ksl_nsid = token_grps->i_cnt;
1898*11963SAfshin.Ardakani@Sun.COM 	lp->ksl_neid = 0;
1899*11963SAfshin.Ardakani@Sun.COM 
1900*11963SAfshin.Ardakani@Sun.COM 	for (i = 0; i < lp->ksl_nsid; i++) {
1901*11963SAfshin.Ardakani@Sun.COM 		smb_cred_set_sid(&token_grps->i_ids[i], &lp->ksl_sids[i]);
1902*11963SAfshin.Ardakani@Sun.COM 		if (lp->ksl_sids[i].ks_id > IDMAP_WK__MAX_GID)
1903*11963SAfshin.Ardakani@Sun.COM 			lp->ksl_neid++;
1904*11963SAfshin.Ardakani@Sun.COM 	}
1905*11963SAfshin.Ardakani@Sun.COM 
1906*11963SAfshin.Ardakani@Sun.COM 	return (lp);
1907*11963SAfshin.Ardakani@Sun.COM }
1908*11963SAfshin.Ardakani@Sun.COM 
1909*11963SAfshin.Ardakani@Sun.COM /*
1910*11963SAfshin.Ardakani@Sun.COM  * A Solaris credential (cred_t structure) will be allocated and
1911*11963SAfshin.Ardakani@Sun.COM  * initialized based on the given Windows style user access token.
1912*11963SAfshin.Ardakani@Sun.COM  *
1913*11963SAfshin.Ardakani@Sun.COM  * cred's gid is set to the primary group of the mapped Solaris user.
1914*11963SAfshin.Ardakani@Sun.COM  * When there is no such mapped user (i.e. the mapped UID is ephemeral)
1915*11963SAfshin.Ardakani@Sun.COM  * or his/her primary group could not be obtained, cred's gid is set to
1916*11963SAfshin.Ardakani@Sun.COM  * the mapped Solaris group of token's primary group.
1917*11963SAfshin.Ardakani@Sun.COM  */
1918*11963SAfshin.Ardakani@Sun.COM cred_t *
1919*11963SAfshin.Ardakani@Sun.COM smb_cred_create(smb_token_t *token, uint32_t *privileges)
1920*11963SAfshin.Ardakani@Sun.COM {
1921*11963SAfshin.Ardakani@Sun.COM 	ksid_t			ksid;
1922*11963SAfshin.Ardakani@Sun.COM 	ksidlist_t		*ksidlist = NULL;
1923*11963SAfshin.Ardakani@Sun.COM 	smb_posix_grps_t	*posix_grps;
1924*11963SAfshin.Ardakani@Sun.COM 	cred_t			*cr;
1925*11963SAfshin.Ardakani@Sun.COM 	gid_t			gid;
1926*11963SAfshin.Ardakani@Sun.COM 
1927*11963SAfshin.Ardakani@Sun.COM 	ASSERT(token);
1928*11963SAfshin.Ardakani@Sun.COM 	ASSERT(token->tkn_posix_grps);
1929*11963SAfshin.Ardakani@Sun.COM 	posix_grps = token->tkn_posix_grps;
1930*11963SAfshin.Ardakani@Sun.COM 
1931*11963SAfshin.Ardakani@Sun.COM 	ASSERT(privileges);
1932*11963SAfshin.Ardakani@Sun.COM 
1933*11963SAfshin.Ardakani@Sun.COM 	cr = crget();
1934*11963SAfshin.Ardakani@Sun.COM 	ASSERT(cr != NULL);
1935*11963SAfshin.Ardakani@Sun.COM 
1936*11963SAfshin.Ardakani@Sun.COM 	if (!IDMAP_ID_IS_EPHEMERAL(token->tkn_user.i_id) &&
1937*11963SAfshin.Ardakani@Sun.COM 	    (posix_grps->pg_ngrps != 0)) {
1938*11963SAfshin.Ardakani@Sun.COM 		gid = posix_grps->pg_grps[0];
1939*11963SAfshin.Ardakani@Sun.COM 	} else {
1940*11963SAfshin.Ardakani@Sun.COM 		gid = token->tkn_primary_grp.i_id;
1941*11963SAfshin.Ardakani@Sun.COM 	}
1942*11963SAfshin.Ardakani@Sun.COM 
1943*11963SAfshin.Ardakani@Sun.COM 	if (crsetugid(cr, token->tkn_user.i_id, gid) != 0) {
1944*11963SAfshin.Ardakani@Sun.COM 		crfree(cr);
1945*11963SAfshin.Ardakani@Sun.COM 		return (NULL);
1946*11963SAfshin.Ardakani@Sun.COM 	}
1947*11963SAfshin.Ardakani@Sun.COM 
1948*11963SAfshin.Ardakani@Sun.COM 	if (crsetgroups(cr, posix_grps->pg_ngrps, posix_grps->pg_grps) != 0) {
1949*11963SAfshin.Ardakani@Sun.COM 		crfree(cr);
1950*11963SAfshin.Ardakani@Sun.COM 		return (NULL);
1951*11963SAfshin.Ardakani@Sun.COM 	}
1952*11963SAfshin.Ardakani@Sun.COM 
1953*11963SAfshin.Ardakani@Sun.COM 	smb_cred_set_sid(&token->tkn_user, &ksid);
1954*11963SAfshin.Ardakani@Sun.COM 	crsetsid(cr, &ksid, KSID_USER);
1955*11963SAfshin.Ardakani@Sun.COM 	smb_cred_set_sid(&token->tkn_primary_grp, &ksid);
1956*11963SAfshin.Ardakani@Sun.COM 	crsetsid(cr, &ksid, KSID_GROUP);
1957*11963SAfshin.Ardakani@Sun.COM 	smb_cred_set_sid(&token->tkn_owner, &ksid);
1958*11963SAfshin.Ardakani@Sun.COM 	crsetsid(cr, &ksid, KSID_OWNER);
1959*11963SAfshin.Ardakani@Sun.COM 	ksidlist = smb_cred_set_sidlist(&token->tkn_win_grps);
1960*11963SAfshin.Ardakani@Sun.COM 	crsetsidlist(cr, ksidlist);
1961*11963SAfshin.Ardakani@Sun.COM 
1962*11963SAfshin.Ardakani@Sun.COM 	*privileges = 0;
1963*11963SAfshin.Ardakani@Sun.COM 
1964*11963SAfshin.Ardakani@Sun.COM 	if (smb_token_query_privilege(token, SE_BACKUP_LUID))
1965*11963SAfshin.Ardakani@Sun.COM 		*privileges |= SMB_USER_PRIV_BACKUP;
1966*11963SAfshin.Ardakani@Sun.COM 
1967*11963SAfshin.Ardakani@Sun.COM 	if (smb_token_query_privilege(token, SE_RESTORE_LUID))
1968*11963SAfshin.Ardakani@Sun.COM 		*privileges |= SMB_USER_PRIV_RESTORE;
1969*11963SAfshin.Ardakani@Sun.COM 
1970*11963SAfshin.Ardakani@Sun.COM 	if (smb_token_query_privilege(token, SE_TAKE_OWNERSHIP_LUID)) {
1971*11963SAfshin.Ardakani@Sun.COM 		*privileges |= SMB_USER_PRIV_TAKE_OWNERSHIP;
1972*11963SAfshin.Ardakani@Sun.COM 		(void) crsetpriv(cr, PRIV_FILE_CHOWN, NULL);
1973*11963SAfshin.Ardakani@Sun.COM 	}
1974*11963SAfshin.Ardakani@Sun.COM 
1975*11963SAfshin.Ardakani@Sun.COM 	if (smb_token_query_privilege(token, SE_SECURITY_LUID))
1976*11963SAfshin.Ardakani@Sun.COM 		*privileges |= SMB_USER_PRIV_SECURITY;
1977*11963SAfshin.Ardakani@Sun.COM 
1978*11963SAfshin.Ardakani@Sun.COM 	return (cr);
1979*11963SAfshin.Ardakani@Sun.COM }
1980*11963SAfshin.Ardakani@Sun.COM 
1981*11963SAfshin.Ardakani@Sun.COM /*
1982*11963SAfshin.Ardakani@Sun.COM  * smb_cred_rele
1983*11963SAfshin.Ardakani@Sun.COM  *
1984*11963SAfshin.Ardakani@Sun.COM  * The reference count of the user's credential will get decremented if it
1985*11963SAfshin.Ardakani@Sun.COM  * is non-zero. Otherwise, the credential will be freed.
1986*11963SAfshin.Ardakani@Sun.COM  */
1987*11963SAfshin.Ardakani@Sun.COM void
1988*11963SAfshin.Ardakani@Sun.COM smb_cred_rele(cred_t *cr)
1989*11963SAfshin.Ardakani@Sun.COM {
1990*11963SAfshin.Ardakani@Sun.COM 	ASSERT(cr);
1991*11963SAfshin.Ardakani@Sun.COM 	crfree(cr);
1992*11963SAfshin.Ardakani@Sun.COM }
1993*11963SAfshin.Ardakani@Sun.COM 
1994*11963SAfshin.Ardakani@Sun.COM /*
1995*11963SAfshin.Ardakani@Sun.COM  * smb_cred_is_member
1996*11963SAfshin.Ardakani@Sun.COM  *
1997*11963SAfshin.Ardakani@Sun.COM  * Same as smb_token_is_member. The only difference is that
1998*11963SAfshin.Ardakani@Sun.COM  * we compare the given SID against user SID and the ksidlist
1999*11963SAfshin.Ardakani@Sun.COM  * of the user's cred.
2000*11963SAfshin.Ardakani@Sun.COM  */
2001*11963SAfshin.Ardakani@Sun.COM int
2002*11963SAfshin.Ardakani@Sun.COM smb_cred_is_member(cred_t *cr, smb_sid_t *sid)
2003*11963SAfshin.Ardakani@Sun.COM {
2004*11963SAfshin.Ardakani@Sun.COM 	ksidlist_t *ksidlist;
2005*11963SAfshin.Ardakani@Sun.COM 	ksid_t ksid1, *ksid2;
2006*11963SAfshin.Ardakani@Sun.COM 	smb_id_t id;
2007*11963SAfshin.Ardakani@Sun.COM 	int i, rc = 0;
2008*11963SAfshin.Ardakani@Sun.COM 
2009*11963SAfshin.Ardakani@Sun.COM 	ASSERT(cr);
2010*11963SAfshin.Ardakani@Sun.COM 
2011*11963SAfshin.Ardakani@Sun.COM 	bzero(&id, sizeof (smb_id_t));
2012*11963SAfshin.Ardakani@Sun.COM 	id.i_sid = sid;
2013*11963SAfshin.Ardakani@Sun.COM 	smb_cred_set_sid(&id, &ksid1);
2014*11963SAfshin.Ardakani@Sun.COM 
2015*11963SAfshin.Ardakani@Sun.COM 	ksidlist = crgetsidlist(cr);
2016*11963SAfshin.Ardakani@Sun.COM 	ASSERT(ksidlist);
2017*11963SAfshin.Ardakani@Sun.COM 	ASSERT(ksid1.ks_domain);
2018*11963SAfshin.Ardakani@Sun.COM 	ASSERT(ksid1.ks_domain->kd_name);
2019*11963SAfshin.Ardakani@Sun.COM 
2020*11963SAfshin.Ardakani@Sun.COM 	i = 0;
2021*11963SAfshin.Ardakani@Sun.COM 	ksid2 = crgetsid(cr, KSID_USER);
2022*11963SAfshin.Ardakani@Sun.COM 	do {
2023*11963SAfshin.Ardakani@Sun.COM 		ASSERT(ksid2->ks_domain);
2024*11963SAfshin.Ardakani@Sun.COM 		ASSERT(ksid2->ks_domain->kd_name);
2025*11963SAfshin.Ardakani@Sun.COM 
2026*11963SAfshin.Ardakani@Sun.COM 		if (strcmp(ksid1.ks_domain->kd_name,
2027*11963SAfshin.Ardakani@Sun.COM 		    ksid2->ks_domain->kd_name) == 0 &&
2028*11963SAfshin.Ardakani@Sun.COM 		    ksid1.ks_rid == ksid2->ks_rid) {
2029*11963SAfshin.Ardakani@Sun.COM 			rc = 1;
2030*11963SAfshin.Ardakani@Sun.COM 			break;
2031*11963SAfshin.Ardakani@Sun.COM 		}
2032*11963SAfshin.Ardakani@Sun.COM 
2033*11963SAfshin.Ardakani@Sun.COM 		ksid2 = &ksidlist->ksl_sids[i];
2034*11963SAfshin.Ardakani@Sun.COM 	} while (i++ < ksidlist->ksl_nsid);
2035*11963SAfshin.Ardakani@Sun.COM 
2036*11963SAfshin.Ardakani@Sun.COM 	ksid_rele(&ksid1);
2037*11963SAfshin.Ardakani@Sun.COM 	return (rc);
2038*11963SAfshin.Ardakani@Sun.COM }
2039*11963SAfshin.Ardakani@Sun.COM 
2040*11963SAfshin.Ardakani@Sun.COM /*
2041*11963SAfshin.Ardakani@Sun.COM  * smb_cred_create_privs
2042*11963SAfshin.Ardakani@Sun.COM  *
2043*11963SAfshin.Ardakani@Sun.COM  * Creates a duplicate credential that contains system privileges for
2044*11963SAfshin.Ardakani@Sun.COM  * certain SMB privileges: Backup and Restore.
2045*11963SAfshin.Ardakani@Sun.COM  *
2046*11963SAfshin.Ardakani@Sun.COM  */
2047*11963SAfshin.Ardakani@Sun.COM cred_t *
2048*11963SAfshin.Ardakani@Sun.COM smb_cred_create_privs(cred_t *user_cr, uint32_t privileges)
2049*11963SAfshin.Ardakani@Sun.COM {
2050*11963SAfshin.Ardakani@Sun.COM 	cred_t *cr = NULL;
2051*11963SAfshin.Ardakani@Sun.COM 
2052*11963SAfshin.Ardakani@Sun.COM 	ASSERT(user_cr != NULL);
2053*11963SAfshin.Ardakani@Sun.COM 
2054*11963SAfshin.Ardakani@Sun.COM 	if (privileges & (SMB_USER_PRIV_BACKUP | SMB_USER_PRIV_RESTORE))
2055*11963SAfshin.Ardakani@Sun.COM 		cr = crdup(user_cr);
2056*11963SAfshin.Ardakani@Sun.COM 
2057*11963SAfshin.Ardakani@Sun.COM 	if (cr == NULL)
2058*11963SAfshin.Ardakani@Sun.COM 		return (NULL);
2059*11963SAfshin.Ardakani@Sun.COM 
2060*11963SAfshin.Ardakani@Sun.COM 	if (privileges & SMB_USER_PRIV_BACKUP) {
2061*11963SAfshin.Ardakani@Sun.COM 		(void) crsetpriv(cr, PRIV_FILE_DAC_READ,
2062*11963SAfshin.Ardakani@Sun.COM 		    PRIV_FILE_DAC_SEARCH, PRIV_SYS_MOUNT, NULL);
2063*11963SAfshin.Ardakani@Sun.COM 	}
2064*11963SAfshin.Ardakani@Sun.COM 
2065*11963SAfshin.Ardakani@Sun.COM 	if (privileges & SMB_USER_PRIV_RESTORE) {
2066*11963SAfshin.Ardakani@Sun.COM 		(void) crsetpriv(cr, PRIV_FILE_DAC_WRITE,
2067*11963SAfshin.Ardakani@Sun.COM 		    PRIV_FILE_CHOWN, PRIV_FILE_CHOWN_SELF,
2068*11963SAfshin.Ardakani@Sun.COM 		    PRIV_FILE_DAC_SEARCH, PRIV_FILE_LINK_ANY,
2069*11963SAfshin.Ardakani@Sun.COM 		    PRIV_FILE_OWNER, PRIV_FILE_SETID, PRIV_SYS_LINKDIR,
2070*11963SAfshin.Ardakani@Sun.COM 		    PRIV_SYS_MOUNT, NULL);
2071*11963SAfshin.Ardakani@Sun.COM 	}
2072*11963SAfshin.Ardakani@Sun.COM 
2073*11963SAfshin.Ardakani@Sun.COM 	return (cr);
2074*11963SAfshin.Ardakani@Sun.COM }
2075*11963SAfshin.Ardakani@Sun.COM 
2076*11963SAfshin.Ardakani@Sun.COM /*
2077*11963SAfshin.Ardakani@Sun.COM  * smb_pad_align
2078*11963SAfshin.Ardakani@Sun.COM  *
2079*11963SAfshin.Ardakani@Sun.COM  * Returns the number of bytes required to pad an offset to the
2080*11963SAfshin.Ardakani@Sun.COM  * specified alignment.
2081*11963SAfshin.Ardakani@Sun.COM  */
2082*11963SAfshin.Ardakani@Sun.COM uint32_t
2083*11963SAfshin.Ardakani@Sun.COM smb_pad_align(uint32_t offset, uint32_t align)
2084*11963SAfshin.Ardakani@Sun.COM {
2085*11963SAfshin.Ardakani@Sun.COM 	uint32_t pad = offset % align;
2086*11963SAfshin.Ardakani@Sun.COM 
2087*11963SAfshin.Ardakani@Sun.COM 	if (pad != 0)
2088*11963SAfshin.Ardakani@Sun.COM 		pad = align - pad;
2089*11963SAfshin.Ardakani@Sun.COM 
2090*11963SAfshin.Ardakani@Sun.COM 	return (pad);
2091*11963SAfshin.Ardakani@Sun.COM }
2092*11963SAfshin.Ardakani@Sun.COM 
2093*11963SAfshin.Ardakani@Sun.COM /*
2094*11963SAfshin.Ardakani@Sun.COM  * smb_panic
2095*11963SAfshin.Ardakani@Sun.COM  *
2096*11963SAfshin.Ardakani@Sun.COM  * Logs the file name, function name and line number passed in and panics the
2097*11963SAfshin.Ardakani@Sun.COM  * system.
2098*11963SAfshin.Ardakani@Sun.COM  */
2099*11963SAfshin.Ardakani@Sun.COM void
2100*11963SAfshin.Ardakani@Sun.COM smb_panic(char *file, const char *func, int line)
2101*11963SAfshin.Ardakani@Sun.COM {
2102*11963SAfshin.Ardakani@Sun.COM 	cmn_err(CE_PANIC, "%s:%s:%d\n", file, func, line);
2103*11963SAfshin.Ardakani@Sun.COM }
2104