xref: /illumos-gate/usr/src/uts/common/fs/smbsrv/smb_common_transact.c (revision d00756ccb34596a328f8a15d1965da5412d366d0)
1 /*
2  * CDDL HEADER START
3  *
4  * The contents of this file are subject to the terms of the
5  * Common Development and Distribution License (the "License").
6  * You may not use this file except in compliance with the License.
7  *
8  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
9  * or http://www.opensolaris.org/os/licensing.
10  * See the License for the specific language governing permissions
11  * and limitations under the License.
12  *
13  * When distributing Covered Code, include this CDDL HEADER in each
14  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
15  * If applicable, add the following below this CDDL HEADER, with the
16  * fields enclosed by brackets "[]" replaced with your own identifying
17  * information: Portions Copyright [yyyy] [name of copyright owner]
18  *
19  * CDDL HEADER END
20  */
21 /*
22  * Copyright 2008 Sun Microsystems, Inc.  All rights reserved.
23  * Use is subject to license terms.
24  *
25  */
26 
27 #pragma ident	"%Z%%M%	%I%	%E% SMI"
28 
29 #include <smbsrv/smb_incl.h>
30 #include <smbsrv/smb_fsops.h>
31 #include <smbsrv/oem.h>
32 #include <smbsrv/nmpipes.h>
33 #include <smbsrv/mailslot.h>
34 #include <smbsrv/lmerr.h>
35 #include <smbsrv/nterror.h>
36 
37 extern int smb_maxbufsize;
38 
39 #define	MAX_SHARE_NAME_LEN	13
40 #define	SHARE_INFO_1_SIZE	(MAX_SHARE_NAME_LEN + sizeof (char) + \
41     sizeof (short) + sizeof (uint32_t))
42 
43 /*
44  * count of bytes in server response packet
45  * except parameters and data. Note that setup
46  * word count is zero.
47  */
48 #define	RESP_HEADER_LEN		24
49 
50 /*
51  * NB. I started by using common functions for transaction/transaction2
52  * and transaction_secondary/transaction2_secondary because they
53  * are respectively so similar. However, it turned out to be a bad
54  * idea because of quirky differences. Be sure if you modify one
55  * of these four functions to check and see if the modification should
56  * be applied to its peer.
57  */
58 
59 static int smb_trans_ready(struct smb_xa *);
60 static smb_sdrc_t smb_trans_dispatch(struct smb_request *, struct smb_xa *);
61 static smb_sdrc_t smb_trans2_dispatch(struct smb_request *, struct smb_xa *);
62 static smb_sdrc_t smb_nt_transact_query_quota(struct smb_request *,
63     struct smb_xa *);
64 
65 smb_sdrc_t
66 smb_com_transaction(struct smb_request *sr)
67 {
68 	int		rc;
69 	unsigned char	msrcnt, suwcnt;
70 	uint16_t	tpscnt, tdscnt, mprcnt, mdrcnt, flags;
71 	uint16_t	pscnt, psoff, dscnt, dsoff;
72 	uint32_t	timeo;
73 	struct smb_xa *xa;
74 	char *stn;
75 	int ready;
76 
77 	rc = smbsr_decode_vwv(sr, SMB_TRANSHDR_ED_FMT,
78 	    &tpscnt, &tdscnt, &mprcnt, &mdrcnt, &msrcnt, &flags,
79 	    &timeo, &pscnt, &psoff, &dscnt, &dsoff, &suwcnt);
80 
81 	if (rc != 0)
82 		return (SDRC_ERROR_REPLY);
83 
84 	xa = smb_xa_create(sr->session, sr, tpscnt, tdscnt, mprcnt, mdrcnt,
85 	    msrcnt, suwcnt);
86 	if (xa == NULL) {
87 		smbsr_error(sr, 0, ERRSRV, ERRnoroom);
88 		return (SDRC_ERROR_REPLY);
89 	}
90 
91 	/* Should be some alignment stuff here in SMB? */
92 	if (sr->smb_flg2 & SMB_FLAGS2_UNICODE) {
93 		rc = smbsr_decode_data(sr, "%.U", sr, &stn);
94 	} else {
95 		rc = smbsr_decode_data(sr, "%s", sr,  &stn);
96 	}
97 	if (rc != 0) {
98 		smb_xa_rele(sr->session, xa);
99 		return (SDRC_ERROR_REPLY);
100 	}
101 	xa->xa_smb_trans_name = MEM_STRDUP("smb", stn);
102 
103 	xa->smb_flags  = flags;
104 	xa->smb_timeout = timeo;
105 	xa->req_disp_param = pscnt;
106 	xa->req_disp_data  = dscnt;
107 
108 	if (MBC_SHADOW_CHAIN(&xa->req_setup_mb, &sr->smb_vwv,
109 	    sr->smb_vwv.chain_offset, suwcnt * 2)) {
110 		smb_xa_rele(sr->session, xa);
111 		smbsr_error(sr, 0, ERRDOS, ERRbadformat);
112 		return (SDRC_ERROR_REPLY);
113 	}
114 	if (MBC_SHADOW_CHAIN(&xa->req_param_mb, &sr->command, psoff, pscnt)) {
115 		smb_xa_rele(sr->session, xa);
116 		smbsr_error(sr, 0, ERRDOS, ERRbadformat);
117 		return (SDRC_ERROR_REPLY);
118 	}
119 	if (MBC_SHADOW_CHAIN(&xa->req_data_mb, &sr->command, dsoff, dscnt)) {
120 		smb_xa_rele(sr->session, xa);
121 		smbsr_error(sr, 0, ERRDOS, ERRbadformat);
122 		return (SDRC_ERROR_REPLY);
123 	}
124 
125 	ready = smb_trans_ready(xa);
126 
127 	if (smb_xa_open(xa)) {
128 		smb_xa_rele(sr->session, xa);
129 		smbsr_error(sr, 0, ERRDOS, ERRsrverror);
130 		return (SDRC_ERROR_REPLY);
131 	}
132 	sr->r_xa = xa;
133 
134 	if (!ready) {
135 		rc = smbsr_encode_empty_result(sr);
136 		return ((rc == 0) ? SDRC_NORMAL_REPLY : SDRC_ERROR_REPLY);
137 	}
138 
139 	if (!smb_xa_complete(xa)) {
140 		smb_xa_close(xa);
141 		smbsr_error(sr, 0, ERRDOS, ERRbadformat);
142 		return (SDRC_ERROR_REPLY);
143 	}
144 
145 	return (smb_trans_dispatch(sr, xa));
146 }
147 
148 smb_sdrc_t
149 smb_com_transaction_secondary(struct smb_request *sr)
150 {
151 	uint16_t tpscnt, tdscnt, pscnt, psdisp;
152 	uint16_t dscnt, dsoff, dsdisp, psoff;
153 	smb_xa_t *xa;
154 	int rc;
155 
156 	if ((xa = smbsr_lookup_xa(sr)) == 0) {
157 		smbsr_error(sr, 0, ERRSRV, ERRsrverror);
158 		return (SDRC_ERROR_REPLY);
159 	}
160 
161 	if (sr->session->signing.flags & SMB_SIGNING_ENABLED) {
162 		if (smb_sign_check_secondary(sr, xa->reply_seqnum) != 0) {
163 			smbsr_error(sr, NT_STATUS_ACCESS_DENIED,
164 			    ERRDOS, ERRnoaccess);
165 			return (SDRC_ERROR_REPLY);
166 		}
167 	}
168 
169 	if (xa->smb_com != SMB_COM_TRANSACTION) {
170 		return (SDRC_DROP_VC);
171 	}
172 
173 	rc = smbsr_decode_vwv(sr, SMB_TRANSSHDR_ED_FMT, &tpscnt, &tdscnt,
174 	    &pscnt, &psoff, &psdisp, &dscnt, &dsoff, &dsdisp);
175 
176 	if (rc != 0)
177 		return (SDRC_ERROR_REPLY);
178 
179 	mutex_enter(&xa->xa_mutex);
180 	xa->smb_tpscnt = tpscnt;	/* might have shrunk */
181 	xa->smb_tdscnt = tdscnt;	/* might have shrunk */
182 	xa->req_disp_param = psdisp+pscnt;
183 	xa->req_disp_data  = dsdisp+dscnt;
184 
185 	if (MBC_SHADOW_CHAIN(&xa->req_param_mb, &sr->command, psoff, pscnt)) {
186 		mutex_exit(&xa->xa_mutex);
187 		smb_xa_close(xa);
188 		smbsr_error(sr, 0, ERRDOS, ERRbadformat);
189 		return (SDRC_ERROR_REPLY);
190 	}
191 	if (MBC_SHADOW_CHAIN(&xa->req_data_mb, &sr->command, dsoff, dscnt)) {
192 		mutex_exit(&xa->xa_mutex);
193 		smb_xa_close(xa);
194 		smbsr_error(sr, 0, ERRDOS, ERRbadformat);
195 		return (SDRC_ERROR_REPLY);
196 	}
197 	mutex_exit(&xa->xa_mutex);
198 
199 	if (!smb_trans_ready(xa))
200 		return (SDRC_NO_REPLY);
201 
202 	if (!smb_xa_complete(xa))
203 		return (SDRC_NO_REPLY);
204 
205 	return (smb_trans_dispatch(sr, xa));
206 }
207 
208 smb_sdrc_t
209 smb_com_ioctl(struct smb_request *sr)
210 {
211 	uint16_t fid, category, function, tpscnt, tdscnt, mprcnt;
212 	uint16_t mdrcnt, pscnt, pdoff, dscnt, dsoff;
213 	uint32_t timeout;
214 	int rc;
215 
216 	rc = smbsr_decode_vwv(sr, "wwwwwwwl2.wwww", &fid, &category, &function,
217 	    &tpscnt, &tdscnt, &mprcnt, &mdrcnt, &timeout, &pscnt,
218 	    &pdoff, &dscnt, &dsoff);
219 
220 	if (rc != 0)
221 		return (SDRC_ERROR_REPLY);
222 
223 	return (SDRC_UNIMPLEMENTED);
224 }
225 
226 smb_sdrc_t /*ARGSUSED*/
227 smb_com_ioctl_secondary(struct smb_request *sr)
228 {
229 	return (SDRC_UNIMPLEMENTED);
230 }
231 
232 smb_sdrc_t
233 smb_com_transaction2(struct smb_request *sr)
234 {
235 	unsigned char	msrcnt, suwcnt;
236 	uint16_t	tpscnt, tdscnt, mprcnt, mdrcnt, flags;
237 	uint16_t	pscnt, psoff, dscnt, dsoff;
238 	uint32_t	timeo;
239 	smb_xa_t *xa;
240 	int ready;
241 	int rc;
242 
243 	rc = smbsr_decode_vwv(sr, SMB_TRANSHDR_ED_FMT, &tpscnt, &tdscnt,
244 	    &mprcnt, &mdrcnt, &msrcnt, &flags, &timeo, &pscnt, &psoff, &dscnt,
245 	    &dsoff, &suwcnt);
246 
247 	if (rc != 0)
248 		return (SDRC_ERROR_REPLY);
249 
250 	xa = smb_xa_create(sr->session, sr, tpscnt, tdscnt, mprcnt, mdrcnt,
251 	    msrcnt, suwcnt);
252 	if (xa == 0) {
253 		smbsr_error(sr, 0, ERRSRV, ERRnoroom);
254 		return (SDRC_ERROR_REPLY);
255 	}
256 
257 	xa->smb_flags  = flags;
258 	xa->smb_timeout = timeo;
259 	xa->req_disp_param = pscnt;
260 	xa->req_disp_data  = dscnt;
261 
262 	if (MBC_SHADOW_CHAIN(&xa->req_setup_mb, &sr->smb_vwv,
263 	    sr->smb_vwv.chain_offset, suwcnt*2)) {
264 		smb_xa_rele(sr->session, xa);
265 		smbsr_error(sr, 0, ERRDOS, ERRbadformat);
266 		return (SDRC_ERROR_REPLY);
267 	}
268 	if (MBC_SHADOW_CHAIN(&xa->req_param_mb, &sr->command, psoff, pscnt)) {
269 		smb_xa_rele(sr->session, xa);
270 		smbsr_error(sr, 0, ERRDOS, ERRbadformat);
271 		return (SDRC_ERROR_REPLY);
272 	}
273 	if (MBC_SHADOW_CHAIN(&xa->req_data_mb, &sr->command, dsoff, dscnt)) {
274 		smb_xa_rele(sr->session, xa);
275 		smbsr_error(sr, 0, ERRDOS, ERRbadformat);
276 		return (SDRC_ERROR_REPLY);
277 	}
278 
279 	ready = smb_trans_ready(xa);
280 
281 	if (smb_xa_open(xa)) {
282 		smb_xa_rele(sr->session, xa);
283 		smbsr_error(sr, 0, ERRDOS, ERRsrverror);
284 		return (SDRC_ERROR_REPLY);
285 	}
286 	sr->r_xa = xa;
287 
288 	if (!ready) {
289 		rc = smbsr_encode_empty_result(sr);
290 		return ((rc == 0) ? SDRC_NORMAL_REPLY : SDRC_ERROR_REPLY);
291 	}
292 
293 	if (!smb_xa_complete(xa)) {
294 		smb_xa_close(xa);
295 		smbsr_error(sr, 0, ERRDOS, ERRbadformat);
296 		return (SDRC_ERROR_REPLY);
297 	}
298 
299 	return (smb_trans2_dispatch(sr, xa));
300 }
301 
302 smb_sdrc_t
303 smb_com_transaction2_secondary(struct smb_request *sr)
304 {
305 	uint16_t tpscnt, tdscnt, fid;
306 	uint16_t pscnt, psoff, psdisp, dscnt, dsoff, dsdisp;
307 	smb_xa_t *xa;
308 	int rc;
309 
310 	if ((xa = smbsr_lookup_xa(sr)) == 0) {
311 		smbsr_error(sr, 0, ERRSRV, ERRsrverror);
312 		return (SDRC_ERROR_REPLY);
313 	}
314 
315 	if (sr->session->signing.flags & SMB_SIGNING_ENABLED) {
316 		if (smb_sign_check_secondary(sr, xa->reply_seqnum) != 0) {
317 			smbsr_error(sr, NT_STATUS_ACCESS_DENIED,
318 			    ERRDOS, ERRnoaccess);
319 			return (SDRC_ERROR_REPLY);
320 		}
321 	}
322 
323 	if (xa->smb_com != SMB_COM_TRANSACTION2) {
324 		return (SDRC_DROP_VC);
325 	}
326 
327 	rc = smbsr_decode_vwv(sr, SMB_TRANS2SHDR_ED_FMT, &tpscnt, &tdscnt,
328 	    &pscnt, &psoff, &psdisp, &dscnt, &dsoff, &dsdisp, &fid);
329 
330 	if (rc != 0)
331 		return (SDRC_ERROR_REPLY);
332 
333 	mutex_enter(&xa->xa_mutex);
334 	xa->smb_tpscnt = tpscnt;	/* might have shrunk */
335 	xa->smb_tdscnt = tdscnt;	/* might have shrunk */
336 	xa->xa_smb_fid = fid;		/* overwrite rules? */
337 	xa->req_disp_param = psdisp + pscnt;
338 	xa->req_disp_data  = dsdisp + dscnt;
339 
340 	if (MBC_SHADOW_CHAIN(&xa->req_param_mb, &sr->command, psoff, pscnt)) {
341 		mutex_exit(&xa->xa_mutex);
342 		smb_xa_close(xa);
343 		smbsr_error(sr, 0, ERRDOS, ERRbadformat);
344 		return (SDRC_ERROR_REPLY);
345 	}
346 	if (MBC_SHADOW_CHAIN(&xa->req_data_mb, &sr->command, dsoff, dscnt)) {
347 		mutex_exit(&xa->xa_mutex);
348 		smb_xa_close(xa);
349 		smbsr_error(sr, 0, ERRDOS, ERRbadformat);
350 		return (SDRC_ERROR_REPLY);
351 	}
352 	mutex_exit(&xa->xa_mutex);
353 
354 	if (!smb_trans_ready(xa))
355 		return (SDRC_NO_REPLY);
356 
357 	if (!smb_xa_complete(xa))
358 		return (SDRC_NO_REPLY);
359 
360 	return (smb_trans2_dispatch(sr, xa));
361 }
362 
363 static smb_sdrc_t
364 smb_nt_trans_dispatch(struct smb_request *sr, struct smb_xa *xa)
365 {
366 	int rc;
367 	int total_bytes, n_setup, n_param, n_data;
368 	int param_off, param_pad, data_off, data_pad;
369 
370 	n_setup = (xa->smb_msrcnt < 200) ? xa->smb_msrcnt : 200;
371 	n_setup++;
372 	n_setup = n_setup & ~0x0001;
373 	n_param = (xa->smb_mprcnt < smb_maxbufsize)
374 	    ? xa->smb_mprcnt : smb_maxbufsize;
375 	n_param++;
376 	n_param = n_param & ~0x0001;
377 	rc = smb_maxbufsize - (SMBHEADERSIZE + 28 + n_setup + n_param);
378 	n_data = (xa->smb_mdrcnt < rc) ? xa->smb_mdrcnt : rc;
379 	MBC_INIT(&xa->rep_setup_mb, n_setup * 2);
380 	MBC_INIT(&xa->rep_param_mb, n_param);
381 	MBC_INIT(&xa->rep_data_mb, n_data);
382 
383 	switch (xa->smb_func) {
384 	case NT_TRANSACT_CREATE:
385 		rc = smb_nt_transact_create(sr, xa);
386 		break;
387 	case NT_TRANSACT_NOTIFY_CHANGE:
388 		rc = smb_nt_transact_notify_change(sr, xa);
389 		break;
390 	case NT_TRANSACT_QUERY_SECURITY_DESC:
391 		rc = smb_nt_transact_query_security_info(sr, xa);
392 		break;
393 	case NT_TRANSACT_SET_SECURITY_DESC:
394 		rc = smb_nt_transact_set_security_info(sr, xa);
395 		break;
396 	case NT_TRANSACT_IOCTL:
397 		rc = smb_nt_transact_ioctl(sr, xa);
398 		break;
399 
400 	case NT_TRANSACT_QUERY_QUOTA:
401 		(void) smb_nt_transact_query_quota(sr, xa);
402 		smbsr_error(sr, 0, ERRSRV, ERRaccess);
403 		return (SDRC_ERROR_REPLY);
404 
405 	case NT_TRANSACT_SET_QUOTA:
406 		smbsr_error(sr, 0, ERRSRV, ERRaccess);
407 		return (SDRC_ERROR_REPLY);
408 
409 	default:
410 		smbsr_error(sr, 0, ERRSRV, ERRsmbcmd);
411 		return (SDRC_ERROR_REPLY);
412 	}
413 
414 	switch (rc) {
415 	case SDRC_NORMAL_REPLY:
416 		break;
417 
418 	case SDRC_DROP_VC:
419 	case SDRC_NO_REPLY:
420 	case SDRC_ERROR_REPLY:
421 		return (rc);
422 
423 	case SDRC_UNIMPLEMENTED:
424 	case SDRC_UNSUPPORTED:
425 		smbsr_error(sr, 0, ERRSRV, ERRsmbcmd);
426 		return (SDRC_ERROR_REPLY);
427 
428 	default:
429 		break;
430 	}
431 
432 	n_setup = MBC_LENGTH(&xa->rep_setup_mb);
433 	n_param = MBC_LENGTH(&xa->rep_param_mb);
434 	n_data  = MBC_LENGTH(&xa->rep_data_mb);
435 
436 	if (xa->smb_msrcnt < n_setup ||
437 	    xa->smb_mprcnt < n_param ||
438 	    xa->smb_mdrcnt < n_data) {
439 		smbsr_error(sr, 0, ERRSRV, ERRsmbcmd);
440 		return (SDRC_ERROR_REPLY);
441 	}
442 
443 	/* neato, blast it over there */
444 
445 	n_setup = (n_setup + 1) / 2;		/* Conver to setup words */
446 	param_pad = 1;				/* must be one */
447 	param_off = param_pad + 32 + 37 + (n_setup << 1) + 2;
448 	data_pad = (4 - ((param_off + n_param) & 3)) % 4; /* Pad to 4 byte */
449 	data_off = param_off + n_param + data_pad; /* Param off from hdr */
450 	total_bytes = param_pad + n_param + data_pad + n_data;
451 
452 	rc = smbsr_encode_result(sr, 18+n_setup, total_bytes,
453 	    "b 3. llllllllb C w #. C #. C",
454 	    18 + n_setup,		/* wct */
455 	    n_param,			/* Total Parameter Bytes */
456 	    n_data,			/* Total Data Bytes */
457 	    n_param,			/* Total Parameter Bytes this buffer */
458 	    param_off,			/* Param offset from header start */
459 	    0,				/* Param displacement */
460 	    n_data,			/* Total Data Bytes this buffer */
461 	    data_off,			/* Data offset from header start */
462 	    0,				/* Data displacement */
463 	    n_setup,			/* suwcnt */
464 	    &xa->rep_setup_mb,		/* setup[] */
465 	    total_bytes,		/* Total data bytes */
466 	    param_pad,
467 	    &xa->rep_param_mb,
468 	    data_pad,
469 	    &xa->rep_data_mb);
470 	return ((rc == 0) ? SDRC_NORMAL_REPLY : SDRC_ERROR_REPLY);
471 }
472 
473 
474 /*
475  * smb_nt_transact_query_quota
476  *
477  * There are 16 parameter bytes: fid, flags and 12 zero bytes.
478  */
479 static smb_sdrc_t
480 smb_nt_transact_query_quota(struct smb_request *sr, struct smb_xa *xa)
481 {
482 	uint16_t fid;
483 	uint16_t flags;
484 
485 	if (smb_decode_mbc(&xa->req_param_mb, "%ww", sr, &fid, &flags))
486 		return (SDRC_ERROR_REPLY);
487 
488 	return (SDRC_NORMAL_REPLY);
489 }
490 
491 
492 smb_sdrc_t
493 smb_com_nt_transact(struct smb_request *sr)
494 {
495 	uint16_t	Function;
496 	unsigned char	MaxSetupCount, SetupCount;
497 	uint32_t	TotalParameterCount, TotalDataCount;
498 	uint32_t	MaxParameterCount, MaxDataCount, pscnt;
499 	uint32_t	psoff, dscnt, dsoff;
500 	smb_xa_t *xa;
501 	int ready;
502 	int rc;
503 
504 	rc = smbsr_decode_vwv(sr, SMB_NT_TRANSHDR_ED_FMT, &MaxSetupCount,
505 	    &TotalParameterCount, &TotalDataCount, &MaxParameterCount,
506 	    &MaxDataCount, &pscnt, &psoff, &dscnt,
507 	    &dsoff, &SetupCount, &Function);
508 
509 	if (rc != 0)
510 		return (SDRC_ERROR_REPLY);
511 
512 	xa = smb_xa_create(sr->session, sr, TotalParameterCount, TotalDataCount,
513 	    MaxParameterCount, MaxDataCount, MaxSetupCount, SetupCount);
514 	if (xa == 0) {
515 		smbsr_error(sr, 0, ERRSRV, ERRnoroom);
516 		return (SDRC_ERROR_REPLY);
517 	}
518 
519 	xa->smb_flags  = 0;
520 	xa->smb_timeout = 0;
521 	xa->smb_func = Function;
522 	xa->req_disp_param = pscnt;
523 	xa->req_disp_data  = dscnt;
524 
525 	if (MBC_SHADOW_CHAIN(&xa->req_setup_mb, &sr->smb_vwv,
526 	    sr->smb_vwv.chain_offset, SetupCount * 2)) {
527 		smb_xa_rele(sr->session, xa);
528 		smbsr_error(sr, 0, ERRDOS, ERRbadformat);
529 		return (SDRC_ERROR_REPLY);
530 	}
531 	if (MBC_SHADOW_CHAIN(&xa->req_param_mb, &sr->command, psoff, pscnt)) {
532 		smb_xa_rele(sr->session, xa);
533 		smbsr_error(sr, 0, ERRDOS, ERRbadformat);
534 		return (SDRC_ERROR_REPLY);
535 	}
536 	if (MBC_SHADOW_CHAIN(&xa->req_data_mb, &sr->command, dsoff, dscnt)) {
537 		smb_xa_rele(sr->session, xa);
538 		smbsr_error(sr, 0, ERRDOS, ERRbadformat);
539 		return (SDRC_ERROR_REPLY);
540 	}
541 
542 	ready = smb_trans_ready(xa);
543 
544 	if (smb_xa_open(xa)) {
545 		smb_xa_rele(sr->session, xa);
546 		smbsr_error(sr, 0, ERRDOS, ERRsrverror);
547 		return (SDRC_ERROR_REPLY);
548 	}
549 	sr->r_xa = xa;
550 
551 	if (!ready) {
552 		rc = smbsr_encode_empty_result(sr);
553 		return ((rc == 0) ? SDRC_NORMAL_REPLY : SDRC_ERROR_REPLY);
554 	}
555 
556 	if (!smb_xa_complete(xa)) {
557 		smb_xa_close(xa);
558 		smbsr_error(sr, 0, ERRDOS, ERRbadformat);
559 		return (SDRC_ERROR_REPLY);
560 	}
561 
562 	return (smb_nt_trans_dispatch(sr, xa));
563 }
564 
565 
566 smb_sdrc_t
567 smb_com_nt_transact_secondary(struct smb_request *sr)
568 {
569 	uint16_t tpscnt, tdscnt, fid;
570 	uint16_t pscnt, psoff, psdisp, dscnt, dsoff, dsdisp;
571 	smb_xa_t *xa;
572 	int rc;
573 
574 	if ((xa = smbsr_lookup_xa(sr)) == 0) {
575 		smbsr_error(sr, 0, ERRSRV, ERRsrverror);
576 		return (SDRC_ERROR_REPLY);
577 	}
578 
579 	if (sr->session->signing.flags & SMB_SIGNING_ENABLED) {
580 		if (smb_sign_check_secondary(sr, xa->reply_seqnum) != 0) {
581 			smbsr_error(sr, NT_STATUS_ACCESS_DENIED,
582 			    ERRDOS, ERRnoaccess);
583 			return (SDRC_ERROR_REPLY);
584 		}
585 	}
586 
587 	if (xa->smb_com != SMB_COM_TRANSACTION2) {
588 		return (SDRC_DROP_VC);
589 	}
590 
591 	rc = smbsr_decode_vwv(sr, SMB_TRANS2SHDR_ED_FMT, &tpscnt, &tdscnt,
592 	    &pscnt, &psoff, &psdisp, &dscnt, &dsoff, &dsdisp, &fid);
593 
594 	if (rc != 0)
595 		return (SDRC_ERROR_REPLY);
596 
597 	mutex_enter(&xa->xa_mutex);
598 	xa->smb_tpscnt = tpscnt;	/* might have shrunk */
599 	xa->smb_tdscnt = tdscnt;	/* might have shrunk */
600 	xa->xa_smb_fid = fid;		/* overwrite rules? */
601 	xa->req_disp_param = psdisp+pscnt;
602 	xa->req_disp_data  = dsdisp+dscnt;
603 
604 	if (MBC_SHADOW_CHAIN(&xa->req_param_mb, &sr->command, psoff, pscnt)) {
605 		mutex_exit(&xa->xa_mutex);
606 		smb_xa_close(xa);
607 		smbsr_error(sr, 0, ERRDOS, ERRbadformat);
608 		return (SDRC_ERROR_REPLY);
609 	}
610 	if (MBC_SHADOW_CHAIN(&xa->req_data_mb, &sr->command, dsoff, dscnt)) {
611 		mutex_exit(&xa->xa_mutex);
612 		smb_xa_close(xa);
613 		smbsr_error(sr, 0, ERRDOS, ERRbadformat);
614 		return (SDRC_ERROR_REPLY);
615 	}
616 	mutex_exit(&xa->xa_mutex);
617 
618 	if (!smb_trans_ready(xa))
619 		return (SDRC_NO_REPLY);
620 
621 	if (!smb_xa_complete(xa))
622 		return (SDRC_NO_REPLY);
623 
624 	return (smb_nt_trans_dispatch(sr, xa));
625 }
626 
627 static int
628 smb_trans_ready(struct smb_xa *xa)
629 {
630 	int rc;
631 
632 	mutex_enter(&xa->xa_mutex);
633 	rc = xa->req_disp_data >= xa->smb_tdscnt &&
634 	    xa->req_disp_param >= xa->smb_tpscnt;
635 	mutex_exit(&xa->xa_mutex);
636 
637 	return (rc);
638 }
639 
640 
641 /*
642  * smb_emit_SHARE_INFO_0
643  *
644  * This function will convert unicode chars to oem chars before
645  * and store the result in a fixed length, MAX_SHARE_NAME_LEN, buffer. If the
646  * length after conversion is longer than 12, -1 will be reported
647  * to indicate an error. The fixed length is a limitation of the
648  * smb protocol.
649  */
650 static int
651 smb_emit_SHARE_INFO_0(struct mbuf_chain *output, unsigned char *name)
652 {
653 	mts_wchar_t *unibuf;
654 	char *tmpbuf;
655 	unsigned int cpid = oem_get_smb_cpid();
656 	unsigned int length;
657 	char	name_buf[MAX_SHARE_NAME_LEN];
658 
659 	if (name == 0)
660 		tmpbuf = "";
661 	else
662 		tmpbuf = (char *)name;
663 
664 	length = strlen(tmpbuf) + 1;
665 	unibuf = MEM_MALLOC("smb", length * sizeof (mts_wchar_t));
666 
667 	(void) mts_mbstowcs(unibuf, tmpbuf, length);
668 	tmpbuf = MEM_MALLOC("smb", length);
669 	if (unicodestooems(tmpbuf, unibuf, length, cpid) == 0)
670 		(void) strcpy(tmpbuf, (char *)name);
671 
672 	if (strlen(tmpbuf) + 1 > MAX_SHARE_NAME_LEN) {
673 		MEM_FREE("smb", unibuf);
674 		MEM_FREE("smb", tmpbuf);
675 		return (-1);
676 	}
677 
678 	bzero(name_buf, sizeof (name_buf));
679 	(void) strcpy(name_buf, tmpbuf);
680 	(void) smb_encode_mbc(output, "13c", name_buf);
681 
682 	MEM_FREE("smb", unibuf);
683 	MEM_FREE("smb", tmpbuf);
684 
685 	return (0);
686 }
687 
688 static int
689 smb_emit_SHARE_INFO_1(struct mbuf_chain *output, struct mbuf_chain *text,
690     unsigned char *name, uint16_t type,
691     unsigned char *comment)
692 {
693 	if (smb_emit_SHARE_INFO_0(output, name) < 0)
694 		return (-1);
695 
696 	(void) smb_encode_mbc(output, ".wl", type, MBC_LENGTH(text));
697 	(void) smb_encode_mbc(text, "s",
698 	    (comment ? comment : (unsigned char *)"No comment"));
699 	return (0);
700 }
701 
702 static void /*ARGSUSED*/
703 smb_emit_SHARE_INFO_2(struct mbuf_chain *output, struct mbuf_chain *text,
704 	struct smb_request *sr, unsigned char *name, uint16_t type,
705 	unsigned char *comment, uint16_t access, char *path, char *password)
706 {
707 	unsigned char	pword[9];
708 
709 	/*
710 	 * XXX PGD.  Is there a bug here?  We zero pword, copy password
711 	 * into pword then ignore it and use password for smb_encode_mbc?
712 	 */
713 	bzero(pword, sizeof (pword));
714 	(void) strncpy((char *)pword, password, sizeof (pword));
715 	(void) smb_emit_SHARE_INFO_1(output, text, name, type, comment);
716 	(void) smb_encode_mbc(output, "wwwl9c.",
717 	    access,
718 	    smb_info.si.skc_maxconnections,
719 	    smb_svcstate_session_count(&smb_info.si_svc_sm_ctx),
720 	    MBC_LENGTH(text),
721 	    password);
722 	(void) smb_encode_mbc(text, "s", path);
723 }
724 
725 /*
726  * is_long_sharename
727  *
728  * This function is extracted from smb_emit_SHARE_INFO_0 only for
729  * finding shares that their names are longer than MAX_SHARE_NAME_LEN.
730  *
731  * The function returns 1 for long share names and 0 when the length
732  * is Ok.
733  */
734 static int
735 is_long_sharename(unsigned char *name)
736 {
737 	mts_wchar_t *unibuf;
738 	char *tmpbuf;
739 	unsigned int cpid = oem_get_smb_cpid();
740 	unsigned int length;
741 
742 	if (name == 0)
743 		tmpbuf = "";
744 	else
745 		tmpbuf = (char *)name;
746 
747 	length = strlen(tmpbuf) + 1;
748 	unibuf = MEM_MALLOC("smb", length * sizeof (mts_wchar_t));
749 	(void) mts_mbstowcs(unibuf, tmpbuf, length);
750 	tmpbuf = MEM_MALLOC("smb", length);
751 	if (unicodestooems(tmpbuf, unibuf, length, cpid) == 0)
752 		(void) strcpy(tmpbuf, (char *)name);
753 
754 	if (strlen(tmpbuf) + 1 > MAX_SHARE_NAME_LEN) {
755 		MEM_FREE("smb", unibuf);
756 		MEM_FREE("smb", tmpbuf);
757 		return (1);
758 	}
759 
760 	MEM_FREE("smb", unibuf);
761 	MEM_FREE("smb", tmpbuf);
762 
763 	return (0);
764 }
765 
766 /*
767  * This structure holds information about shares which will
768  * fit in the specified client buffer size.
769  *
770  * sei_bufsize: Client specified buffer size
771  * sei_count: Maximum number of shares that can be
772  *            sent in the buffer.
773  *
774  * The return data section consists of a number of SHARE_INFO_1 structures.
775  * In case there are multiple SHARE_INFO_1 data structures to return this
776  * function put all fixed length part of these structures in the return buffer
777  * and then put all the variable length data (shares' comment) at the end of
778  * buffer.
779  *
780  * sei_info_len: Size of fixed length part of SHARE_INFO_1
781  *               structures for sei_count shares
782  * sei_cmnt_len: Size of comments for sei_count shares
783  */
784 typedef struct {
785 	uint16_t sei_bufsize;
786 	short sei_count;
787 	int   sei_infolen;
788 	int   sei_cmntlen;
789 } smb_share_enum_t;
790 
791 /*
792  * smb_share_update_info
793  *
794  * Check to see if the given buffer has enough
795  * room to fit the information of the given share.
796  * If there is enough room update the passed max_???
797  * information.
798  *
799  * Return 1 if buffer is not full yet, 0 if it's full.
800  */
801 static int
802 smb_share_update_info(lmshare_info_t *si, smb_share_enum_t *shr_enum_info)
803 {
804 	int cmnt_len;
805 	int new_info_len = shr_enum_info->sei_infolen;
806 	int new_cmnt_len = shr_enum_info->sei_cmntlen;
807 
808 	if (lmshrd_is_special(si->share_name))
809 		cmnt_len = 1;
810 	else
811 		cmnt_len = (strlen(si->comment) + 1);
812 
813 	new_info_len += SHARE_INFO_1_SIZE;
814 	new_cmnt_len += cmnt_len;
815 
816 	if ((new_info_len + new_cmnt_len) < shr_enum_info->sei_bufsize) {
817 		shr_enum_info->sei_count++;
818 		shr_enum_info->sei_infolen = new_info_len;
819 		shr_enum_info->sei_cmntlen = new_cmnt_len;
820 		return (1);
821 	}
822 
823 	return (0);
824 }
825 
826 /*
827  * smb_share_skip_share
828  *
829  * Determines whether the given share should be enumerated
830  * or not. The share will not be enumerated if its name is
831  * long or it's autohome share.
832  *
833  * Return 1 if the share should be skipped; otherwise returns
834  * 0
835  */
836 static int
837 smb_share_skip_share(lmshare_info_t *si)
838 {
839 	if (is_long_sharename((unsigned char *)si->share_name)) {
840 		return (1);
841 	}
842 
843 	/* Skip autohome share if autohome filter is enabled */
844 	if (si->mode == LMSHRM_TRANS) {
845 		return (1);
846 	}
847 
848 	return (0);
849 }
850 
851 /*
852  * smb_share_add_autohome
853  *
854  * Determines if an autohome share should be added to shares' list
855  * for the given user.
856  * Autohome will be add when all the following conditions are true:
857  *
858  *  1. Autohome feature is enabled
859  *  2. A share with the same name as the given user exists
860  *  3. The share is not a permanent share
861  *  4. Share name is not longer than maximum allowed
862  */
863 static int
864 smb_share_add_autohome(char *username, lmshare_info_t *si)
865 {
866 	int do_add = 0;
867 
868 	do_add = (lmshrd_getinfo(username, si) == NERR_Success) &&
869 	    (si->mode & LMSHRM_TRANS) &&
870 	    (is_long_sharename((unsigned char *)(si->share_name)) == 0);
871 
872 	return (do_add);
873 }
874 
875 /*
876  * smb_share_total_info
877  *
878  * This function calculates following informations
879  *	- Maximum number of shares that can be sent for clients
880  *	  according to its buffer size (cli_bufsize)
881  *	- length of fixed information about above shares
882  *	- length of comments of above shares
883  *	- total number of shares that their names are no longer
884  *	  than MAX_SHARE_NAME_LEN.
885  *
886  * Added SMB user object to the parameter list to filter out other
887  * user autohome shares.
888  */
889 static void
890 smb_share_total_info(smb_share_enum_t *shr_enum_info, short *tot_shares_num,
891     smb_user_t *user)
892 {
893 	uint64_t iterator;
894 	lmshare_info_t *si;
895 	struct lmshare_info *auto_si;
896 	int more_room = 1;
897 
898 	si = kmem_zalloc(sizeof (lmshare_info_t), KM_SLEEP);
899 	auto_si = kmem_zalloc(sizeof (struct lmshare_info), KM_SLEEP);
900 
901 	*tot_shares_num = 0;
902 	shr_enum_info->sei_count = 0;
903 	shr_enum_info->sei_infolen = 0;
904 	shr_enum_info->sei_cmntlen = 0;
905 
906 	if (smb_share_add_autohome(user->u_name, auto_si)) {
907 		(*tot_shares_num)++;
908 		more_room = smb_share_update_info(auto_si, shr_enum_info);
909 	}
910 
911 	iterator = lmshrd_open_iterator(LMSHRM_ALL);
912 	if (iterator == 0) {
913 		kmem_free(si, sizeof (lmshare_info_t));
914 		kmem_free(auto_si, sizeof (struct lmshare_info));
915 		return;
916 	}
917 
918 	/* check for door errors */
919 	if (lmshrd_iterate(iterator, si) != NERR_Success) {
920 		(void) lmshrd_close_iterator(iterator);
921 		kmem_free(si, sizeof (lmshare_info_t));
922 		kmem_free(auto_si, sizeof (struct lmshare_info));
923 		return;
924 	}
925 
926 	while (*si->share_name != 0) {
927 		if (smb_share_skip_share(si)) {
928 			/* check for door errors */
929 			if (lmshrd_iterate(iterator, si) != NERR_Success) {
930 				(void) lmshrd_close_iterator(iterator);
931 				kmem_free(si, sizeof (lmshare_info_t));
932 				kmem_free(auto_si,
933 				    sizeof (struct lmshare_info));
934 				return;
935 			}
936 			continue;
937 		}
938 
939 		(*tot_shares_num)++;
940 
941 		if (more_room) {
942 			more_room = smb_share_update_info(si, shr_enum_info);
943 		}
944 
945 		/* check for door errors */
946 		if (lmshrd_iterate(iterator, si) != NERR_Success) {
947 			(void) lmshrd_close_iterator(iterator);
948 			kmem_free(si, sizeof (lmshare_info_t));
949 			kmem_free(auto_si, sizeof (struct lmshare_info));
950 			return;
951 		}
952 	}
953 
954 	(void) lmshrd_close_iterator(iterator);
955 	kmem_free(si, sizeof (lmshare_info_t));
956 	kmem_free(auto_si, sizeof (struct lmshare_info));
957 }
958 
959 /*
960  * smb_encode_SHARE_INFO_1
961  *
962  * This function is extracted from smb_emit_SHARE_INFO_1 and only
963  * encodes fixed part of SHARE_INFO_1 structure.
964  *
965  * The function returns -1 if encoding fails and 0 on success.
966  */
967 static int
968 smb_encode_SHARE_INFO_1(struct mbuf_chain *output, unsigned char *name,
969     uint16_t type, int cmnt_len)
970 {
971 	if (smb_emit_SHARE_INFO_0(output, name) < 0)
972 		return (-1);
973 	(void) smb_encode_mbc(output, ".wl", type, cmnt_len);
974 	return (0);
975 }
976 
977 /*
978  * collect_shares_info
979  *
980  * This function encodes information of shares_num of shares
981  * into data_mb and cmnt_str.
982  *
983  * Added SMB user object to the parameter list to filter out other
984  * user autohome shares.
985  *
986  */
987 static void
988 collect_shares_info(uint64_t iterator, int shares_num,
989     struct mbuf_chain *data_mb,
990     char *cmnt_str, int *cmnt_len,
991     smb_user_t *user, int first_resp)
992 {
993 	int i = 0;
994 	lmshare_info_t *si;
995 	struct lmshare_info *tsi;
996 	int is_special;
997 
998 	si = kmem_zalloc(sizeof (lmshare_info_t), KM_SLEEP);
999 	tsi = kmem_zalloc(sizeof (struct lmshare_info), KM_SLEEP);
1000 
1001 	if (first_resp && smb_share_add_autohome(user->u_name, tsi)) {
1002 		if (smb_encode_SHARE_INFO_1(data_mb,
1003 		    (unsigned char *)tsi->share_name,
1004 		    tsi->stype, *cmnt_len) == 0) {
1005 			(void) memcpy(cmnt_str+(*cmnt_len),
1006 			    tsi->comment, strlen(tsi->comment)+1);
1007 			(*cmnt_len) += (strlen(tsi->comment) + 1);
1008 			i++;
1009 		}
1010 	}
1011 
1012 	/* check for door errors */
1013 	if (lmshrd_iterate(iterator, si) != NERR_Success) {
1014 		kmem_free(si, sizeof (lmshare_info_t));
1015 		kmem_free(tsi, sizeof (struct lmshare_info));
1016 		return;
1017 	}
1018 
1019 	while ((i < shares_num) && (*si->share_name != 0)) {
1020 		if (smb_share_skip_share(si)) {
1021 			goto next;
1022 		}
1023 
1024 
1025 		is_special = lmshrd_is_special(si->share_name);
1026 		/* check for door errors */
1027 		if (is_special == NERR_InternalError) {
1028 			kmem_free(si, sizeof (lmshare_info_t));
1029 			kmem_free(tsi, sizeof (struct lmshare_info));
1030 			return;
1031 		}
1032 
1033 		if (is_special) {
1034 			si->stype |= STYPE_HIDDEN;
1035 			if (smb_encode_SHARE_INFO_1(data_mb,
1036 			    (unsigned char *)si->share_name,
1037 			    si->stype, *cmnt_len) < 0) {
1038 				goto next;
1039 			}
1040 			cmnt_str[*cmnt_len] = '\0';
1041 			(*cmnt_len)++;
1042 		} else {
1043 			if (smb_encode_SHARE_INFO_1(data_mb,
1044 			    (unsigned char *)si->share_name, si->stype,
1045 			    *cmnt_len) < 0) {
1046 				goto next;
1047 			}
1048 			(void) memcpy(cmnt_str+(*cmnt_len), si->comment,
1049 			    strlen(si->comment)+1);
1050 			(*cmnt_len) += (strlen(si->comment) + 1);
1051 		}
1052 
1053 	next:
1054 		/* check for door errors */
1055 		if (lmshrd_iterate(iterator, si) != NERR_Success) {
1056 			kmem_free(si, sizeof (lmshare_info_t));
1057 			kmem_free(tsi, sizeof (struct lmshare_info));
1058 			return;
1059 		}
1060 	}
1061 	kmem_free(si, sizeof (lmshare_info_t));
1062 	kmem_free(tsi, sizeof (struct lmshare_info));
1063 }
1064 
1065 int
1066 smb_trans_net_share_enum(struct smb_request *sr, struct smb_xa *xa)
1067 {
1068 	smb_share_enum_t shr_enum_info;
1069 	short left_shares_cnt;		/* Number of shares not sent yet */
1070 
1071 	/*
1072 	 * Number of shares that should be sent
1073 	 * in the current response packet.
1074 	 * It can be a number between 0 and
1075 	 * max_share_scnt.
1076 	 */
1077 	short shares_scnt;
1078 
1079 	/*
1080 	 * Maximum number of shares that can be
1081 	 * sent in one response packet regarding
1082 	 * the maximum negotiated buffer size
1083 	 * for SMB messages.
1084 	 */
1085 	short max_shares_per_packet;
1086 
1087 	/*
1088 	 * Total number of shares on the server
1089 	 * that their name is not greater than
1090 	 * MAX_SHARE_NAME_LEN
1091 	 */
1092 	short shares_tot_num;
1093 
1094 	/*
1095 	 * Size of total data (info + cmnt)
1096 	 * that should be sent for client
1097 	 */
1098 	int shares_tot_byte;
1099 
1100 	/*
1101 	 * Maximum size of data that can be
1102 	 * sent in one SMB transaction response
1103 	 * according to the maximum negotiated
1104 	 * buffer size for SMB  packets
1105 	 */
1106 	int data_buf_limit;
1107 
1108 	/*
1109 	 * Number of comment bytes that will
1110 	 * be sent in the current response
1111 	 */
1112 	uint16_t cmnt_scnt;
1113 
1114 	/*
1115 	 * Number of data bytes that will
1116 	 * be sent in the current response
1117 	 */
1118 	uint16_t data_scnt;
1119 
1120 	/*
1121 	 * Total number of data bytes that
1122 	 * are sent till now. This is only
1123 	 * used for calculating current data
1124 	 * displacement
1125 	 */
1126 	uint16_t tot_data_scnt;
1127 
1128 	/*
1129 	 * Number of parameter bytes should
1130 	 * be sent for the current response.
1131 	 * It is 8 for the 1st response and
1132 	 * 0 for others
1133 	 */
1134 	uint16_t param_scnt;
1135 
1136 	/* number of setup and parameter bytes */
1137 	uint16_t n_setup, n_param;
1138 
1139 	/* data and parameter displacement */
1140 	uint16_t data_disp, param_disp;
1141 
1142 	/* return status by the 1st reply */
1143 	uint16_t ret_stat;
1144 
1145 	/* parameter and data offset and pad */
1146 	int param_off, param_pad, data_off, data_pad;
1147 
1148 	/*
1149 	 * total bytes of parameters and data
1150 	 * in the packet, plus the pad bytes.
1151 	 */
1152 	int tot_packet_bytes;
1153 
1154 	char first_resp;
1155 	uint16_t opcode, level, cli_bufsize;
1156 	unsigned char *r_fmt;
1157 	char fmt[10];
1158 	uint64_t iterator;
1159 	char *cmnt_str, *cmnt_start;
1160 	int cmnt_len;
1161 	struct mbuf_chain reply;
1162 	smb_user_t *user;
1163 
1164 	user = sr->uid_user;
1165 	ASSERT(user);
1166 
1167 	/*
1168 	 * Initialize the mbuf chain of reply to zero. If it is not
1169 	 * zero, code inside the while loop will try to free the chain.
1170 	 */
1171 	bzero(&reply, sizeof (struct mbuf_chain));
1172 
1173 	if (smb_decode_mbc(&xa->req_param_mb, "%wss(lev)w(size)w", sr,
1174 	    &opcode, &r_fmt, &r_fmt, &level, &cli_bufsize) != 0)
1175 		return (SDRC_UNSUPPORTED);
1176 
1177 	if (level != 1) {
1178 		(void) smb_encode_mbc(&xa->rep_param_mb, "wwww",
1179 		    NERR_BadTransactConfig, 0, 0, 0);
1180 		return (SDRC_NORMAL_REPLY);
1181 	}
1182 
1183 	n_setup = 0;	/* Setup count for NetShareEnum SMB is 0 */
1184 	n_param = 8;
1185 	data_buf_limit = sr->session->smb_msg_size -
1186 	    (SMB_HEADER_ED_LEN + RESP_HEADER_LEN + n_param);
1187 
1188 	shr_enum_info.sei_bufsize = cli_bufsize;
1189 	smb_share_total_info(&shr_enum_info, &shares_tot_num, user);
1190 
1191 	shares_tot_byte = shr_enum_info.sei_infolen + shr_enum_info.sei_cmntlen;
1192 
1193 	/* Check buffer to have enough space */
1194 	if (shares_tot_byte == 0) {
1195 		(void) smb_encode_mbc(&xa->rep_param_mb, "wwww",
1196 		    ERROR_NOT_ENOUGH_MEMORY, 0, 0, 0);
1197 		return (SDRC_NORMAL_REPLY);
1198 	}
1199 
1200 	max_shares_per_packet = data_buf_limit / SHARE_INFO_1_SIZE;
1201 
1202 	shares_scnt = (shr_enum_info.sei_count > max_shares_per_packet)
1203 	    ? max_shares_per_packet : shr_enum_info.sei_count;
1204 
1205 	cmnt_str = MEM_MALLOC("smb", shr_enum_info.sei_cmntlen * sizeof (char));
1206 	cmnt_len = 0;
1207 	/* save start of buffer to free it at the end of function */
1208 	cmnt_start = cmnt_str;
1209 
1210 	iterator = lmshrd_open_iterator(LMSHRM_ALL);
1211 
1212 	if (iterator == NULL) {
1213 		MEM_FREE("smb", cmnt_str);
1214 		return (SDRC_DROP_VC);
1215 	}
1216 
1217 	/*
1218 	 * The rep_setup_mb is already initialized in smb_trans_dispatch().
1219 	 * Calling MBC_INIT() will initialized the structure and so the
1220 	 * pointer to the mbuf chains will be lost. Therefore, we need
1221 	 * to free the resources before calling MBC_INIT() again.
1222 	 */
1223 	m_freem(xa->rep_setup_mb.chain);
1224 	MBC_INIT(&xa->rep_setup_mb, n_setup * 2);
1225 
1226 	left_shares_cnt = shr_enum_info.sei_count;
1227 	tot_data_scnt = 0;
1228 	cmnt_scnt = 0;
1229 
1230 	first_resp = 1;
1231 	while (tot_data_scnt < shares_tot_byte) {
1232 		/*
1233 		 * Calling MBC_INIT() will initialized the structure and so the
1234 		 * pointer to the mbuf chains will be lost. Therefore, we need
1235 		 * to free the resources if any before calling MBC_INIT().
1236 		 */
1237 		m_freem(xa->rep_data_mb.chain);
1238 		MBC_INIT(&xa->rep_data_mb, data_buf_limit);
1239 		collect_shares_info(iterator, shares_scnt, &xa->rep_data_mb,
1240 		    cmnt_str, &cmnt_len, user, first_resp);
1241 		data_scnt = shares_scnt * SHARE_INFO_1_SIZE;
1242 		left_shares_cnt -= shares_scnt;
1243 		if (left_shares_cnt < max_shares_per_packet)
1244 			shares_scnt = left_shares_cnt;
1245 		if (left_shares_cnt == 0) {
1246 			/*
1247 			 * Now send comments.
1248 			 * Append comments to the end of share_info_1
1249 			 * structures.
1250 			 */
1251 			cmnt_scnt = data_buf_limit -
1252 			    MBC_LENGTH(&xa->rep_data_mb);
1253 			if (cmnt_scnt > shr_enum_info.sei_cmntlen) {
1254 				/*LINTED E_ASSIGN_NARROW_CONV*/
1255 				cmnt_scnt = shr_enum_info.sei_cmntlen;
1256 			}
1257 			(void) sprintf(fmt, "%dc", cmnt_scnt);
1258 			(void) smb_encode_mbc(&xa->rep_data_mb, fmt, cmnt_str);
1259 			cmnt_str += cmnt_scnt;
1260 			shr_enum_info.sei_cmntlen -= cmnt_scnt;
1261 		}
1262 		data_scnt += cmnt_scnt;
1263 		tot_data_scnt += data_scnt;
1264 
1265 		/* Only the 1st response packet contains parameters */
1266 		param_scnt = (first_resp) ? n_param : 0;
1267 		param_pad = 1;				/* always one */
1268 		param_off = SMB_HEADER_ED_LEN + RESP_HEADER_LEN;
1269 		param_disp = (first_resp) ? 0 : n_param;
1270 
1271 		/*
1272 		 * Calling MBC_INIT() will initialized the structure and so the
1273 		 * pointer to the mbuf chains will be lost. Therefore, we need
1274 		 * to free the resources if any before calling MBC_INIT().
1275 		 */
1276 		m_freem(xa->rep_param_mb.chain);
1277 		MBC_INIT(&xa->rep_param_mb, param_scnt);
1278 		if (first_resp) {
1279 			first_resp = 0;
1280 			/* Prepare parameters for the 1st response packet */
1281 			ret_stat = (shares_tot_num > shr_enum_info.sei_count)
1282 			    ? ERROR_MORE_DATA : 0;
1283 			(void) smb_encode_mbc(&xa->rep_param_mb, "wwww",
1284 			    ret_stat, -shr_enum_info.sei_infolen,
1285 			    shr_enum_info.sei_count,
1286 			    shares_tot_num);
1287 		}
1288 
1289 		data_pad = (param_off + n_param) & 1;	/* Pad to short */
1290 
1291 		/* data off from hdr start */
1292 		data_off = param_off + param_scnt + data_pad;
1293 		data_disp = tot_data_scnt - data_scnt;
1294 		tot_packet_bytes = param_pad + param_scnt + data_pad +
1295 		    data_scnt;
1296 
1297 		/*
1298 		 * Calling MBC_INIT() will initialized the structure and so the
1299 		 * pointer to the mbuf chains will be lost. Therefore, we need
1300 		 * to free the resources if any before calling MBC_INIT().
1301 		 */
1302 		m_freem(reply.chain);
1303 		MBC_INIT(&reply, SMB_HEADER_ED_LEN
1304 		    + sizeof (uchar_t)		/* word parameters count */
1305 		    + 10*sizeof (ushort_t)	/* word parameters */
1306 		    + n_setup*sizeof (ushort_t)	/* setup parameters */
1307 		    + sizeof (ushort_t)		/* total data byte count */
1308 		    + tot_packet_bytes);
1309 
1310 		(void) smb_encode_mbc(&reply, SMB_HEADER_ED_FMT,
1311 		    sr->first_smb_com,
1312 		    sr->smb_rcls,
1313 		    sr->smb_reh,
1314 		    sr->smb_err,
1315 		    sr->smb_flg | SMB_FLAGS_REPLY,
1316 		    sr->smb_flg2,
1317 		    sr->smb_pid_high,
1318 		    sr->smb_sig,
1319 		    sr->smb_tid,
1320 		    sr->smb_pid,
1321 		    sr->smb_uid,
1322 		    sr->smb_mid);
1323 
1324 		(void) smb_encode_mbc(&reply,
1325 		    "b ww 2. www www b . C w #. C #. C",
1326 		    10 + n_setup,	/* wct */
1327 		    n_param,		/* Total Parameter Bytes */
1328 		    shares_tot_byte,	/* Total Data Bytes */
1329 		    param_scnt,		/* Total Parameter Bytes this buffer */
1330 		    param_off,		/* Param offset from header start */
1331 		    param_disp,		/* Param displacement */
1332 		    data_scnt,		/* Total Data Bytes this buffer */
1333 		    data_off,		/* Data offset from header start */
1334 		    data_disp,		/* Data displacement */
1335 		    n_setup,		/* suwcnt */
1336 		    &xa->rep_setup_mb, 	/* setup[] */
1337 		    tot_packet_bytes,	/* Total data bytes */
1338 		    param_pad,
1339 		    &xa->rep_param_mb,
1340 		    data_pad,
1341 		    &xa->rep_data_mb);
1342 
1343 		if (sr->session->signing.flags & SMB_SIGNING_ENABLED)
1344 			smb_sign_reply(sr, NULL);
1345 
1346 		(void) smb_session_send(sr->session, 0, &reply);
1347 	}
1348 
1349 	(void) lmshrd_close_iterator(iterator);
1350 	MEM_FREE("smb", cmnt_start);
1351 	return (SDRC_NO_REPLY);
1352 }
1353 
1354 int
1355 smb_trans_net_share_get_info(struct smb_request *sr, struct smb_xa *xa)
1356 {
1357 	uint16_t		opcode, level, max_bytes, access;
1358 	uint32_t		type;
1359 	unsigned char		*req_fmt;
1360 	unsigned char		*rep_fmt;
1361 	struct mbuf_chain	str_mb;
1362 	char			*share;
1363 	char			*path;
1364 	char			*password;
1365 	char			*comment;
1366 	lmshare_info_t		si;
1367 	int			shr_found;
1368 
1369 	if (smb_decode_mbc(&xa->req_param_mb, "%wsss(lev)w(size)w", sr,
1370 	    &opcode, &req_fmt, &rep_fmt, &share, &level, &max_bytes) != 0)
1371 		return (SDRC_UNSUPPORTED);
1372 
1373 	(void) utf8_strlwr(share);
1374 	shr_found = lmshrd_getinfo(share, &si);
1375 	if (strcmp(share, "ipc$") == 0) {
1376 		type = STYPE_IPC;
1377 		path = "";
1378 		password = "";
1379 		access = SHARE_ACCESS_ALL;
1380 	} else if (shr_found) {
1381 		path = si.directory;
1382 		type = STYPE_DISKTREE;
1383 		if (path[strlen(path)] == '$')
1384 			type |= STYPE_HIDDEN;
1385 		password = "";
1386 		access = SHARE_ACCESS_ALL;
1387 	} else {
1388 		/* We have no idea what this share is... */
1389 		(void) smb_encode_mbc(&xa->rep_param_mb, "www",
1390 		    NERR_NetNameNotFound, 0, 0);
1391 		return (SDRC_NORMAL_REPLY);
1392 	}
1393 
1394 	if (shr_found)
1395 		comment = si.comment;
1396 	else
1397 		comment = "";
1398 
1399 	password = "";
1400 
1401 	MBC_INIT(&str_mb, max_bytes);
1402 
1403 	switch (level) {
1404 	case 0 :
1405 		(void) smb_emit_SHARE_INFO_0(&xa->rep_data_mb,
1406 		    (unsigned char *)share);
1407 		break;
1408 
1409 	case 1 :
1410 		(void) smb_emit_SHARE_INFO_1(&xa->rep_data_mb, &str_mb,
1411 		    (unsigned char *)share, type,
1412 		    (unsigned char *)comment);
1413 		break;
1414 
1415 	case 2 :
1416 		smb_emit_SHARE_INFO_2(&xa->rep_data_mb, &str_mb, sr,
1417 		    (unsigned char *)share, type, (unsigned char *)comment,
1418 		    access, path, password);
1419 	default:
1420 		m_freem(str_mb.chain);
1421 		return (SDRC_UNSUPPORTED);
1422 	}
1423 
1424 	(void) smb_encode_mbc(&xa->rep_param_mb, "www", 0,
1425 	    -MBC_LENGTH(&xa->rep_data_mb),
1426 	    MBC_LENGTH(&xa->rep_data_mb) + MBC_LENGTH(&str_mb));
1427 	(void) smb_encode_mbc(&xa->rep_data_mb, "C", &str_mb);
1428 	m_freem(str_mb.chain);
1429 	return (SDRC_NORMAL_REPLY);
1430 }
1431 
1432 int
1433 smb_trans_net_workstation_get_info(struct smb_request *sr, struct smb_xa *xa)
1434 {
1435 	uint16_t		opcode, level, max_bytes;
1436 	unsigned char		*req_fmt;
1437 	unsigned char		*rep_fmt;
1438 	struct mbuf_chain	str_mb;
1439 	char *domain;
1440 	char *hostname;
1441 
1442 	if ((smb_decode_mbc(&xa->req_param_mb, "%wss(lev)w(size)w", sr,
1443 	    &opcode, &req_fmt, &rep_fmt, &level, &max_bytes) != 0) ||
1444 	    (level != 10)) {
1445 		(void) smb_encode_mbc(&xa->rep_param_mb, "wwww",
1446 		    NERR_BadTransactConfig, 0, 0, 0);
1447 		return (SDRC_NORMAL_REPLY);
1448 	}
1449 
1450 	domain = smb_info.si.skc_resource_domain;
1451 	hostname = smb_info.si.skc_hostname;
1452 
1453 	MBC_INIT(&str_mb, max_bytes);
1454 
1455 	(void) smb_encode_mbc(&str_mb, "."); /* Prevent NULL pointers */
1456 
1457 	(void) smb_encode_mbc(&xa->rep_data_mb, "l", MBC_LENGTH(&str_mb));
1458 	(void) smb_encode_mbc(&str_mb, "s", hostname);
1459 	(void) smb_encode_mbc(&xa->rep_data_mb, "l", MBC_LENGTH(&str_mb));
1460 	(void) smb_encode_mbc(&str_mb, "s", "nobody");
1461 	(void) smb_encode_mbc(&xa->rep_data_mb, "l", MBC_LENGTH(&str_mb));
1462 	(void) smb_encode_mbc(&str_mb, "s", domain);
1463 	(void) smb_encode_mbc(&xa->rep_data_mb, "bbl",
1464 	    SMB_VERSION_MAJOR, SMB_VERSION_MINOR, MBC_LENGTH(&str_mb));
1465 	(void) smb_encode_mbc(&str_mb, "s", domain);
1466 	(void) smb_encode_mbc(&xa->rep_data_mb, "l", MBC_LENGTH(&str_mb));
1467 	(void) smb_encode_mbc(&str_mb, "s", domain);
1468 
1469 	(void) smb_encode_mbc(&xa->rep_param_mb, "www", 0,
1470 	    -MBC_LENGTH(&xa->rep_data_mb),
1471 	    MBC_LENGTH(&xa->rep_data_mb) + MBC_LENGTH(&str_mb));
1472 	(void) smb_encode_mbc(&xa->rep_data_mb, "C", &str_mb);
1473 	m_freem(str_mb.chain);
1474 	return (SDRC_NORMAL_REPLY);
1475 }
1476 
1477 int
1478 smb_trans_net_user_get_info(struct smb_request *sr, struct smb_xa *xa)
1479 {
1480 	uint16_t		opcode, level, max_bytes;
1481 	unsigned char		*req_fmt;
1482 	unsigned char		*rep_fmt;
1483 	unsigned char		*user;
1484 	int rc;
1485 
1486 	rc = smb_decode_mbc(&xa->req_param_mb, "%wssww", sr,
1487 	    &opcode,
1488 	    &req_fmt,
1489 	    &rep_fmt,
1490 	    &user,
1491 	    &level,
1492 	    &max_bytes);
1493 
1494 	if (rc != 0)
1495 		return (SDRC_UNSUPPORTED);
1496 
1497 	(void) smb_encode_mbc(&xa->rep_param_mb, "www",
1498 	    NERR_UserNotFound, 0, 0);
1499 	return (SDRC_NORMAL_REPLY);
1500 }
1501 
1502 smb_sdrc_t
1503 smb_trans_server_get_info(struct smb_request *sr, struct smb_xa *xa)
1504 {
1505 	uint16_t		opcode, level, buf_size;
1506 	char			*req_fmt;
1507 	char			*rep_fmt;
1508 	char			server_name[16];
1509 	struct mbuf_chain	str_mb;
1510 	char *hostname;
1511 	char *comment;
1512 
1513 	if (smb_decode_mbc(&xa->req_param_mb, "%wssww", sr,
1514 	    &opcode, &req_fmt, &rep_fmt, &level, &buf_size) != 0) {
1515 		return (SDRC_ERROR_REPLY);
1516 	}
1517 
1518 	comment = smb_info.si.skc_system_comment;
1519 	hostname = smb_info.si.skc_hostname;
1520 
1521 	MBC_INIT(&str_mb, buf_size);
1522 
1523 	bzero(server_name, sizeof (server_name));
1524 	(void) strncpy(server_name, hostname, sizeof (server_name));
1525 
1526 	switch (level) {
1527 	case 0:
1528 		(void) smb_encode_mbc(&xa->rep_data_mb, "16c", server_name);
1529 		break;
1530 	case 1:
1531 		(void) smb_encode_mbc(&str_mb, "."); /* Prevent NULL pointers */
1532 		(void) smb_encode_mbc(&xa->rep_data_mb, "16cbbll", server_name,
1533 		    SMB_VERSION_MAJOR, SMB_VERSION_MINOR,
1534 		    MY_SERVER_TYPE, MBC_LENGTH(&str_mb));
1535 		(void) smb_encode_mbc(&str_mb, "s", comment);
1536 		break;
1537 	case 2:
1538 		/* B16BBDzDDDWWzWWWWWWWB21BzWWWWWWWWWWWWWWWWWWWWWWz */
1539 		(void) smb_encode_mbc(&str_mb, "."); /* Prevent NULL pointers */
1540 					/*  B16BBDz */
1541 		(void) smb_encode_mbc(&xa->rep_data_mb, "16cbbll", server_name,
1542 		    SMB_VERSION_MAJOR,
1543 		    SMB_VERSION_MINOR, MY_SERVER_TYPE, MBC_LENGTH(&str_mb));
1544 		(void) smb_encode_mbc(&str_mb, "s", comment);
1545 		(void) smb_encode_mbc(&xa->rep_data_mb, "lllwwl",
1546 		    (uint32_t)1,
1547 		    (uint32_t)2,
1548 		    (uint32_t)3,
1549 		    (uint16_t)4,
1550 		    (uint16_t)5,
1551 		    MBC_LENGTH(&str_mb));
1552 		(void) smb_encode_mbc(&str_mb, "s", "str1");
1553 		(void) smb_encode_mbc(&xa->rep_data_mb, "wwwwwww21cbl",
1554 		    (uint16_t)6,
1555 		    (uint16_t)7,
1556 		    (uint16_t)8,
1557 		    (uint16_t)9,
1558 		    (uint16_t)10,
1559 		    (uint16_t)11,
1560 		    (uint16_t)12,
1561 		    "21 byte comment       ",
1562 		    (unsigned char)13,
1563 		    MBC_LENGTH(&str_mb));
1564 		(void) smb_encode_mbc(&str_mb, "s", "str2");
1565 		(void) smb_encode_mbc(&xa->rep_data_mb,
1566 		    "wwwwwwwwwwwwwwwwwwwwwwl",
1567 		    (uint16_t)14,
1568 		    (uint16_t)15,
1569 		    (uint16_t)16,
1570 		    (uint16_t)17,
1571 		    (uint16_t)18,
1572 		    (uint16_t)19,
1573 		    (uint16_t)20,
1574 		    (uint16_t)21,
1575 		    (uint16_t)22,
1576 		    (uint16_t)23,
1577 		    (uint16_t)24,
1578 		    (uint16_t)25,
1579 		    (uint16_t)26,
1580 		    (uint16_t)27,
1581 		    (uint16_t)28,
1582 		    (uint16_t)29,
1583 		    (uint16_t)20,
1584 		    (uint16_t)31,
1585 		    (uint16_t)32,
1586 		    (uint16_t)33,
1587 		    (uint16_t)34,
1588 		    (uint16_t)35,
1589 		    MBC_LENGTH(&str_mb));
1590 		(void) smb_encode_mbc(&str_mb, "s", "str3");
1591 		break;
1592 	default:
1593 		m_freem(str_mb.chain);
1594 		return (SDRC_UNSUPPORTED);
1595 	}
1596 
1597 	(void) smb_encode_mbc(&xa->rep_param_mb, "www", 0,
1598 	    -MBC_LENGTH(&xa->rep_data_mb),
1599 	    (MBC_LENGTH(&xa->rep_data_mb)) +
1600 	    (MBC_LENGTH(&str_mb)));
1601 	(void) smb_encode_mbc(&xa->rep_data_mb, "C", &str_mb);
1602 	m_freem(str_mb.chain);
1603 	return (SDRC_NORMAL_REPLY);
1604 }
1605 
1606 /*
1607  * 6.4 The NetServerEnum2 RAP Service
1608  *
1609  * The NetServerEnum2 RAP service lists all computers of the specified type
1610  * or types that are visible in the specified domains. It may also
1611  * enumerate domains.
1612  *
1613  * The following definition uses the notation and terminology defined in
1614  * the CIFS Remote Administration Protocol specification, which is required
1615  * in order to make it well-defined. The definition is:
1616  *
1617  *     uint16_t NetServerEnum2 (
1618  *         uint16_t  sLevel,
1619  *         RCVBUF          pbBuffer,
1620  *         RCVBUFLEN       cbBuffer,
1621  *         ENTCOUNT        pcEntriesRead,
1622  *         uint16_t  *pcTotalAvail,
1623  *         uint32_t   fServerType,
1624  *         char            *pszDomain,
1625  *     );
1626  *
1627  * where:
1628  *
1629  *    sLevel specifies the level of detail (0 or 1) requested.
1630  *
1631  *    pbBuffer points to the buffer to receive the returned data. If the
1632  *    function is successful, the buffer contains a sequence of
1633  *    server_info_x structures, where x is 0 or 1, depending on the
1634  *    level of detail requested.
1635  *
1636  *    cbBuffer specifies the size, in bytes, of the buffer pointed to by
1637  *    the pbBuffer parameter.
1638  *
1639  *    pcEntriesRead points to a 16 bit variable that receives a count of
1640  *    the number of servers enumerated in the buffer. This count is
1641  *    valid only if NetServerEnum2 returns the NERR_Success or
1642  *    ERROR_MORE_DATA values.
1643  *
1644  *    pcTotal Avail points to a 16 bit variable that receives a count of
1645  *    the total number of available entries. This count is valid only if
1646  *    NetServerEnum2 returns the NERR_Success or ERROR_MORE_DATA values.
1647  *
1648  *     fServerType specifies the type or types of computers to enumerate.
1649  *     Computers that match at least one of the specified types are
1650  *     returned in the buffer. Possible values are defined in the request
1651  *     parameters section.
1652  *
1653  *    pszDomain points to a null-terminated string that contains the
1654  *    name of the workgroup in which to enumerate computers of the
1655  *    specified type or types. If the pszDomain parameter is a null
1656  *    string or a null pointer, servers are enumerated for the current
1657  *    domain of the computer.
1658  *
1659  * 6.4.1 Transaction Request Parameters section
1660  *
1661  * The Transaction request parameters section in this instance contains:
1662  * . The 16 bit function number for NetServerEnum2 which is 104.
1663  * . The parameter descriptor string which is "WrLehDz".
1664  * . The data descriptor string for the (returned) data which is "B16" for
1665  *   level detail 0 or "B16BBDz" for level detail 1.
1666  * . The actual parameters as described by the parameter descriptor
1667  *   string.
1668  *
1669  * The parameters are:
1670  * . A 16 bit integer with a value of 0 or 1 (corresponding to the "W" in
1671  *   the parameter descriptor string. This represents the level of detail
1672  *   the server is expected to return
1673  * . A 16 bit integer that contains the size of the receive buffer.
1674  * . A 32 bit integer that represents the type of servers the function
1675  *   should enumerate. The possible values may be any of the following or
1676  *   a combination of the following:
1677  *
1678  * SV_TYPE_WORKSTATION        0x00000001 All workstations
1679  * SV_TYPE_SERVER             0x00000002 All servers
1680  * SV_TYPE_SQLSERVER          0x00000004 Any server running with SQL
1681  *                                       server
1682  * SV_TYPE_DOMAIN_CTRL        0x00000008 Primary domain controller
1683  * SV_TYPE_DOMAIN_BAKCTRL     0x00000010 Backup domain controller
1684  * SV_TYPE_TIME_SOURCE        0x00000020 Server running the timesource
1685  *                                       service
1686  * SV_TYPE_AFP                0x00000040 Apple File Protocol servers
1687  * SV_TYPE_NOVELL             0x00000080 Novell servers
1688  * SV_TYPE_DOMAIN_MEMBER      0x00000100 Domain Member
1689  * SV_TYPE_PRINTQ_SERVER      0x00000200 Server sharing print queue
1690  * SV_TYPE_DIALIN_SERVER      0x00000400 Server running dialin service.
1691  * SV_TYPE_XENIX_SERVER       0x00000800 Xenix server
1692  * SV_TYPE_NT                 0x00001000 NT server
1693  * SV_TYPE_WFW                0x00002000 Server running Windows for
1694  *                                       Workgroups
1695  * SV_TYPE_SERVER_NT          0x00008000 Windows NT non DC server
1696  * SV_TYPE_POTENTIAL_BROWSER  0x00010000 Server that can run the browser
1697  *                                       service
1698  * SV_TYPE_BACKUP_BROWSER     0x00020000 Backup browser server
1699  * SV_TYPE_MASTER_BROWSER     0x00040000 Master browser server
1700  * SV_TYPE_DOMAIN_MASTER      0x00080000 Domain Master Browser server
1701  * SV_TYPE_LOCAL_LIST_ONLY    0x40000000 Enumerate only entries marked
1702  *                                       "local"
1703  * SV_TYPE_DOMAIN_ENUM        0x80000000 Enumerate Domains. The pszDomain
1704  *                                       parameter must be NULL.
1705  *
1706  * . A null terminated ASCII string representing the pszDomain parameter
1707  *   described above
1708  *
1709  * 6.4.2 Transaction Request Data section
1710  *
1711  * There is no data or auxiliary data to send as part of the request.
1712  *
1713  * 6.4.3 Transaction Response Parameters section
1714  *
1715  * The transaction response parameters section consists of:
1716  * . A 16 bit word indicating the return status. The possible values are:
1717  *
1718  * Code                   Value  Description
1719  * NERR_Success           0      No errors encountered
1720  * ERROR_MORE_DATA        234    Additional data is available
1721  * NERR_ServerNotStarted  2114   The RAP service on the remote computer
1722  *                               is not running
1723  * NERR_BadTransactConfig 2141   The server is not configured for
1724  *                               transactions, IPC$ is not shared
1725  *
1726  * . A 16 bit "converter" word.
1727  * . A 16 bit number representing the number of entries returned.
1728  * . A 16 bit number representing the total number of available entries.
1729  *   If the supplied buffer is large enough, this will equal the number of
1730  *   entries returned.
1731  *
1732  * 6.4.4 Transaction Response Data section
1733  *
1734  * The return data section consists of a number of SERVER_INFO_1 structures.
1735  * The number of such structures present is determined by the third entry
1736  * (described above) in the return parameters section.
1737  *
1738  * At level detail 0, the Transaction response data section contains a
1739  * number of SERVER_INFO_0 data structure. The number of such structures is
1740  * equal to the 16 bit number returned by the server in the third parameter
1741  * in the Transaction response parameter section. The SERVER_INFO_0 data
1742  * structure is defined as:
1743  *
1744  *     struct SERVER_INFO_0 {
1745  *         char        sv0_name[16];
1746  *     };
1747  *
1748  *  where:
1749  *
1750  *    sv0_name is a null-terminated string that specifies the name of a
1751  *    computer or domain .
1752  *
1753  * At level detail 1, the Transaction response data section contains a
1754  * number of SERVER_INFO_1 data structure. The number of such structures is
1755  * equal to the 16 bit number returned by the server in the third parameter
1756  * in the Transaction response parameter section. The SERVER_INFO_1 data
1757  * structure is defined as:
1758  *
1759  *     struct SERVER_INFO_1 {
1760  *         char            sv1_name[16];
1761  *         char            sv1_version_major;
1762  *         char            sv1_version_minor;
1763  *         uint32_t   sv1_type;
1764  *         char        *sv1_comment_or_master_browser;
1765  *     };
1766  *
1767  *    sv1_name contains a null-terminated string that specifies the name
1768  *    of a computer, or a domain name if SV_TYPE_DOMAIN_ENUM is set in
1769  *    sv1_type.
1770  *
1771  *    sv1_version_major whatever was specified in the HostAnnouncement
1772  *    or DomainAnnouncement frame with which the entry was registered.
1773  *
1774  *    sv1_version_minor whatever was specified in the HostAnnouncement
1775  *    or DomainAnnouncement frame with which the entry was registered.
1776  *
1777  *    sv1_type specifies the type of software the computer is running.
1778  *    The member can be one or a combination of the values defined above
1779  *    in the Transaction request parameters section for fServerType.
1780  *
1781  *
1782  *    sv1_comment_or_master_browser points to a null-terminated string. If
1783  *    the sv1_type indicates that the entry is for a domain, this
1784  *    specifies the name of server running the domain master browser;
1785  *    otherwise, it specifies a comment describing the server. The comment
1786  *    can be a null string or the pointer may be a null pointer.
1787  *
1788  *    In case there are multiple SERVER_INFO_1 data structures to
1789  *    return, the server may put all these fixed length structures in
1790  *    the return buffer, leave some space and then put all the variable
1791  *    length data (the actual value of the sv1_comment strings) at the
1792  *    end of the buffer.
1793  *
1794  * There is no auxiliary data to receive.
1795  */
1796 
1797 int
1798 smb_trans_net_server_enum2(struct smb_request *sr, struct smb_xa *xa)
1799 {
1800 	uint16_t opcode, level, max_bytes;
1801 	uint32_t server_type;
1802 	unsigned char *domain;
1803 	struct mbuf_chain str_mb;
1804 	char *hostname, *s;
1805 	smb_kmod_cfg_t *si;
1806 
1807 	if (smb_decode_mbc(&xa->req_param_mb,
1808 	    "%w s(request format) s(reply format) wwls", sr, &opcode, &s, &s,
1809 	    &level, &max_bytes, &server_type, &domain) != 0)
1810 		return (SDRC_UNSUPPORTED);
1811 
1812 	si = &smb_info.si;
1813 
1814 	if (utf8_strcasecmp(si->skc_resource_domain, (char *)domain) != 0) {
1815 		(void) smb_encode_mbc(&xa->rep_param_mb, "wwww", 0, 0, 0, 0);
1816 		return (SDRC_NORMAL_REPLY);
1817 	}
1818 
1819 	if ((server_type & MY_SERVER_TYPE) == 0) {
1820 		(void) smb_encode_mbc(&xa->rep_param_mb, "wwww", 0, 0, 0, 0);
1821 		return (SDRC_NORMAL_REPLY);
1822 	}
1823 
1824 	MBC_INIT(&str_mb, max_bytes);
1825 
1826 	hostname = si->skc_hostname;
1827 
1828 	(void) smb_encode_mbc(&xa->rep_data_mb, "16c", hostname);
1829 	if (level == 1) {
1830 		(void) smb_encode_mbc(&xa->rep_data_mb, "bbll",
1831 		    SMB_VERSION_MAJOR, SMB_VERSION_MINOR,
1832 		    MY_SERVER_TYPE, MBC_LENGTH(&str_mb));
1833 		(void) smb_encode_mbc(&str_mb, "s", si->skc_system_comment);
1834 	}
1835 
1836 	(void) smb_encode_mbc(&xa->rep_param_mb, "wwww", 0,
1837 	    -MBC_LENGTH(&xa->rep_data_mb), 1, 1);
1838 	(void) smb_encode_mbc(&xa->rep_data_mb, "m", str_mb.chain);
1839 	return (SDRC_NORMAL_REPLY);
1840 }
1841 
1842 /*
1843  * is_supported_pipe
1844  *
1845  * Currently, just return 0 if the pipe is \\PIPE\repl otherwise
1846  * return 1.
1847  */
1848 int
1849 is_supported_pipe(char *pname)
1850 {
1851 	if (utf8_strcasecmp(pname, PIPE_REPL) == 0)
1852 		return (0);
1853 
1854 	return (1);
1855 }
1856 
1857 static smb_sdrc_t
1858 smb_trans_dispatch(struct smb_request *sr, struct smb_xa *xa)
1859 {
1860 	int		rc, pos;
1861 	int		total_bytes, n_setup, n_param, n_data;
1862 	int		param_off, param_pad, data_off, data_pad;
1863 	uint16_t	opcode;
1864 	uint16_t	devstate;
1865 	char		*req_fmt;
1866 	char		*rep_fmt;
1867 	struct vardata_block vdb;
1868 
1869 	n_setup = (xa->smb_msrcnt < 200) ? xa->smb_msrcnt : 200;
1870 	n_setup++;
1871 	n_setup = n_setup & ~0x0001;
1872 	n_param = (xa->smb_mprcnt < smb_maxbufsize)
1873 	    ? xa->smb_mprcnt : smb_maxbufsize;
1874 	n_param++;
1875 	n_param = n_param & ~0x0001;
1876 	rc = smb_maxbufsize - (SMBHEADERSIZE + 28 + n_setup + n_param);
1877 	n_data =  (xa->smb_mdrcnt < rc) ? xa->smb_mdrcnt : rc;
1878 	MBC_INIT(&xa->rep_setup_mb, n_setup * 2);
1879 	MBC_INIT(&xa->rep_param_mb, n_param);
1880 	MBC_INIT(&xa->rep_data_mb, n_data);
1881 
1882 	if (xa->smb_suwcnt > 0 && STYPE_ISIPC(sr->tid_tree->t_res_type)) {
1883 		rc = smb_decode_mbc(&xa->req_setup_mb, "ww", &opcode,
1884 		    &sr->smb_fid);
1885 		if (rc != 0)
1886 			goto trans_err_not_supported;
1887 		switch (opcode) {
1888 		case TRANS_SET_NMPIPE_STATE:
1889 			if ((rc = smb_decode_mbc(&xa->req_param_mb, "w",
1890 			    &devstate)) != 0)
1891 				goto trans_err_not_supported;
1892 
1893 			rc = SDRC_NORMAL_REPLY;
1894 			break;
1895 
1896 		case TRANS_TRANSACT_NMPIPE:
1897 			sr->fid_ofile = smb_ofile_lookup_by_fid(sr->tid_tree,
1898 			    sr->smb_fid);
1899 			if (sr->fid_ofile == NULL) {
1900 				smbsr_error(sr, NT_STATUS_INVALID_HANDLE,
1901 				    ERRDOS, ERRbadfid);
1902 				return (SDRC_ERROR_REPLY);
1903 			}
1904 
1905 			rc = smb_decode_mbc(&xa->req_data_mb, "#B",
1906 			    xa->smb_tdscnt, &vdb);
1907 			if (rc != 0)
1908 				goto trans_err_not_supported;
1909 
1910 			rc = smb_rpc_transact(sr, &vdb.uio);
1911 			break;
1912 
1913 		case TRANS_WAIT_NMPIPE:
1914 			if (is_supported_pipe(xa->xa_smb_trans_name) == 0) {
1915 				smbsr_error(sr, 0, ERRDOS, ERRbadfile);
1916 				return (SDRC_ERROR_REPLY);
1917 			}
1918 			rc = SDRC_NORMAL_REPLY;
1919 			break;
1920 
1921 		default:
1922 			goto trans_err_not_supported;
1923 		}
1924 	} else {
1925 		if ((utf8_strcasecmp(xa->xa_smb_trans_name,
1926 		    PIPE_LANMAN) != 0) &&
1927 		    (utf8_strcasecmp(
1928 		    xa->xa_smb_trans_name, MAILSLOT_LANMAN) != 0) &&
1929 		    (utf8_strcasecmp(
1930 		    xa->xa_smb_trans_name, MAILSLOT_BROWSE) != 0) &&
1931 		    (utf8_strcasecmp(
1932 		    xa->xa_smb_trans_name, MAILSLOT_MSBROWSE) != 0))
1933 			goto trans_err_not_supported;
1934 
1935 		if ((rc = smb_decode_mbc(&xa->req_param_mb, "%wss\b", sr,
1936 		    &opcode, &req_fmt, &rep_fmt)) != 0)
1937 			goto trans_err_not_supported;
1938 
1939 		/* for now, only respond to the */
1940 		switch (opcode) {
1941 		case API_WshareEnum:
1942 			rc = smb_trans_net_share_enum(sr, xa);
1943 			break;
1944 
1945 		case API_WshareGetInfo:
1946 			rc = smb_trans_net_share_get_info(sr, xa);
1947 			break;
1948 
1949 		case API_WserverGetInfo:
1950 			rc = smb_trans_server_get_info(sr, xa);
1951 			break;
1952 
1953 		case API_WUserGetInfo:
1954 			rc = smb_trans_net_user_get_info(sr, xa);
1955 			break;
1956 
1957 		case API_WWkstaGetInfo:
1958 			rc = smb_trans_net_workstation_get_info(sr, xa);
1959 			break;
1960 
1961 		case API_NetServerEnum2:
1962 			rc = smb_trans_net_server_enum2(sr, xa);
1963 			break;
1964 
1965 		default:
1966 			goto trans_err_not_supported;
1967 		}
1968 	}
1969 
1970 	switch (rc) {
1971 	case SDRC_NORMAL_REPLY:
1972 		break;
1973 
1974 	case SDRC_DROP_VC:
1975 	case SDRC_NO_REPLY:
1976 	case SDRC_ERROR_REPLY:
1977 		return (rc);
1978 
1979 	case SDRC_UNIMPLEMENTED:
1980 	case SDRC_UNSUPPORTED:
1981 		goto trans_err_not_supported;
1982 
1983 	default:
1984 		break;
1985 	}
1986 
1987 	n_setup = MBC_LENGTH(&xa->rep_setup_mb);
1988 	n_param = MBC_LENGTH(&xa->rep_param_mb);
1989 	n_data  = MBC_LENGTH(&xa->rep_data_mb);
1990 
1991 	if (xa->smb_msrcnt < n_setup ||
1992 	    xa->smb_mprcnt < n_param ||
1993 	    xa->smb_mdrcnt < n_data) {
1994 		goto trans_err_too_small;
1995 	}
1996 
1997 	/* neato, blast it over there */
1998 
1999 	n_setup = (n_setup + 1) / 2;		/* Convert to setup words */
2000 	param_pad = 1;				/* always one */
2001 	param_off = param_pad + 32 + 21 + (n_setup << 1) + 2;
2002 	data_pad = (param_off + n_param) & 1;	/* Pad to short */
2003 	/* Param off from hdr start */
2004 	data_off = param_off + n_param + data_pad;
2005 	total_bytes = param_pad + n_param + data_pad + n_data;
2006 
2007 	rc = smbsr_encode_result(sr, 10+n_setup, total_bytes,
2008 	    "b ww 2. www www b . C w #. C #. C",
2009 	    10 + n_setup,		/* wct */
2010 	    n_param,			/* Total Parameter Bytes */
2011 	    n_data,			/* Total Data Bytes */
2012 	    n_param,			/* Total Parameter Bytes this buffer */
2013 	    param_off,			/* Param offset from header start */
2014 	    0,				/* Param displacement */
2015 	    n_data,			/* Total Data Bytes this buffer */
2016 	    data_off,			/* Data offset from header start */
2017 	    0,				/* Data displacement */
2018 	    n_setup,			/* suwcnt */
2019 	    &xa->rep_setup_mb, /* setup[] */
2020 	    total_bytes,		/* Total data bytes */
2021 	    param_pad,
2022 	    &xa->rep_param_mb,
2023 	    data_pad,
2024 	    &xa->rep_data_mb);
2025 	return ((rc == 0) ? SDRC_NORMAL_REPLY : SDRC_ERROR_REPLY);
2026 
2027 trans_err_too_small:
2028 	rc = NERR_BufTooSmall;
2029 	goto trans_err;
2030 
2031 trans_err_not_supported:
2032 	rc = ERROR_NOT_SUPPORTED;
2033 	goto trans_err;
2034 
2035 trans_err:
2036 	pos = MBC_LENGTH(&sr->reply) + 23;
2037 	rc = smbsr_encode_result(sr, 10, 4, "b ww 2. www www b . w ww",
2038 	    10,		/* wct */
2039 	    4, 0,	/* tpscnt tdscnt */
2040 	    4, pos, 0,	/* pscnt psoff psdisp */
2041 	    0, 0, 0,	/* dscnt dsoff dsdisp */
2042 	    0,		/* suwcnt */
2043 	    4,		/* bcc */
2044 	    rc,
2045 	    0);		/* converter word? */
2046 	return ((rc == 0) ? SDRC_NORMAL_REPLY : SDRC_ERROR_REPLY);
2047 }
2048 
2049 static smb_sdrc_t
2050 smb_trans2_dispatch(struct smb_request *sr, struct smb_xa *xa)
2051 {
2052 	int		rc, pos;
2053 	int		total_bytes, n_setup, n_param, n_data;
2054 	int		param_off, param_pad, data_off, data_pad;
2055 	uint16_t	opcode;
2056 	uint16_t  nt_unknown_secret = 0x0100;
2057 	char *fmt;
2058 
2059 	n_setup = (xa->smb_msrcnt < 200) ? xa->smb_msrcnt : 200;
2060 	n_setup++;
2061 	n_setup = n_setup & ~0x0001;
2062 	n_param = (xa->smb_mprcnt < smb_maxbufsize)
2063 	    ? xa->smb_mprcnt : smb_maxbufsize;
2064 	n_param++;
2065 	n_param = n_param & ~0x0001;
2066 	rc = smb_maxbufsize - (SMBHEADERSIZE + 28 + n_setup + n_param);
2067 	n_data =  (xa->smb_mdrcnt < rc) ? xa->smb_mdrcnt : rc;
2068 	MBC_INIT(&xa->rep_setup_mb, n_setup * 2);
2069 	MBC_INIT(&xa->rep_param_mb, n_param);
2070 	MBC_INIT(&xa->rep_data_mb, n_data);
2071 
2072 	if (smb_decode_mbc(&xa->req_setup_mb, "w", &opcode) != 0)
2073 		goto trans_err_not_supported;
2074 
2075 	/*
2076 	 * Save this for /proc to read later.
2077 	 */
2078 	xa->smb_func = opcode;
2079 
2080 	/* for now, only respond to the */
2081 	switch (opcode) {
2082 	case TRANS2_CREATE_DIRECTORY:
2083 		rc = smb_com_trans2_create_directory(sr, xa);
2084 		break;
2085 
2086 	case TRANS2_FIND_FIRST2:
2087 		/*
2088 		 * Should have enough room to send the response
2089 		 * data back to client.
2090 		 */
2091 		if (n_data == 0) {
2092 			smbsr_error(sr, NT_STATUS_INFO_LENGTH_MISMATCH,
2093 			    ERRDOS, ERROR_BAD_LENGTH);
2094 			return (SDRC_ERROR_REPLY);
2095 		}
2096 		rc = smb_com_trans2_find_first2(sr, xa);
2097 		break;
2098 
2099 	case TRANS2_FIND_NEXT2:
2100 		/*
2101 		 * Should have enough room to send the response
2102 		 * data back to client.
2103 		 */
2104 		if (n_data == 0) {
2105 			smbsr_error(sr, NT_STATUS_INFO_LENGTH_MISMATCH,
2106 			    ERRDOS, ERROR_BAD_LENGTH);
2107 			return (SDRC_ERROR_REPLY);
2108 		}
2109 		rc = smb_com_trans2_find_next2(sr, xa);
2110 		break;
2111 
2112 	case TRANS2_QUERY_FS_INFORMATION:
2113 		/*
2114 		 * Should have enough room to send the response
2115 		 * data back to client.
2116 		 */
2117 		if (n_data == 0) {
2118 			smbsr_error(sr, NT_STATUS_INFO_LENGTH_MISMATCH,
2119 			    ERRDOS, ERROR_BAD_LENGTH);
2120 			return (SDRC_ERROR_REPLY);
2121 		}
2122 		rc = smb_com_trans2_query_fs_information(sr, xa);
2123 		break;
2124 
2125 	case TRANS2_QUERY_PATH_INFORMATION:
2126 		/*
2127 		 * Should have enough room to send the response
2128 		 * data back to client.
2129 		 */
2130 		if (n_data == 0) {
2131 			smbsr_error(sr, NT_STATUS_INFO_LENGTH_MISMATCH,
2132 			    ERRDOS, ERROR_BAD_LENGTH);
2133 			return (SDRC_ERROR_REPLY);
2134 		}
2135 		rc = smb_com_trans2_query_path_information(sr, xa);
2136 		break;
2137 
2138 	case TRANS2_QUERY_FILE_INFORMATION:
2139 		/*
2140 		 * Should have enough room to send the response
2141 		 * data back to client.
2142 		 */
2143 		if (n_data == 0) {
2144 			smbsr_error(sr, NT_STATUS_INFO_LENGTH_MISMATCH,
2145 			    ERRDOS, ERROR_BAD_LENGTH);
2146 			return (SDRC_ERROR_REPLY);
2147 		}
2148 		rc = smb_com_trans2_query_file_information(sr, xa);
2149 		break;
2150 
2151 	case TRANS2_SET_PATH_INFORMATION:
2152 		rc = smb_com_trans2_set_path_information(sr, xa);
2153 		break;
2154 
2155 	case TRANS2_SET_FILE_INFORMATION:
2156 		rc = smb_com_trans2_set_file_information(sr, xa);
2157 		break;
2158 	default:
2159 		goto trans_err_not_supported;
2160 	}
2161 
2162 	switch (rc) {
2163 	case SDRC_NORMAL_REPLY:
2164 		break;
2165 
2166 	case SDRC_DROP_VC:
2167 	case SDRC_NO_REPLY:
2168 	case SDRC_ERROR_REPLY:
2169 		return (rc);
2170 
2171 	case SDRC_UNIMPLEMENTED:
2172 	case SDRC_UNSUPPORTED:
2173 		goto trans_err_not_supported;
2174 
2175 	default:
2176 		break;
2177 	}
2178 
2179 	n_setup = MBC_LENGTH(&xa->rep_setup_mb);
2180 	n_param = MBC_LENGTH(&xa->rep_param_mb);
2181 	n_data  = MBC_LENGTH(&xa->rep_data_mb);
2182 
2183 	if (xa->smb_msrcnt < n_setup ||
2184 	    xa->smb_mprcnt < n_param ||
2185 	    xa->smb_mdrcnt < n_data) {
2186 		goto trans_err_too_small;
2187 	}
2188 
2189 	/* neato, blast it over there */
2190 
2191 	n_setup = (n_setup + 1) / 2;		/* Conver to setup words */
2192 	param_pad = 1;				/* must be one */
2193 	param_off = param_pad + 32 + 21 + (n_setup << 1) + 2;
2194 
2195 	/*
2196 	 * Including the nt_unknown_secret value persuades netmon to
2197 	 * display the correct data format for QueryPathInfo and
2198 	 * QueryFileInfo.
2199 	 */
2200 	if (opcode == TRANS2_QUERY_FILE_INFORMATION ||
2201 	    opcode == TRANS2_QUERY_PATH_INFORMATION) {
2202 		data_pad = sizeof (uint16_t);
2203 		data_off = param_off + n_param + data_pad;
2204 		fmt = "b ww 2. www www b . C w #. C w C";
2205 		nt_unknown_secret = 0x0100;
2206 	}
2207 	else
2208 	{
2209 		data_pad = (param_off + n_param) & 1; /* Pad to short */
2210 		/* Param off from hdr start */
2211 		data_off = param_off + n_param + data_pad;
2212 		fmt = "b ww 2. www www b . C w #. C #. C";
2213 		/*LINTED E_ASSIGN_NARROW_CONV*/
2214 		nt_unknown_secret = data_pad;
2215 	}
2216 
2217 	total_bytes = param_pad + n_param + data_pad + n_data;
2218 
2219 	rc = smbsr_encode_result(sr, 10+n_setup, total_bytes,
2220 	    fmt,
2221 	    10 + n_setup,		/* wct */
2222 	    n_param,			/* Total Parameter Bytes */
2223 	    n_data /* + data_pad */,	/* Total Data Bytes */
2224 	    n_param,			/* Total Parameter Bytes this buffer */
2225 	    param_off,			/* Param offset from header start */
2226 	    0,				/* Param displacement */
2227 	    n_data /* + data_pad */,	/* Total Data Bytes this buffer */
2228 	    data_off,			/* Data offset from header start */
2229 	    0,				/* Data displacement */
2230 	    n_setup,			/* suwcnt */
2231 	    &xa->rep_setup_mb,		/* setup[] */
2232 	    total_bytes,		/* Total data bytes */
2233 	    param_pad,
2234 	    &xa->rep_param_mb,
2235 	    nt_unknown_secret,
2236 	    &xa->rep_data_mb);
2237 	return ((rc == 0) ? SDRC_NORMAL_REPLY : SDRC_ERROR_REPLY);
2238 
2239 trans_err_too_small:
2240 	rc = NERR_BufTooSmall;
2241 	goto trans_err;
2242 
2243 trans_err_not_supported:
2244 	rc = ERROR_NOT_SUPPORTED;
2245 	goto trans_err;
2246 
2247 trans_err:
2248 	pos = MBC_LENGTH(&sr->reply) + 23;
2249 	rc = smbsr_encode_result(sr, 10, 4, "b ww 2. www www b . w ww",
2250 	    10,		/* wct */
2251 	    4, 0,	/* tpscnt tdscnt */
2252 	    4, pos, 0,	/* pscnt psoff psdisp */
2253 	    0, 0, 0,	/* dscnt dsoff dsdisp */
2254 	    0,		/* suwcnt */
2255 	    4,		/* bcc */
2256 	    rc,
2257 	    0);		/* converter word? */
2258 	return ((rc == 0) ? SDRC_NORMAL_REPLY : SDRC_ERROR_REPLY);
2259 }
2260 
2261 smb_xa_t *
2262 smb_xa_create(
2263     smb_session_t	*session,
2264     smb_request_t	*sr,
2265     uint32_t		total_parameter_count,
2266     uint32_t		total_data_count,
2267     uint32_t		max_parameter_count,
2268     uint32_t		max_data_count,
2269     uint32_t		max_setup_count,
2270     uint32_t		setup_word_count)
2271 {
2272 	smb_xa_t	*xa, *nxa;
2273 	smb_llist_t	*xlist;
2274 
2275 	xa = MEM_ZALLOC("xa", sizeof (smb_xa_t));
2276 	xa->xa_refcnt = 1;
2277 	xa->smb_com = sr->smb_com;
2278 	xa->smb_flg = sr->smb_flg;
2279 	xa->smb_flg2 = sr->smb_flg2;
2280 	xa->smb_tid = sr->smb_tid;
2281 	xa->smb_pid = sr->smb_pid;
2282 	xa->smb_uid = sr->smb_uid;
2283 	xa->xa_smb_mid = sr->smb_mid;
2284 	xa->reply_seqnum = sr->reply_seqnum;
2285 	xa->smb_tpscnt = total_parameter_count;
2286 	xa->smb_tdscnt = total_data_count;
2287 	xa->smb_mprcnt = max_parameter_count;
2288 	xa->smb_mdrcnt = max_data_count;
2289 	xa->smb_msrcnt = max_setup_count;
2290 	xa->smb_suwcnt = setup_word_count;
2291 	xa->xa_session = session;
2292 	xa->xa_magic = SMB_XA_MAGIC;
2293 
2294 	/*
2295 	 * The new xa structure is checked against the current list to see
2296 	 * if it exists already.
2297 	 */
2298 	xlist = &session->s_xa_list;
2299 	smb_llist_enter(xlist, RW_WRITER);
2300 	nxa = smb_llist_head(xlist);
2301 	while (nxa) {
2302 		ASSERT(nxa->xa_magic == SMB_XA_MAGIC);
2303 		if (nxa->xa_smb_mid == xa->xa_smb_mid &&
2304 		    nxa->smb_pid == xa->smb_pid &&
2305 		    !SMB_XA_CLOSED(nxa) &&
2306 		    !(nxa->xa_flags & SMB_XA_FLAG_COMPLETE)) {
2307 			smb_llist_exit(xlist);
2308 			MEM_FREE("xa", xa);
2309 			return (NULL);
2310 		}
2311 		nxa = smb_llist_next(xlist, nxa);
2312 	}
2313 	smb_llist_insert_tail(xlist, xa);
2314 	smb_llist_exit(xlist);
2315 	return (xa);
2316 }
2317 
2318 void
2319 smb_xa_delete(smb_xa_t *xa)
2320 {
2321 	ASSERT(xa->xa_refcnt == 0);
2322 	ASSERT(SMB_XA_CLOSED(xa));
2323 
2324 	if (xa->xa_smb_trans_name)
2325 		MEM_FREE("smb", xa->xa_smb_trans_name);
2326 
2327 	if (xa->rep_setup_mb.chain != NULL)
2328 		m_freem(xa->rep_setup_mb.chain);
2329 	if (xa->rep_param_mb.chain != NULL)
2330 		m_freem(xa->rep_param_mb.chain);
2331 	if (xa->rep_data_mb.chain != NULL)
2332 		m_freem(xa->rep_data_mb.chain);
2333 
2334 	xa->xa_magic = (uint32_t)~SMB_XA_MAGIC;
2335 	MEM_FREE("xa", xa);
2336 }
2337 
2338 smb_xa_t *
2339 smb_xa_hold(smb_xa_t *xa)
2340 {
2341 	mutex_enter(&xa->xa_mutex);
2342 	xa->xa_refcnt++;
2343 	ASSERT(xa->xa_refcnt);
2344 	mutex_exit(&xa->xa_mutex);
2345 	return (xa);
2346 }
2347 
2348 void
2349 smb_xa_rele(smb_session_t *session, smb_xa_t *xa)
2350 {
2351 	mutex_enter(&xa->xa_mutex);
2352 	ASSERT(xa->xa_refcnt);
2353 	xa->xa_refcnt--;
2354 	if (SMB_XA_CLOSED(xa) && (xa->xa_refcnt == 0)) {
2355 		mutex_exit(&xa->xa_mutex);
2356 		smb_llist_enter(&session->s_xa_list, RW_WRITER);
2357 		smb_llist_remove(&session->s_xa_list, xa);
2358 		smb_llist_exit(&session->s_xa_list);
2359 		smb_xa_delete(xa);
2360 		return;
2361 	}
2362 	mutex_exit(&xa->xa_mutex);
2363 }
2364 
2365 int
2366 smb_xa_open(smb_xa_t *xa)
2367 {
2368 	int rc;
2369 
2370 	mutex_enter(&xa->xa_mutex);
2371 
2372 	ASSERT((xa->xa_flags & SMB_XA_FLAG_OPEN) == 0);
2373 
2374 	if ((xa->xa_flags & SMB_XA_FLAG_CLOSE) == 0) {
2375 		xa->xa_flags |= SMB_XA_FLAG_OPEN;
2376 		rc = 0;
2377 	} else {
2378 		rc = ERROR_INVALID_HANDLE;
2379 	}
2380 
2381 	mutex_exit(&xa->xa_mutex);
2382 
2383 	return (rc);
2384 }
2385 
2386 void
2387 smb_xa_close(smb_xa_t *xa)
2388 {
2389 	mutex_enter(&xa->xa_mutex);
2390 	xa->xa_flags |= SMB_XA_FLAG_CLOSE;
2391 	xa->xa_flags &= ~SMB_XA_FLAG_OPEN;
2392 
2393 	if (xa->xa_refcnt == 0) {
2394 		mutex_exit(&xa->xa_mutex);
2395 		smb_llist_enter(&xa->xa_session->s_xa_list, RW_WRITER);
2396 		smb_llist_remove(&xa->xa_session->s_xa_list, xa);
2397 		smb_llist_exit(&xa->xa_session->s_xa_list);
2398 		smb_xa_delete(xa);
2399 		return;
2400 	}
2401 
2402 	mutex_exit(&xa->xa_mutex);
2403 }
2404 
2405 int
2406 smb_xa_complete(smb_xa_t *xa)
2407 {
2408 	int rc;
2409 
2410 	mutex_enter(&xa->xa_mutex);
2411 	if (xa->xa_flags & (SMB_XA_FLAG_COMPLETE | SMB_XA_FLAG_CLOSE)) {
2412 		rc = 0;
2413 	} else {
2414 		rc = 1;
2415 		xa->xa_flags |= SMB_XA_FLAG_COMPLETE;
2416 	}
2417 	mutex_exit(&xa->xa_mutex);
2418 	return (rc);
2419 }
2420 
2421 smb_xa_t *
2422 smb_xa_find(
2423     smb_session_t	*session,
2424     uint16_t		pid,
2425     uint16_t		mid)
2426 {
2427 	smb_xa_t	*xa;
2428 	smb_llist_t	*xlist;
2429 
2430 	xlist = &session->s_xa_list;
2431 	smb_llist_enter(xlist, RW_READER);
2432 	xa = smb_llist_head(xlist);
2433 	while (xa) {
2434 		mutex_enter(&xa->xa_mutex);
2435 		if (xa->xa_smb_mid == mid &&
2436 		    xa->smb_pid == pid &&
2437 		    !SMB_XA_CLOSED(xa) &&
2438 		    !(xa->xa_flags & SMB_XA_FLAG_COMPLETE)) {
2439 			xa->xa_refcnt++;
2440 			ASSERT(xa->xa_refcnt);
2441 			mutex_exit(&xa->xa_mutex);
2442 			break;
2443 		}
2444 		mutex_exit(&xa->xa_mutex);
2445 		xa = smb_llist_next(xlist, xa);
2446 	}
2447 	smb_llist_exit(xlist);
2448 	return (xa);
2449 }
2450