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