xref: /illumos-gate/usr/src/uts/common/fs/smbsrv/smb_common_transact.c (revision ca9327a6de44d69ddab3668cc1e143ce781387a3)
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 	unsigned int cpid = oem_get_smb_cpid();
736 	unsigned int length;
737 	char name_buf[MAX_SHARE_NAME_LEN];
738 	mts_wchar_t *unibuf;
739 	char *tmpbuf;
740 	int rc = 0;
741 
742 	tmpbuf = (name == NULL) ? "" : (char *)name;
743 	length = strlen(tmpbuf) + 1;
744 
745 	unibuf = kmem_alloc(length * sizeof (mts_wchar_t), KM_SLEEP);
746 	(void) mts_mbstowcs(unibuf, tmpbuf, length);
747 
748 	tmpbuf = kmem_alloc(length, KM_SLEEP);
749 	if (unicodestooems(tmpbuf, unibuf, length, cpid) == 0)
750 		(void) strcpy(tmpbuf, (char *)name);
751 
752 	if (strlen(tmpbuf) + 1 <= MAX_SHARE_NAME_LEN) {
753 		bzero(name_buf, sizeof (name_buf));
754 		(void) strcpy(name_buf, tmpbuf);
755 		(void) smb_encode_mbc(output, "13c", name_buf);
756 	} else {
757 		rc = -1;
758 	}
759 
760 	kmem_free(unibuf, length * sizeof (mts_wchar_t));
761 	kmem_free(tmpbuf, length);
762 
763 	return (rc);
764 }
765 
766 static int
767 smb_emit_SHARE_INFO_1(struct mbuf_chain *output, struct mbuf_chain *text,
768     unsigned char *name, uint16_t type,
769     unsigned char *comment)
770 {
771 	if (smb_emit_SHARE_INFO_0(output, name) < 0)
772 		return (-1);
773 
774 	(void) smb_encode_mbc(output, ".wl", type, MBC_LENGTH(text));
775 	(void) smb_encode_mbc(text, "s",
776 	    (comment ? comment : (unsigned char *)"No comment"));
777 	return (0);
778 }
779 
780 static void /*ARGSUSED*/
781 smb_emit_SHARE_INFO_2(struct mbuf_chain *output, struct mbuf_chain *text,
782 	struct smb_request *sr, unsigned char *name, uint16_t type,
783 	unsigned char *comment, uint16_t access, char *path, char *password)
784 {
785 	unsigned char	pword[9];
786 
787 	/*
788 	 * XXX PGD.  Is there a bug here?  We zero pword, copy password
789 	 * into pword then ignore it and use password for smb_encode_mbc?
790 	 */
791 	bzero(pword, sizeof (pword));
792 	(void) strncpy((char *)pword, password, sizeof (pword));
793 	(void) smb_emit_SHARE_INFO_1(output, text, name, type, comment);
794 	(void) smb_encode_mbc(output, "wwwl9c.",
795 	    access,
796 	    sr->sr_cfg->skc_maxconnections,
797 	    smb_server_get_session_count(),
798 	    MBC_LENGTH(text),
799 	    password);
800 	(void) smb_encode_mbc(text, "s", path);
801 }
802 
803 /*
804  * is_long_sharename
805  *
806  * This function is extracted from smb_emit_SHARE_INFO_0 only for
807  * finding shares that their names are longer than MAX_SHARE_NAME_LEN.
808  *
809  * The function returns 1 for long share names and 0 when the length
810  * is Ok.
811  */
812 static boolean_t
813 is_long_sharename(unsigned char *name)
814 {
815 	unsigned int cpid = oem_get_smb_cpid();
816 	size_t length;
817 	mts_wchar_t *unibuf;
818 	char *tmpbuf;
819 	boolean_t islong;
820 
821 	tmpbuf = (name == NULL) ? "" : (char *)name;
822 	length = strlen(tmpbuf) + 1;
823 
824 	unibuf = kmem_alloc(length * sizeof (mts_wchar_t), KM_SLEEP);
825 	(void) mts_mbstowcs(unibuf, tmpbuf, length);
826 
827 	tmpbuf = kmem_alloc(length, KM_SLEEP);
828 	if (unicodestooems(tmpbuf, unibuf, length, cpid) == 0)
829 		(void) strcpy(tmpbuf, (char *)name);
830 
831 	islong = (strlen(tmpbuf) + 1 > MAX_SHARE_NAME_LEN);
832 
833 	kmem_free(unibuf, length * sizeof (mts_wchar_t));
834 	kmem_free(tmpbuf, length);
835 
836 	return (islong);
837 }
838 
839 /*
840  * This structure holds information about shares which will
841  * fit in the specified client buffer size.
842  *
843  * sei_bufsize: Client specified buffer size
844  * sei_count: Maximum number of shares that can be
845  *            sent in the buffer.
846  *
847  * The return data section consists of a number of SHARE_INFO_1 structures.
848  * In case there are multiple SHARE_INFO_1 data structures to return this
849  * function put all fixed length part of these structures in the return buffer
850  * and then put all the variable length data (shares' comment) at the end of
851  * buffer.
852  *
853  * sei_info_len: Size of fixed length part of SHARE_INFO_1
854  *               structures for sei_count shares
855  * sei_cmnt_len: Size of comments for sei_count shares
856  */
857 typedef struct {
858 	uint16_t sei_bufsize;
859 	short sei_count;
860 	int   sei_infolen;
861 	int   sei_cmntlen;
862 } smb_share_enum_t;
863 
864 /*
865  * smb_share_update_info
866  *
867  * Check to see if the given buffer has enough
868  * room to fit the information of the given share.
869  * If there is enough room update the passed max_???
870  * information.
871  *
872  * Return 1 if buffer is not full yet, 0 if it's full.
873  */
874 static int
875 smb_share_update_info(door_handle_t dhdl, lmshare_info_t *si,
876     smb_share_enum_t *shr_enum_info)
877 {
878 	int cmnt_len;
879 	int new_info_len = shr_enum_info->sei_infolen;
880 	int new_cmnt_len = shr_enum_info->sei_cmntlen;
881 
882 	if (lmshrd_is_special(dhdl, si->share_name))
883 		cmnt_len = 1;
884 	else
885 		cmnt_len = (strlen(si->comment) + 1);
886 
887 	new_info_len += SHARE_INFO_1_SIZE;
888 	new_cmnt_len += cmnt_len;
889 
890 	if ((new_info_len + new_cmnt_len) < shr_enum_info->sei_bufsize) {
891 		shr_enum_info->sei_count++;
892 		shr_enum_info->sei_infolen = new_info_len;
893 		shr_enum_info->sei_cmntlen = new_cmnt_len;
894 		return (1);
895 	}
896 
897 	return (0);
898 }
899 
900 /*
901  * smb_share_skip_share
902  *
903  * Determines whether the given share should be enumerated
904  * or not. The share will not be enumerated if its name is
905  * long or it's autohome share.
906  *
907  * Return 1 if the share should be skipped; otherwise returns
908  * 0
909  */
910 static int
911 smb_share_skip_share(lmshare_info_t *si)
912 {
913 	if (is_long_sharename((unsigned char *)si->share_name)) {
914 		return (1);
915 	}
916 
917 	/* Skip autohome share if autohome filter is enabled */
918 	if (si->mode == LMSHRM_TRANS) {
919 		return (1);
920 	}
921 
922 	return (0);
923 }
924 
925 /*
926  * smb_share_add_autohome
927  *
928  * Determines if an autohome share should be added to shares' list
929  * for the given user.
930  * Autohome will be add when all the following conditions are true:
931  *
932  *  1. Autohome feature is enabled
933  *  2. A share with the same name as the given user exists
934  *  3. The share is not a permanent share
935  *  4. Share name is not longer than maximum allowed
936  */
937 static int
938 smb_share_add_autohome(door_handle_t dhdl, char *username, lmshare_info_t *si)
939 {
940 	int do_add = 0;
941 
942 	do_add = (lmshrd_getinfo(dhdl, username, si) == NERR_Success) &&
943 	    (si->mode & LMSHRM_TRANS) &&
944 	    (!is_long_sharename((unsigned char *)(si->share_name)));
945 
946 	return (do_add);
947 }
948 
949 /*
950  * smb_share_total_info
951  *
952  * This function calculates following informations
953  *	- Maximum number of shares that can be sent for clients
954  *	  according to its buffer size (cli_bufsize)
955  *	- length of fixed information about above shares
956  *	- length of comments of above shares
957  *	- total number of shares that their names are no longer
958  *	  than MAX_SHARE_NAME_LEN.
959  *
960  * Added SMB user object to the parameter list to filter out other
961  * user autohome shares.
962  */
963 static void
964 smb_share_total_info(door_handle_t dhdl, smb_share_enum_t *shr_enum_info,
965     short *tot_shares_num, smb_user_t *user)
966 {
967 	uint64_t iterator;
968 	lmshare_info_t *si;
969 	struct lmshare_info *auto_si;
970 	int more_room = 1;
971 
972 	si = kmem_zalloc(sizeof (lmshare_info_t), KM_SLEEP);
973 	auto_si = kmem_zalloc(sizeof (struct lmshare_info), KM_SLEEP);
974 
975 	*tot_shares_num = 0;
976 	shr_enum_info->sei_count = 0;
977 	shr_enum_info->sei_infolen = 0;
978 	shr_enum_info->sei_cmntlen = 0;
979 
980 	if (smb_share_add_autohome(dhdl, user->u_name, auto_si)) {
981 		(*tot_shares_num)++;
982 		more_room = smb_share_update_info(dhdl, auto_si, shr_enum_info);
983 	}
984 
985 	iterator = lmshrd_open_iterator(dhdl, LMSHRM_ALL);
986 	if (iterator == 0) {
987 		kmem_free(si, sizeof (lmshare_info_t));
988 		kmem_free(auto_si, sizeof (struct lmshare_info));
989 		return;
990 	}
991 
992 	/* check for door errors */
993 	if (lmshrd_iterate(dhdl, iterator, si) != NERR_Success) {
994 		(void) lmshrd_close_iterator(dhdl, iterator);
995 		kmem_free(si, sizeof (lmshare_info_t));
996 		kmem_free(auto_si, sizeof (struct lmshare_info));
997 		return;
998 	}
999 
1000 	while (*si->share_name != 0) {
1001 		if (smb_share_skip_share(si)) {
1002 			/* check for door errors */
1003 			if (lmshrd_iterate(dhdl, iterator, si) !=
1004 			    NERR_Success) {
1005 				(void) lmshrd_close_iterator(dhdl, iterator);
1006 				kmem_free(si, sizeof (lmshare_info_t));
1007 				kmem_free(auto_si,
1008 				    sizeof (struct lmshare_info));
1009 				return;
1010 			}
1011 			continue;
1012 		}
1013 
1014 		(*tot_shares_num)++;
1015 
1016 		if (more_room) {
1017 			more_room = smb_share_update_info(dhdl, si,
1018 			    shr_enum_info);
1019 		}
1020 
1021 		/* check for door errors */
1022 		if (lmshrd_iterate(dhdl, iterator, si) != NERR_Success) {
1023 			(void) lmshrd_close_iterator(dhdl, iterator);
1024 			kmem_free(si, sizeof (lmshare_info_t));
1025 			kmem_free(auto_si, sizeof (struct lmshare_info));
1026 			return;
1027 		}
1028 	}
1029 
1030 	(void) lmshrd_close_iterator(dhdl, iterator);
1031 	kmem_free(si, sizeof (lmshare_info_t));
1032 	kmem_free(auto_si, sizeof (struct lmshare_info));
1033 }
1034 
1035 /*
1036  * smb_encode_SHARE_INFO_1
1037  *
1038  * This function is extracted from smb_emit_SHARE_INFO_1 and only
1039  * encodes fixed part of SHARE_INFO_1 structure.
1040  *
1041  * The function returns -1 if encoding fails and 0 on success.
1042  */
1043 static int
1044 smb_encode_SHARE_INFO_1(struct mbuf_chain *output, unsigned char *name,
1045     uint16_t type, int cmnt_len)
1046 {
1047 	if (smb_emit_SHARE_INFO_0(output, name) < 0)
1048 		return (-1);
1049 	(void) smb_encode_mbc(output, ".wl", type, cmnt_len);
1050 	return (0);
1051 }
1052 
1053 /*
1054  * collect_shares_info
1055  *
1056  * This function encodes information of shares_num of shares
1057  * into data_mb and cmnt_str.
1058  *
1059  * Added SMB user object to the parameter list to filter out other
1060  * user autohome shares.
1061  *
1062  */
1063 static void
1064 collect_shares_info(door_handle_t dhdl, uint64_t iterator, int shares_num,
1065     struct mbuf_chain *data_mb, char *cmnt_str, int *cmnt_len, smb_user_t *user,
1066     int first_resp)
1067 {
1068 	int i = 0;
1069 	lmshare_info_t *si;
1070 	struct lmshare_info *tsi;
1071 	int is_special;
1072 
1073 	si = kmem_zalloc(sizeof (lmshare_info_t), KM_SLEEP);
1074 	tsi = kmem_zalloc(sizeof (struct lmshare_info), KM_SLEEP);
1075 
1076 	if (first_resp && smb_share_add_autohome(dhdl, user->u_name, tsi)) {
1077 		if (smb_encode_SHARE_INFO_1(data_mb,
1078 		    (unsigned char *)tsi->share_name,
1079 		    tsi->stype, *cmnt_len) == 0) {
1080 			(void) memcpy(cmnt_str+(*cmnt_len),
1081 			    tsi->comment, strlen(tsi->comment)+1);
1082 			(*cmnt_len) += (strlen(tsi->comment) + 1);
1083 			i++;
1084 		}
1085 	}
1086 
1087 	/* check for door errors */
1088 	if (lmshrd_iterate(dhdl, iterator, si) != NERR_Success) {
1089 		kmem_free(si, sizeof (lmshare_info_t));
1090 		kmem_free(tsi, sizeof (struct lmshare_info));
1091 		return;
1092 	}
1093 
1094 	while ((i < shares_num) && (*si->share_name != 0)) {
1095 		if (smb_share_skip_share(si)) {
1096 			goto next;
1097 		}
1098 
1099 
1100 		is_special = lmshrd_is_special(dhdl, si->share_name);
1101 		/* check for door errors */
1102 		if (is_special == NERR_InternalError) {
1103 			kmem_free(si, sizeof (lmshare_info_t));
1104 			kmem_free(tsi, sizeof (struct lmshare_info));
1105 			return;
1106 		}
1107 
1108 		if (is_special) {
1109 			si->stype |= STYPE_HIDDEN;
1110 			if (smb_encode_SHARE_INFO_1(data_mb,
1111 			    (unsigned char *)si->share_name,
1112 			    si->stype, *cmnt_len) < 0) {
1113 				goto next;
1114 			}
1115 			cmnt_str[*cmnt_len] = '\0';
1116 			(*cmnt_len)++;
1117 		} else {
1118 			if (smb_encode_SHARE_INFO_1(data_mb,
1119 			    (unsigned char *)si->share_name, si->stype,
1120 			    *cmnt_len) < 0) {
1121 				goto next;
1122 			}
1123 			(void) memcpy(cmnt_str+(*cmnt_len), si->comment,
1124 			    strlen(si->comment)+1);
1125 			(*cmnt_len) += (strlen(si->comment) + 1);
1126 		}
1127 
1128 	next:
1129 		/* check for door errors */
1130 		if (lmshrd_iterate(dhdl, iterator, si) != NERR_Success) {
1131 			kmem_free(si, sizeof (lmshare_info_t));
1132 			kmem_free(tsi, sizeof (struct lmshare_info));
1133 			return;
1134 		}
1135 	}
1136 	kmem_free(si, sizeof (lmshare_info_t));
1137 	kmem_free(tsi, sizeof (struct lmshare_info));
1138 }
1139 
1140 int
1141 smb_trans_net_share_enum(struct smb_request *sr, struct smb_xa *xa)
1142 {
1143 	door_handle_t dhdl = sr->sr_server->sv_lmshrd;
1144 	smb_share_enum_t shr_enum_info;
1145 	short left_shares_cnt;		/* Number of shares not sent yet */
1146 
1147 	/*
1148 	 * Number of shares that should be sent
1149 	 * in the current response packet.
1150 	 * It can be a number between 0 and
1151 	 * max_share_scnt.
1152 	 */
1153 	short shares_scnt;
1154 
1155 	/*
1156 	 * Maximum number of shares that can be
1157 	 * sent in one response packet regarding
1158 	 * the maximum negotiated buffer size
1159 	 * for SMB messages.
1160 	 */
1161 	short max_shares_per_packet;
1162 
1163 	/*
1164 	 * Total number of shares on the server
1165 	 * that their name is not greater than
1166 	 * MAX_SHARE_NAME_LEN
1167 	 */
1168 	short shares_tot_num;
1169 
1170 	/*
1171 	 * Size of total data (info + cmnt)
1172 	 * that should be sent for client
1173 	 */
1174 	int shares_tot_byte;
1175 
1176 	/*
1177 	 * Maximum size of data that can be
1178 	 * sent in one SMB transaction response
1179 	 * according to the maximum negotiated
1180 	 * buffer size for SMB  packets
1181 	 */
1182 	int data_buf_limit;
1183 
1184 	/*
1185 	 * Number of comment bytes that will
1186 	 * be sent in the current response
1187 	 */
1188 	uint16_t cmnt_scnt;
1189 
1190 	/*
1191 	 * Number of data bytes that will
1192 	 * be sent in the current response
1193 	 */
1194 	uint16_t data_scnt;
1195 
1196 	/*
1197 	 * Total number of data bytes that
1198 	 * are sent till now. This is only
1199 	 * used for calculating current data
1200 	 * displacement
1201 	 */
1202 	uint16_t tot_data_scnt;
1203 
1204 	/*
1205 	 * Number of parameter bytes should
1206 	 * be sent for the current response.
1207 	 * It is 8 for the 1st response and
1208 	 * 0 for others
1209 	 */
1210 	uint16_t param_scnt;
1211 
1212 	/* number of setup and parameter bytes */
1213 	uint16_t n_setup, n_param;
1214 
1215 	/* data and parameter displacement */
1216 	uint16_t data_disp, param_disp;
1217 
1218 	/* return status by the 1st reply */
1219 	uint16_t ret_stat;
1220 
1221 	/* parameter and data offset and pad */
1222 	int param_off, param_pad, data_off, data_pad;
1223 
1224 	/*
1225 	 * total bytes of parameters and data
1226 	 * in the packet, plus the pad bytes.
1227 	 */
1228 	int tot_packet_bytes;
1229 
1230 	char first_resp;
1231 	uint16_t opcode, level, cli_bufsize;
1232 	unsigned char *r_fmt;
1233 	char fmt[10];
1234 	uint64_t iterator;
1235 	char *cmnt_str, *cmnt_start;
1236 	int cmnt_len;
1237 	struct mbuf_chain reply;
1238 	smb_user_t *user;
1239 	size_t cmnt_size;
1240 
1241 	user = sr->uid_user;
1242 	ASSERT(user);
1243 
1244 	/*
1245 	 * Initialize the mbuf chain of reply to zero. If it is not
1246 	 * zero, code inside the while loop will try to free the chain.
1247 	 */
1248 	bzero(&reply, sizeof (struct mbuf_chain));
1249 
1250 	if (smb_decode_mbc(&xa->req_param_mb, "%wss(lev)w(size)w", sr,
1251 	    &opcode, &r_fmt, &r_fmt, &level, &cli_bufsize) != 0)
1252 		return (SDRC_NOT_IMPLEMENTED);
1253 
1254 	if (level != 1) {
1255 		(void) smb_encode_mbc(&xa->rep_param_mb, "wwww",
1256 		    NERR_BadTransactConfig, 0, 0, 0);
1257 		return (SDRC_SUCCESS);
1258 	}
1259 
1260 	n_setup = 0;	/* Setup count for NetShareEnum SMB is 0 */
1261 	n_param = 8;
1262 	data_buf_limit = sr->session->smb_msg_size -
1263 	    (SMB_HEADER_ED_LEN + RESP_HEADER_LEN + n_param);
1264 
1265 	shr_enum_info.sei_bufsize = cli_bufsize;
1266 	smb_share_total_info(dhdl, &shr_enum_info, &shares_tot_num, user);
1267 
1268 	shares_tot_byte = shr_enum_info.sei_infolen + shr_enum_info.sei_cmntlen;
1269 
1270 	/* Check buffer to have enough space */
1271 	if (shares_tot_byte == 0) {
1272 		(void) smb_encode_mbc(&xa->rep_param_mb, "wwww",
1273 		    ERROR_NOT_ENOUGH_MEMORY, 0, 0, 0);
1274 		return (SDRC_SUCCESS);
1275 	}
1276 
1277 	max_shares_per_packet = data_buf_limit / SHARE_INFO_1_SIZE;
1278 
1279 	shares_scnt = (shr_enum_info.sei_count > max_shares_per_packet)
1280 	    ? max_shares_per_packet : shr_enum_info.sei_count;
1281 
1282 	cmnt_size = shr_enum_info.sei_cmntlen * sizeof (char);
1283 	cmnt_str = kmem_alloc(cmnt_size, KM_SLEEP);
1284 	cmnt_len = 0;
1285 	/* save start of buffer to free it at the end of function */
1286 	cmnt_start = cmnt_str;
1287 
1288 	iterator = lmshrd_open_iterator(dhdl, LMSHRM_ALL);
1289 
1290 	if (iterator == NULL) {
1291 		kmem_free(cmnt_start, cmnt_size);
1292 		return (SDRC_DROP_VC);
1293 	}
1294 
1295 	/*
1296 	 * The rep_setup_mb is already initialized in smb_trans_dispatch().
1297 	 * Calling MBC_INIT() will initialized the structure and so the
1298 	 * pointer to the mbuf chains will be lost. Therefore, we need
1299 	 * to free the resources before calling MBC_INIT() again.
1300 	 */
1301 	m_freem(xa->rep_setup_mb.chain);
1302 	MBC_INIT(&xa->rep_setup_mb, n_setup * 2);
1303 
1304 	left_shares_cnt = shr_enum_info.sei_count;
1305 	tot_data_scnt = 0;
1306 	cmnt_scnt = 0;
1307 
1308 	first_resp = 1;
1309 	while (tot_data_scnt < shares_tot_byte) {
1310 		/*
1311 		 * Calling MBC_INIT() will initialized the structure and so the
1312 		 * pointer to the mbuf chains will be lost. Therefore, we need
1313 		 * to free the resources if any before calling MBC_INIT().
1314 		 */
1315 		m_freem(xa->rep_data_mb.chain);
1316 		MBC_INIT(&xa->rep_data_mb, data_buf_limit);
1317 		collect_shares_info(dhdl, iterator,
1318 		    shares_scnt, &xa->rep_data_mb, cmnt_str, &cmnt_len, user,
1319 		    first_resp);
1320 		data_scnt = shares_scnt * SHARE_INFO_1_SIZE;
1321 		left_shares_cnt -= shares_scnt;
1322 		if (left_shares_cnt < max_shares_per_packet)
1323 			shares_scnt = left_shares_cnt;
1324 		if (left_shares_cnt == 0) {
1325 			/*
1326 			 * Now send comments.
1327 			 * Append comments to the end of share_info_1
1328 			 * structures.
1329 			 */
1330 			cmnt_scnt = data_buf_limit -
1331 			    MBC_LENGTH(&xa->rep_data_mb);
1332 			if (cmnt_scnt > shr_enum_info.sei_cmntlen) {
1333 				/*LINTED E_ASSIGN_NARROW_CONV*/
1334 				cmnt_scnt = shr_enum_info.sei_cmntlen;
1335 			}
1336 			(void) sprintf(fmt, "%dc", cmnt_scnt);
1337 			(void) smb_encode_mbc(&xa->rep_data_mb, fmt, cmnt_str);
1338 			cmnt_str += cmnt_scnt;
1339 			shr_enum_info.sei_cmntlen -= cmnt_scnt;
1340 		}
1341 		data_scnt += cmnt_scnt;
1342 		tot_data_scnt += data_scnt;
1343 
1344 		/* Only the 1st response packet contains parameters */
1345 		param_scnt = (first_resp) ? n_param : 0;
1346 		param_pad = 1;				/* always one */
1347 		param_off = SMB_HEADER_ED_LEN + RESP_HEADER_LEN;
1348 		param_disp = (first_resp) ? 0 : n_param;
1349 
1350 		/*
1351 		 * Calling MBC_INIT() will initialized the structure and so the
1352 		 * pointer to the mbuf chains will be lost. Therefore, we need
1353 		 * to free the resources if any before calling MBC_INIT().
1354 		 */
1355 		m_freem(xa->rep_param_mb.chain);
1356 		MBC_INIT(&xa->rep_param_mb, param_scnt);
1357 		if (first_resp) {
1358 			first_resp = 0;
1359 			/* Prepare parameters for the 1st response packet */
1360 			ret_stat = (shares_tot_num > shr_enum_info.sei_count)
1361 			    ? ERROR_MORE_DATA : 0;
1362 			(void) smb_encode_mbc(&xa->rep_param_mb, "wwww",
1363 			    ret_stat, -shr_enum_info.sei_infolen,
1364 			    shr_enum_info.sei_count,
1365 			    shares_tot_num);
1366 		}
1367 
1368 		data_pad = (param_off + n_param) & 1;	/* Pad to short */
1369 
1370 		/* data off from hdr start */
1371 		data_off = param_off + param_scnt + data_pad;
1372 		data_disp = tot_data_scnt - data_scnt;
1373 		tot_packet_bytes = param_pad + param_scnt + data_pad +
1374 		    data_scnt;
1375 
1376 		/*
1377 		 * Calling MBC_INIT() will initialized the structure and so the
1378 		 * pointer to the mbuf chains will be lost. Therefore, we need
1379 		 * to free the resources if any before calling MBC_INIT().
1380 		 */
1381 		m_freem(reply.chain);
1382 		MBC_INIT(&reply, SMB_HEADER_ED_LEN
1383 		    + sizeof (uchar_t)		/* word parameters count */
1384 		    + 10*sizeof (ushort_t)	/* word parameters */
1385 		    + n_setup*sizeof (ushort_t)	/* setup parameters */
1386 		    + sizeof (ushort_t)		/* total data byte count */
1387 		    + tot_packet_bytes);
1388 
1389 		(void) smb_encode_mbc(&reply, SMB_HEADER_ED_FMT,
1390 		    sr->first_smb_com,
1391 		    sr->smb_rcls,
1392 		    sr->smb_reh,
1393 		    sr->smb_err,
1394 		    sr->smb_flg | SMB_FLAGS_REPLY,
1395 		    sr->smb_flg2,
1396 		    sr->smb_pid_high,
1397 		    sr->smb_sig,
1398 		    sr->smb_tid,
1399 		    sr->smb_pid,
1400 		    sr->smb_uid,
1401 		    sr->smb_mid);
1402 
1403 		(void) smb_encode_mbc(&reply,
1404 		    "b ww 2. www www b . C w #. C #. C",
1405 		    10 + n_setup,	/* wct */
1406 		    n_param,		/* Total Parameter Bytes */
1407 		    shares_tot_byte,	/* Total Data Bytes */
1408 		    param_scnt,		/* Total Parameter Bytes this buffer */
1409 		    param_off,		/* Param offset from header start */
1410 		    param_disp,		/* Param displacement */
1411 		    data_scnt,		/* Total Data Bytes this buffer */
1412 		    data_off,		/* Data offset from header start */
1413 		    data_disp,		/* Data displacement */
1414 		    n_setup,		/* suwcnt */
1415 		    &xa->rep_setup_mb, 	/* setup[] */
1416 		    tot_packet_bytes,	/* Total data bytes */
1417 		    param_pad,
1418 		    &xa->rep_param_mb,
1419 		    data_pad,
1420 		    &xa->rep_data_mb);
1421 
1422 		if (sr->session->signing.flags & SMB_SIGNING_ENABLED)
1423 			smb_sign_reply(sr, NULL);
1424 
1425 		(void) smb_session_send(sr->session, 0, &reply);
1426 	}
1427 
1428 	(void) lmshrd_close_iterator(dhdl, iterator);
1429 	kmem_free(cmnt_start, cmnt_size);
1430 	return (SDRC_NO_REPLY);
1431 }
1432 
1433 int
1434 smb_trans_net_share_get_info(smb_request_t *sr, struct smb_xa *xa)
1435 {
1436 	uint16_t		opcode, level, max_bytes, access;
1437 	uint32_t		type;
1438 	unsigned char		*req_fmt;
1439 	unsigned char		*rep_fmt;
1440 	struct mbuf_chain	str_mb;
1441 	char			*share;
1442 	char			*path;
1443 	char			*password;
1444 	char			*comment;
1445 	lmshare_info_t		si;
1446 	int			shr_found;
1447 
1448 	if (smb_decode_mbc(&xa->req_param_mb, "%wsss(lev)w(size)w", sr,
1449 	    &opcode, &req_fmt, &rep_fmt, &share, &level, &max_bytes) != 0)
1450 		return (SDRC_NOT_IMPLEMENTED);
1451 
1452 	(void) utf8_strlwr(share);
1453 	shr_found = lmshrd_getinfo(sr->sr_server->sv_lmshrd, share, &si);
1454 	if (strcmp(share, "ipc$") == 0) {
1455 		type = STYPE_IPC;
1456 		path = "";
1457 		password = "";
1458 		access = SHARE_ACCESS_ALL;
1459 	} else if (shr_found) {
1460 		path = si.directory;
1461 		type = STYPE_DISKTREE;
1462 		if (path[strlen(path)] == '$')
1463 			type |= STYPE_HIDDEN;
1464 		password = "";
1465 		access = SHARE_ACCESS_ALL;
1466 	} else {
1467 		/* We have no idea what this share is... */
1468 		(void) smb_encode_mbc(&xa->rep_param_mb, "www",
1469 		    NERR_NetNameNotFound, 0, 0);
1470 		return (SDRC_SUCCESS);
1471 	}
1472 
1473 	if (shr_found)
1474 		comment = si.comment;
1475 	else
1476 		comment = "";
1477 
1478 	password = "";
1479 
1480 	MBC_INIT(&str_mb, max_bytes);
1481 
1482 	switch (level) {
1483 	case 0 :
1484 		(void) smb_emit_SHARE_INFO_0(&xa->rep_data_mb,
1485 		    (unsigned char *)share);
1486 		break;
1487 
1488 	case 1 :
1489 		(void) smb_emit_SHARE_INFO_1(&xa->rep_data_mb, &str_mb,
1490 		    (unsigned char *)share, type,
1491 		    (unsigned char *)comment);
1492 		break;
1493 
1494 	case 2 :
1495 		smb_emit_SHARE_INFO_2(&xa->rep_data_mb, &str_mb, sr,
1496 		    (unsigned char *)share, type, (unsigned char *)comment,
1497 		    access, path, password);
1498 	default:
1499 		m_freem(str_mb.chain);
1500 		return (SDRC_NOT_IMPLEMENTED);
1501 	}
1502 
1503 	(void) smb_encode_mbc(&xa->rep_param_mb, "www", 0,
1504 	    -MBC_LENGTH(&xa->rep_data_mb),
1505 	    MBC_LENGTH(&xa->rep_data_mb) + MBC_LENGTH(&str_mb));
1506 	(void) smb_encode_mbc(&xa->rep_data_mb, "C", &str_mb);
1507 	m_freem(str_mb.chain);
1508 	return (SDRC_SUCCESS);
1509 }
1510 
1511 int
1512 smb_trans_net_workstation_get_info(struct smb_request *sr, struct smb_xa *xa)
1513 {
1514 	uint16_t		opcode, level, max_bytes;
1515 	unsigned char		*req_fmt;
1516 	unsigned char		*rep_fmt;
1517 	struct mbuf_chain	str_mb;
1518 	char *domain;
1519 	char *hostname;
1520 
1521 	if ((smb_decode_mbc(&xa->req_param_mb, "%wss(lev)w(size)w", sr,
1522 	    &opcode, &req_fmt, &rep_fmt, &level, &max_bytes) != 0) ||
1523 	    (level != 10)) {
1524 		(void) smb_encode_mbc(&xa->rep_param_mb, "wwww",
1525 		    NERR_BadTransactConfig, 0, 0, 0);
1526 		return (SDRC_SUCCESS);
1527 	}
1528 
1529 	domain = sr->sr_cfg->skc_resource_domain;
1530 	hostname = sr->sr_cfg->skc_hostname;
1531 
1532 	MBC_INIT(&str_mb, max_bytes);
1533 
1534 	(void) smb_encode_mbc(&str_mb, "."); /* Prevent NULL pointers */
1535 
1536 	(void) smb_encode_mbc(&xa->rep_data_mb, "l", MBC_LENGTH(&str_mb));
1537 	(void) smb_encode_mbc(&str_mb, "s", hostname);
1538 	(void) smb_encode_mbc(&xa->rep_data_mb, "l", MBC_LENGTH(&str_mb));
1539 	(void) smb_encode_mbc(&str_mb, "s", "nobody");
1540 	(void) smb_encode_mbc(&xa->rep_data_mb, "l", MBC_LENGTH(&str_mb));
1541 	(void) smb_encode_mbc(&str_mb, "s", domain);
1542 	(void) smb_encode_mbc(&xa->rep_data_mb, "bbl",
1543 	    SMB_VERSION_MAJOR, SMB_VERSION_MINOR, MBC_LENGTH(&str_mb));
1544 	(void) smb_encode_mbc(&str_mb, "s", domain);
1545 	(void) smb_encode_mbc(&xa->rep_data_mb, "l", MBC_LENGTH(&str_mb));
1546 	(void) smb_encode_mbc(&str_mb, "s", domain);
1547 
1548 	(void) smb_encode_mbc(&xa->rep_param_mb, "www", 0,
1549 	    -MBC_LENGTH(&xa->rep_data_mb),
1550 	    MBC_LENGTH(&xa->rep_data_mb) + MBC_LENGTH(&str_mb));
1551 	(void) smb_encode_mbc(&xa->rep_data_mb, "C", &str_mb);
1552 	m_freem(str_mb.chain);
1553 	return (SDRC_SUCCESS);
1554 }
1555 
1556 int
1557 smb_trans_net_user_get_info(struct smb_request *sr, struct smb_xa *xa)
1558 {
1559 	uint16_t		opcode, level, max_bytes;
1560 	unsigned char		*req_fmt;
1561 	unsigned char		*rep_fmt;
1562 	unsigned char		*user;
1563 	int rc;
1564 
1565 	rc = smb_decode_mbc(&xa->req_param_mb, "%wssww", sr,
1566 	    &opcode,
1567 	    &req_fmt,
1568 	    &rep_fmt,
1569 	    &user,
1570 	    &level,
1571 	    &max_bytes);
1572 
1573 	if (rc != 0)
1574 		return (SDRC_NOT_IMPLEMENTED);
1575 
1576 	(void) smb_encode_mbc(&xa->rep_param_mb, "www",
1577 	    NERR_UserNotFound, 0, 0);
1578 	return (SDRC_SUCCESS);
1579 }
1580 
1581 smb_sdrc_t
1582 smb_trans_server_get_info(struct smb_request *sr, struct smb_xa *xa)
1583 {
1584 	uint16_t		opcode, level, buf_size;
1585 	char			*req_fmt;
1586 	char			*rep_fmt;
1587 	char			server_name[16];
1588 	struct mbuf_chain	str_mb;
1589 	char *hostname;
1590 	char *comment;
1591 
1592 	if (smb_decode_mbc(&xa->req_param_mb, "%wssww", sr,
1593 	    &opcode, &req_fmt, &rep_fmt, &level, &buf_size) != 0) {
1594 		return (SDRC_ERROR);
1595 	}
1596 
1597 	comment = sr->sr_cfg->skc_system_comment;
1598 	hostname = sr->sr_cfg->skc_hostname;
1599 
1600 	MBC_INIT(&str_mb, buf_size);
1601 
1602 	bzero(server_name, sizeof (server_name));
1603 	(void) strncpy(server_name, hostname, sizeof (server_name));
1604 
1605 	switch (level) {
1606 	case 0:
1607 		(void) smb_encode_mbc(&xa->rep_data_mb, "16c", server_name);
1608 		break;
1609 	case 1:
1610 		(void) smb_encode_mbc(&str_mb, "."); /* Prevent NULL pointers */
1611 		(void) smb_encode_mbc(&xa->rep_data_mb, "16cbbll", server_name,
1612 		    SMB_VERSION_MAJOR, SMB_VERSION_MINOR,
1613 		    MY_SERVER_TYPE, MBC_LENGTH(&str_mb));
1614 		(void) smb_encode_mbc(&str_mb, "s", comment);
1615 		break;
1616 	case 2:
1617 		/* B16BBDzDDDWWzWWWWWWWB21BzWWWWWWWWWWWWWWWWWWWWWWz */
1618 		(void) smb_encode_mbc(&str_mb, "."); /* Prevent NULL pointers */
1619 					/*  B16BBDz */
1620 		(void) smb_encode_mbc(&xa->rep_data_mb, "16cbbll", server_name,
1621 		    SMB_VERSION_MAJOR,
1622 		    SMB_VERSION_MINOR, MY_SERVER_TYPE, MBC_LENGTH(&str_mb));
1623 		(void) smb_encode_mbc(&str_mb, "s", comment);
1624 		(void) smb_encode_mbc(&xa->rep_data_mb, "lllwwl",
1625 		    (uint32_t)1,
1626 		    (uint32_t)2,
1627 		    (uint32_t)3,
1628 		    (uint16_t)4,
1629 		    (uint16_t)5,
1630 		    MBC_LENGTH(&str_mb));
1631 		(void) smb_encode_mbc(&str_mb, "s", "str1");
1632 		(void) smb_encode_mbc(&xa->rep_data_mb, "wwwwwww21cbl",
1633 		    (uint16_t)6,
1634 		    (uint16_t)7,
1635 		    (uint16_t)8,
1636 		    (uint16_t)9,
1637 		    (uint16_t)10,
1638 		    (uint16_t)11,
1639 		    (uint16_t)12,
1640 		    "21 byte comment       ",
1641 		    (unsigned char)13,
1642 		    MBC_LENGTH(&str_mb));
1643 		(void) smb_encode_mbc(&str_mb, "s", "str2");
1644 		(void) smb_encode_mbc(&xa->rep_data_mb,
1645 		    "wwwwwwwwwwwwwwwwwwwwwwl",
1646 		    (uint16_t)14,
1647 		    (uint16_t)15,
1648 		    (uint16_t)16,
1649 		    (uint16_t)17,
1650 		    (uint16_t)18,
1651 		    (uint16_t)19,
1652 		    (uint16_t)20,
1653 		    (uint16_t)21,
1654 		    (uint16_t)22,
1655 		    (uint16_t)23,
1656 		    (uint16_t)24,
1657 		    (uint16_t)25,
1658 		    (uint16_t)26,
1659 		    (uint16_t)27,
1660 		    (uint16_t)28,
1661 		    (uint16_t)29,
1662 		    (uint16_t)20,
1663 		    (uint16_t)31,
1664 		    (uint16_t)32,
1665 		    (uint16_t)33,
1666 		    (uint16_t)34,
1667 		    (uint16_t)35,
1668 		    MBC_LENGTH(&str_mb));
1669 		(void) smb_encode_mbc(&str_mb, "s", "str3");
1670 		break;
1671 	default:
1672 		m_freem(str_mb.chain);
1673 		return (SDRC_NOT_IMPLEMENTED);
1674 	}
1675 
1676 	(void) smb_encode_mbc(&xa->rep_param_mb, "www", 0,
1677 	    -MBC_LENGTH(&xa->rep_data_mb),
1678 	    (MBC_LENGTH(&xa->rep_data_mb)) +
1679 	    (MBC_LENGTH(&str_mb)));
1680 	(void) smb_encode_mbc(&xa->rep_data_mb, "C", &str_mb);
1681 	m_freem(str_mb.chain);
1682 	return (SDRC_SUCCESS);
1683 }
1684 
1685 /*
1686  * 6.4 The NetServerEnum2 RAP Service
1687  *
1688  * The NetServerEnum2 RAP service lists all computers of the specified type
1689  * or types that are visible in the specified domains. It may also
1690  * enumerate domains.
1691  *
1692  * The following definition uses the notation and terminology defined in
1693  * the CIFS Remote Administration Protocol specification, which is required
1694  * in order to make it well-defined. The definition is:
1695  *
1696  *     uint16_t NetServerEnum2 (
1697  *         uint16_t  sLevel,
1698  *         RCVBUF          pbBuffer,
1699  *         RCVBUFLEN       cbBuffer,
1700  *         ENTCOUNT        pcEntriesRead,
1701  *         uint16_t  *pcTotalAvail,
1702  *         uint32_t   fServerType,
1703  *         char            *pszDomain,
1704  *     );
1705  *
1706  * where:
1707  *
1708  *    sLevel specifies the level of detail (0 or 1) requested.
1709  *
1710  *    pbBuffer points to the buffer to receive the returned data. If the
1711  *    function is successful, the buffer contains a sequence of
1712  *    server_info_x structures, where x is 0 or 1, depending on the
1713  *    level of detail requested.
1714  *
1715  *    cbBuffer specifies the size, in bytes, of the buffer pointed to by
1716  *    the pbBuffer parameter.
1717  *
1718  *    pcEntriesRead points to a 16 bit variable that receives a count of
1719  *    the number of servers enumerated in the buffer. This count is
1720  *    valid only if NetServerEnum2 returns the NERR_Success or
1721  *    ERROR_MORE_DATA values.
1722  *
1723  *    pcTotal Avail points to a 16 bit variable that receives a count of
1724  *    the total number of available entries. This count is valid only if
1725  *    NetServerEnum2 returns the NERR_Success or ERROR_MORE_DATA values.
1726  *
1727  *     fServerType specifies the type or types of computers to enumerate.
1728  *     Computers that match at least one of the specified types are
1729  *     returned in the buffer. Possible values are defined in the request
1730  *     parameters section.
1731  *
1732  *    pszDomain points to a null-terminated string that contains the
1733  *    name of the workgroup in which to enumerate computers of the
1734  *    specified type or types. If the pszDomain parameter is a null
1735  *    string or a null pointer, servers are enumerated for the current
1736  *    domain of the computer.
1737  *
1738  * 6.4.1 Transaction Request Parameters section
1739  *
1740  * The Transaction request parameters section in this instance contains:
1741  * . The 16 bit function number for NetServerEnum2 which is 104.
1742  * . The parameter descriptor string which is "WrLehDz".
1743  * . The data descriptor string for the (returned) data which is "B16" for
1744  *   level detail 0 or "B16BBDz" for level detail 1.
1745  * . The actual parameters as described by the parameter descriptor
1746  *   string.
1747  *
1748  * The parameters are:
1749  * . A 16 bit integer with a value of 0 or 1 (corresponding to the "W" in
1750  *   the parameter descriptor string. This represents the level of detail
1751  *   the server is expected to return
1752  * . A 16 bit integer that contains the size of the receive buffer.
1753  * . A 32 bit integer that represents the type of servers the function
1754  *   should enumerate. The possible values may be any of the following or
1755  *   a combination of the following:
1756  *
1757  * SV_TYPE_WORKSTATION        0x00000001 All workstations
1758  * SV_TYPE_SERVER             0x00000002 All servers
1759  * SV_TYPE_SQLSERVER          0x00000004 Any server running with SQL
1760  *                                       server
1761  * SV_TYPE_DOMAIN_CTRL        0x00000008 Primary domain controller
1762  * SV_TYPE_DOMAIN_BAKCTRL     0x00000010 Backup domain controller
1763  * SV_TYPE_TIME_SOURCE        0x00000020 Server running the timesource
1764  *                                       service
1765  * SV_TYPE_AFP                0x00000040 Apple File Protocol servers
1766  * SV_TYPE_NOVELL             0x00000080 Novell servers
1767  * SV_TYPE_DOMAIN_MEMBER      0x00000100 Domain Member
1768  * SV_TYPE_PRINTQ_SERVER      0x00000200 Server sharing print queue
1769  * SV_TYPE_DIALIN_SERVER      0x00000400 Server running dialin service.
1770  * SV_TYPE_XENIX_SERVER       0x00000800 Xenix server
1771  * SV_TYPE_NT                 0x00001000 NT server
1772  * SV_TYPE_WFW                0x00002000 Server running Windows for
1773  *                                       Workgroups
1774  * SV_TYPE_SERVER_NT          0x00008000 Windows NT non DC server
1775  * SV_TYPE_POTENTIAL_BROWSER  0x00010000 Server that can run the browser
1776  *                                       service
1777  * SV_TYPE_BACKUP_BROWSER     0x00020000 Backup browser server
1778  * SV_TYPE_MASTER_BROWSER     0x00040000 Master browser server
1779  * SV_TYPE_DOMAIN_MASTER      0x00080000 Domain Master Browser server
1780  * SV_TYPE_LOCAL_LIST_ONLY    0x40000000 Enumerate only entries marked
1781  *                                       "local"
1782  * SV_TYPE_DOMAIN_ENUM        0x80000000 Enumerate Domains. The pszDomain
1783  *                                       parameter must be NULL.
1784  *
1785  * . A null terminated ASCII string representing the pszDomain parameter
1786  *   described above
1787  *
1788  * 6.4.2 Transaction Request Data section
1789  *
1790  * There is no data or auxiliary data to send as part of the request.
1791  *
1792  * 6.4.3 Transaction Response Parameters section
1793  *
1794  * The transaction response parameters section consists of:
1795  * . A 16 bit word indicating the return status. The possible values are:
1796  *
1797  * Code                   Value  Description
1798  * NERR_Success           0      No errors encountered
1799  * ERROR_MORE_DATA        234    Additional data is available
1800  * NERR_ServerNotStarted  2114   The RAP service on the remote computer
1801  *                               is not running
1802  * NERR_BadTransactConfig 2141   The server is not configured for
1803  *                               transactions, IPC$ is not shared
1804  *
1805  * . A 16 bit "converter" word.
1806  * . A 16 bit number representing the number of entries returned.
1807  * . A 16 bit number representing the total number of available entries.
1808  *   If the supplied buffer is large enough, this will equal the number of
1809  *   entries returned.
1810  *
1811  * 6.4.4 Transaction Response Data section
1812  *
1813  * The return data section consists of a number of SERVER_INFO_1 structures.
1814  * The number of such structures present is determined by the third entry
1815  * (described above) in the return parameters section.
1816  *
1817  * At level detail 0, the Transaction response data section contains a
1818  * number of SERVER_INFO_0 data structure. The number of such structures is
1819  * equal to the 16 bit number returned by the server in the third parameter
1820  * in the Transaction response parameter section. The SERVER_INFO_0 data
1821  * structure is defined as:
1822  *
1823  *     struct SERVER_INFO_0 {
1824  *         char        sv0_name[16];
1825  *     };
1826  *
1827  *  where:
1828  *
1829  *    sv0_name is a null-terminated string that specifies the name of a
1830  *    computer or domain .
1831  *
1832  * At level detail 1, the Transaction response data section contains a
1833  * number of SERVER_INFO_1 data structure. The number of such structures is
1834  * equal to the 16 bit number returned by the server in the third parameter
1835  * in the Transaction response parameter section. The SERVER_INFO_1 data
1836  * structure is defined as:
1837  *
1838  *     struct SERVER_INFO_1 {
1839  *         char            sv1_name[16];
1840  *         char            sv1_version_major;
1841  *         char            sv1_version_minor;
1842  *         uint32_t   sv1_type;
1843  *         char        *sv1_comment_or_master_browser;
1844  *     };
1845  *
1846  *    sv1_name contains a null-terminated string that specifies the name
1847  *    of a computer, or a domain name if SV_TYPE_DOMAIN_ENUM is set in
1848  *    sv1_type.
1849  *
1850  *    sv1_version_major whatever was specified in the HostAnnouncement
1851  *    or DomainAnnouncement frame with which the entry was registered.
1852  *
1853  *    sv1_version_minor whatever was specified in the HostAnnouncement
1854  *    or DomainAnnouncement frame with which the entry was registered.
1855  *
1856  *    sv1_type specifies the type of software the computer is running.
1857  *    The member can be one or a combination of the values defined above
1858  *    in the Transaction request parameters section for fServerType.
1859  *
1860  *
1861  *    sv1_comment_or_master_browser points to a null-terminated string. If
1862  *    the sv1_type indicates that the entry is for a domain, this
1863  *    specifies the name of server running the domain master browser;
1864  *    otherwise, it specifies a comment describing the server. The comment
1865  *    can be a null string or the pointer may be a null pointer.
1866  *
1867  *    In case there are multiple SERVER_INFO_1 data structures to
1868  *    return, the server may put all these fixed length structures in
1869  *    the return buffer, leave some space and then put all the variable
1870  *    length data (the actual value of the sv1_comment strings) at the
1871  *    end of the buffer.
1872  *
1873  * There is no auxiliary data to receive.
1874  */
1875 
1876 int
1877 smb_trans_net_server_enum2(struct smb_request *sr, struct smb_xa *xa)
1878 {
1879 	uint16_t opcode, level, max_bytes;
1880 	uint32_t server_type;
1881 	unsigned char *domain;
1882 	struct mbuf_chain str_mb;
1883 	char *hostname, *s;
1884 	smb_kmod_cfg_t *si;
1885 
1886 	if (smb_decode_mbc(&xa->req_param_mb,
1887 	    "%w s(request format) s(reply format) wwls", sr, &opcode, &s, &s,
1888 	    &level, &max_bytes, &server_type, &domain) != 0)
1889 		return (SDRC_NOT_IMPLEMENTED);
1890 
1891 	si = sr->sr_cfg;
1892 
1893 	if (utf8_strcasecmp(si->skc_resource_domain, (char *)domain) != 0) {
1894 		(void) smb_encode_mbc(&xa->rep_param_mb, "wwww", 0, 0, 0, 0);
1895 		return (SDRC_SUCCESS);
1896 	}
1897 
1898 	if ((server_type & MY_SERVER_TYPE) == 0) {
1899 		(void) smb_encode_mbc(&xa->rep_param_mb, "wwww", 0, 0, 0, 0);
1900 		return (SDRC_SUCCESS);
1901 	}
1902 
1903 	MBC_INIT(&str_mb, max_bytes);
1904 
1905 	hostname = si->skc_hostname;
1906 
1907 	(void) smb_encode_mbc(&xa->rep_data_mb, "16c", hostname);
1908 	if (level == 1) {
1909 		(void) smb_encode_mbc(&xa->rep_data_mb, "bbll",
1910 		    SMB_VERSION_MAJOR, SMB_VERSION_MINOR,
1911 		    MY_SERVER_TYPE, MBC_LENGTH(&str_mb));
1912 		(void) smb_encode_mbc(&str_mb, "s", si->skc_system_comment);
1913 	}
1914 
1915 	(void) smb_encode_mbc(&xa->rep_param_mb, "wwww", 0,
1916 	    -MBC_LENGTH(&xa->rep_data_mb), 1, 1);
1917 	(void) smb_encode_mbc(&xa->rep_data_mb, "m", str_mb.chain);
1918 	return (SDRC_SUCCESS);
1919 }
1920 
1921 /*
1922  * is_supported_pipe
1923  *
1924  * Currently, just return 0 if the pipe is \\PIPE\repl otherwise
1925  * return 1.
1926  */
1927 int
1928 is_supported_pipe(char *pname)
1929 {
1930 	if (utf8_strcasecmp(pname, PIPE_REPL) == 0)
1931 		return (0);
1932 
1933 	return (1);
1934 }
1935 
1936 static smb_sdrc_t
1937 smb_trans_dispatch(struct smb_request *sr, struct smb_xa *xa)
1938 {
1939 	int		rc, pos;
1940 	int		total_bytes, n_setup, n_param, n_data;
1941 	int		param_off, param_pad, data_off, data_pad;
1942 	uint16_t	opcode;
1943 	uint16_t	devstate;
1944 	char		*req_fmt;
1945 	char		*rep_fmt;
1946 	struct vardata_block vdb;
1947 
1948 	n_setup = (xa->smb_msrcnt < 200) ? xa->smb_msrcnt : 200;
1949 	n_setup++;
1950 	n_setup = n_setup & ~0x0001;
1951 	n_param = (xa->smb_mprcnt < smb_maxbufsize)
1952 	    ? xa->smb_mprcnt : smb_maxbufsize;
1953 	n_param++;
1954 	n_param = n_param & ~0x0001;
1955 	rc = smb_maxbufsize - (SMBHEADERSIZE + 28 + n_setup + n_param);
1956 	n_data =  (xa->smb_mdrcnt < rc) ? xa->smb_mdrcnt : rc;
1957 	MBC_INIT(&xa->rep_setup_mb, n_setup * 2);
1958 	MBC_INIT(&xa->rep_param_mb, n_param);
1959 	MBC_INIT(&xa->rep_data_mb, n_data);
1960 
1961 	if (xa->smb_suwcnt > 0 && STYPE_ISIPC(sr->tid_tree->t_res_type)) {
1962 		rc = smb_decode_mbc(&xa->req_setup_mb, "ww", &opcode,
1963 		    &sr->smb_fid);
1964 		if (rc != 0)
1965 			goto trans_err_not_supported;
1966 		switch (opcode) {
1967 		case TRANS_SET_NMPIPE_STATE:
1968 			if ((rc = smb_decode_mbc(&xa->req_param_mb, "w",
1969 			    &devstate)) != 0)
1970 				goto trans_err_not_supported;
1971 
1972 			rc = SDRC_SUCCESS;
1973 			break;
1974 
1975 		case TRANS_TRANSACT_NMPIPE:
1976 			sr->fid_ofile = smb_ofile_lookup_by_fid(sr->tid_tree,
1977 			    sr->smb_fid);
1978 			if (sr->fid_ofile == NULL) {
1979 				smbsr_error(sr, NT_STATUS_INVALID_HANDLE,
1980 				    ERRDOS, ERRbadfid);
1981 				return (SDRC_ERROR);
1982 			}
1983 
1984 			rc = smb_decode_mbc(&xa->req_data_mb, "#B",
1985 			    xa->smb_tdscnt, &vdb);
1986 			if (rc != 0)
1987 				goto trans_err_not_supported;
1988 
1989 			rc = smb_rpc_transact(sr, &vdb.uio);
1990 			break;
1991 
1992 		case TRANS_WAIT_NMPIPE:
1993 			if (is_supported_pipe(xa->xa_smb_trans_name) == 0) {
1994 				smbsr_error(sr, 0, ERRDOS, ERRbadfile);
1995 				return (SDRC_ERROR);
1996 			}
1997 			rc = SDRC_SUCCESS;
1998 			break;
1999 
2000 		default:
2001 			goto trans_err_not_supported;
2002 		}
2003 	} else {
2004 		if ((utf8_strcasecmp(xa->xa_smb_trans_name,
2005 		    PIPE_LANMAN) != 0) &&
2006 		    (utf8_strcasecmp(
2007 		    xa->xa_smb_trans_name, MAILSLOT_LANMAN) != 0) &&
2008 		    (utf8_strcasecmp(
2009 		    xa->xa_smb_trans_name, MAILSLOT_BROWSE) != 0) &&
2010 		    (utf8_strcasecmp(
2011 		    xa->xa_smb_trans_name, MAILSLOT_MSBROWSE) != 0))
2012 			goto trans_err_not_supported;
2013 
2014 		if ((rc = smb_decode_mbc(&xa->req_param_mb, "%wss\b", sr,
2015 		    &opcode, &req_fmt, &rep_fmt)) != 0)
2016 			goto trans_err_not_supported;
2017 
2018 		/* for now, only respond to the */
2019 		switch (opcode) {
2020 		case API_WshareEnum:
2021 			rc = smb_trans_net_share_enum(sr, xa);
2022 			break;
2023 
2024 		case API_WshareGetInfo:
2025 			rc = smb_trans_net_share_get_info(sr, xa);
2026 			break;
2027 
2028 		case API_WserverGetInfo:
2029 			rc = smb_trans_server_get_info(sr, xa);
2030 			break;
2031 
2032 		case API_WUserGetInfo:
2033 			rc = smb_trans_net_user_get_info(sr, xa);
2034 			break;
2035 
2036 		case API_WWkstaGetInfo:
2037 			rc = smb_trans_net_workstation_get_info(sr, xa);
2038 			break;
2039 
2040 		case API_NetServerEnum2:
2041 			rc = smb_trans_net_server_enum2(sr, xa);
2042 			break;
2043 
2044 		default:
2045 			goto trans_err_not_supported;
2046 		}
2047 	}
2048 
2049 	switch (rc) {
2050 	case SDRC_SUCCESS:
2051 		break;
2052 
2053 	case SDRC_DROP_VC:
2054 	case SDRC_NO_REPLY:
2055 	case SDRC_ERROR:
2056 		return (rc);
2057 
2058 	case SDRC_NOT_IMPLEMENTED:
2059 		goto trans_err_not_supported;
2060 
2061 	default:
2062 		break;
2063 	}
2064 
2065 	n_setup = MBC_LENGTH(&xa->rep_setup_mb);
2066 	n_param = MBC_LENGTH(&xa->rep_param_mb);
2067 	n_data  = MBC_LENGTH(&xa->rep_data_mb);
2068 
2069 	if (xa->smb_msrcnt < n_setup ||
2070 	    xa->smb_mprcnt < n_param ||
2071 	    xa->smb_mdrcnt < n_data) {
2072 		goto trans_err_too_small;
2073 	}
2074 
2075 	/* neato, blast it over there */
2076 
2077 	n_setup = (n_setup + 1) / 2;		/* Convert to setup words */
2078 	param_pad = 1;				/* always one */
2079 	param_off = param_pad + 32 + 21 + (n_setup << 1) + 2;
2080 	data_pad = (param_off + n_param) & 1;	/* Pad to short */
2081 	/* Param off from hdr start */
2082 	data_off = param_off + n_param + data_pad;
2083 	total_bytes = param_pad + n_param + data_pad + n_data;
2084 
2085 	rc = smbsr_encode_result(sr, 10+n_setup, total_bytes,
2086 	    "b ww 2. www www b . C w #. C #. C",
2087 	    10 + n_setup,		/* wct */
2088 	    n_param,			/* Total Parameter Bytes */
2089 	    n_data,			/* Total Data Bytes */
2090 	    n_param,			/* Total Parameter Bytes this buffer */
2091 	    param_off,			/* Param offset from header start */
2092 	    0,				/* Param displacement */
2093 	    n_data,			/* Total Data Bytes this buffer */
2094 	    data_off,			/* Data offset from header start */
2095 	    0,				/* Data displacement */
2096 	    n_setup,			/* suwcnt */
2097 	    &xa->rep_setup_mb, /* setup[] */
2098 	    total_bytes,		/* Total data bytes */
2099 	    param_pad,
2100 	    &xa->rep_param_mb,
2101 	    data_pad,
2102 	    &xa->rep_data_mb);
2103 	return ((rc == 0) ? SDRC_SUCCESS : SDRC_ERROR);
2104 
2105 trans_err_too_small:
2106 	rc = NERR_BufTooSmall;
2107 	goto trans_err;
2108 
2109 trans_err_not_supported:
2110 	rc = ERROR_NOT_SUPPORTED;
2111 	goto trans_err;
2112 
2113 trans_err:
2114 	pos = MBC_LENGTH(&sr->reply) + 23;
2115 	rc = smbsr_encode_result(sr, 10, 4, "b ww 2. www www b . w ww",
2116 	    10,		/* wct */
2117 	    4, 0,	/* tpscnt tdscnt */
2118 	    4, pos, 0,	/* pscnt psoff psdisp */
2119 	    0, 0, 0,	/* dscnt dsoff dsdisp */
2120 	    0,		/* suwcnt */
2121 	    4,		/* bcc */
2122 	    rc,
2123 	    0);		/* converter word? */
2124 	return ((rc == 0) ? SDRC_SUCCESS : SDRC_ERROR);
2125 }
2126 
2127 static smb_sdrc_t
2128 smb_trans2_dispatch(struct smb_request *sr, struct smb_xa *xa)
2129 {
2130 	int		rc, pos;
2131 	int		total_bytes, n_setup, n_param, n_data;
2132 	int		param_off, param_pad, data_off, data_pad;
2133 	uint16_t	opcode;
2134 	uint16_t  nt_unknown_secret = 0x0100;
2135 	char *fmt;
2136 
2137 	n_setup = (xa->smb_msrcnt < 200) ? xa->smb_msrcnt : 200;
2138 	n_setup++;
2139 	n_setup = n_setup & ~0x0001;
2140 	n_param = (xa->smb_mprcnt < smb_maxbufsize)
2141 	    ? xa->smb_mprcnt : smb_maxbufsize;
2142 	n_param++;
2143 	n_param = n_param & ~0x0001;
2144 	rc = smb_maxbufsize - (SMBHEADERSIZE + 28 + n_setup + n_param);
2145 	n_data =  (xa->smb_mdrcnt < rc) ? xa->smb_mdrcnt : rc;
2146 	MBC_INIT(&xa->rep_setup_mb, n_setup * 2);
2147 	MBC_INIT(&xa->rep_param_mb, n_param);
2148 	MBC_INIT(&xa->rep_data_mb, n_data);
2149 
2150 	if (smb_decode_mbc(&xa->req_setup_mb, "w", &opcode) != 0)
2151 		goto trans_err_not_supported;
2152 
2153 	/*
2154 	 * Save this for /proc to read later.
2155 	 */
2156 	xa->smb_func = opcode;
2157 
2158 	/* for now, only respond to the */
2159 	switch (opcode) {
2160 	case TRANS2_CREATE_DIRECTORY:
2161 		rc = smb_com_trans2_create_directory(sr, xa);
2162 		break;
2163 
2164 	case TRANS2_FIND_FIRST2:
2165 		/*
2166 		 * Should have enough room to send the response
2167 		 * data back to client.
2168 		 */
2169 		if (n_data == 0) {
2170 			smbsr_error(sr, NT_STATUS_INFO_LENGTH_MISMATCH,
2171 			    ERRDOS, ERROR_BAD_LENGTH);
2172 			return (SDRC_ERROR);
2173 		}
2174 		rc = smb_com_trans2_find_first2(sr, xa);
2175 		break;
2176 
2177 	case TRANS2_FIND_NEXT2:
2178 		/*
2179 		 * Should have enough room to send the response
2180 		 * data back to client.
2181 		 */
2182 		if (n_data == 0) {
2183 			smbsr_error(sr, NT_STATUS_INFO_LENGTH_MISMATCH,
2184 			    ERRDOS, ERROR_BAD_LENGTH);
2185 			return (SDRC_ERROR);
2186 		}
2187 		rc = smb_com_trans2_find_next2(sr, xa);
2188 		break;
2189 
2190 	case TRANS2_QUERY_FS_INFORMATION:
2191 		/*
2192 		 * Should have enough room to send the response
2193 		 * data back to client.
2194 		 */
2195 		if (n_data == 0) {
2196 			smbsr_error(sr, NT_STATUS_INFO_LENGTH_MISMATCH,
2197 			    ERRDOS, ERROR_BAD_LENGTH);
2198 			return (SDRC_ERROR);
2199 		}
2200 		rc = smb_com_trans2_query_fs_information(sr, xa);
2201 		break;
2202 
2203 	case TRANS2_QUERY_PATH_INFORMATION:
2204 		/*
2205 		 * Should have enough room to send the response
2206 		 * data back to client.
2207 		 */
2208 		if (n_data == 0) {
2209 			smbsr_error(sr, NT_STATUS_INFO_LENGTH_MISMATCH,
2210 			    ERRDOS, ERROR_BAD_LENGTH);
2211 			return (SDRC_ERROR);
2212 		}
2213 		rc = smb_com_trans2_query_path_information(sr, xa);
2214 		break;
2215 
2216 	case TRANS2_QUERY_FILE_INFORMATION:
2217 		/*
2218 		 * Should have enough room to send the response
2219 		 * data back to client.
2220 		 */
2221 		if (n_data == 0) {
2222 			smbsr_error(sr, NT_STATUS_INFO_LENGTH_MISMATCH,
2223 			    ERRDOS, ERROR_BAD_LENGTH);
2224 			return (SDRC_ERROR);
2225 		}
2226 		rc = smb_com_trans2_query_file_information(sr, xa);
2227 		break;
2228 
2229 	case TRANS2_SET_PATH_INFORMATION:
2230 		rc = smb_com_trans2_set_path_information(sr, xa);
2231 		break;
2232 
2233 	case TRANS2_SET_FILE_INFORMATION:
2234 		rc = smb_com_trans2_set_file_information(sr, xa);
2235 		break;
2236 	default:
2237 		goto trans_err_not_supported;
2238 	}
2239 
2240 	switch (rc) {
2241 	case SDRC_SUCCESS:
2242 		break;
2243 
2244 	case SDRC_DROP_VC:
2245 	case SDRC_NO_REPLY:
2246 	case SDRC_ERROR:
2247 		return (rc);
2248 
2249 	case SDRC_NOT_IMPLEMENTED:
2250 		goto trans_err_not_supported;
2251 
2252 	default:
2253 		break;
2254 	}
2255 
2256 	n_setup = MBC_LENGTH(&xa->rep_setup_mb);
2257 	n_param = MBC_LENGTH(&xa->rep_param_mb);
2258 	n_data  = MBC_LENGTH(&xa->rep_data_mb);
2259 
2260 	if (xa->smb_msrcnt < n_setup ||
2261 	    xa->smb_mprcnt < n_param ||
2262 	    xa->smb_mdrcnt < n_data) {
2263 		goto trans_err_too_small;
2264 	}
2265 
2266 	/* neato, blast it over there */
2267 
2268 	n_setup = (n_setup + 1) / 2;		/* Conver to setup words */
2269 	param_pad = 1;				/* must be one */
2270 	param_off = param_pad + 32 + 21 + (n_setup << 1) + 2;
2271 
2272 	/*
2273 	 * Including the nt_unknown_secret value persuades netmon to
2274 	 * display the correct data format for QueryPathInfo and
2275 	 * QueryFileInfo.
2276 	 */
2277 	if (opcode == TRANS2_QUERY_FILE_INFORMATION ||
2278 	    opcode == TRANS2_QUERY_PATH_INFORMATION) {
2279 		data_pad = sizeof (uint16_t);
2280 		data_off = param_off + n_param + data_pad;
2281 		fmt = "b ww 2. www www b . C w #. C w C";
2282 		nt_unknown_secret = 0x0100;
2283 	}
2284 	else
2285 	{
2286 		data_pad = (param_off + n_param) & 1; /* Pad to short */
2287 		/* Param off from hdr start */
2288 		data_off = param_off + n_param + data_pad;
2289 		fmt = "b ww 2. www www b . C w #. C #. C";
2290 		/*LINTED E_ASSIGN_NARROW_CONV*/
2291 		nt_unknown_secret = data_pad;
2292 	}
2293 
2294 	total_bytes = param_pad + n_param + data_pad + n_data;
2295 
2296 	rc = smbsr_encode_result(sr, 10+n_setup, total_bytes,
2297 	    fmt,
2298 	    10 + n_setup,		/* wct */
2299 	    n_param,			/* Total Parameter Bytes */
2300 	    n_data /* + data_pad */,	/* Total Data Bytes */
2301 	    n_param,			/* Total Parameter Bytes this buffer */
2302 	    param_off,			/* Param offset from header start */
2303 	    0,				/* Param displacement */
2304 	    n_data /* + data_pad */,	/* Total Data Bytes this buffer */
2305 	    data_off,			/* Data offset from header start */
2306 	    0,				/* Data displacement */
2307 	    n_setup,			/* suwcnt */
2308 	    &xa->rep_setup_mb,		/* setup[] */
2309 	    total_bytes,		/* Total data bytes */
2310 	    param_pad,
2311 	    &xa->rep_param_mb,
2312 	    nt_unknown_secret,
2313 	    &xa->rep_data_mb);
2314 	return ((rc == 0) ? SDRC_SUCCESS : SDRC_ERROR);
2315 
2316 trans_err_too_small:
2317 	rc = NERR_BufTooSmall;
2318 	goto trans_err;
2319 
2320 trans_err_not_supported:
2321 	rc = ERROR_NOT_SUPPORTED;
2322 	goto trans_err;
2323 
2324 trans_err:
2325 	pos = MBC_LENGTH(&sr->reply) + 23;
2326 	rc = smbsr_encode_result(sr, 10, 4, "b ww 2. www www b . w ww",
2327 	    10,		/* wct */
2328 	    4, 0,	/* tpscnt tdscnt */
2329 	    4, pos, 0,	/* pscnt psoff psdisp */
2330 	    0, 0, 0,	/* dscnt dsoff dsdisp */
2331 	    0,		/* suwcnt */
2332 	    4,		/* bcc */
2333 	    rc,
2334 	    0);		/* converter word? */
2335 	return ((rc == 0) ? SDRC_SUCCESS : SDRC_ERROR);
2336 }
2337 
2338 smb_xa_t *
2339 smb_xa_create(
2340     smb_session_t	*session,
2341     smb_request_t	*sr,
2342     uint32_t		total_parameter_count,
2343     uint32_t		total_data_count,
2344     uint32_t		max_parameter_count,
2345     uint32_t		max_data_count,
2346     uint32_t		max_setup_count,
2347     uint32_t		setup_word_count)
2348 {
2349 	smb_xa_t	*xa, *nxa;
2350 	smb_llist_t	*xlist;
2351 
2352 	xa = MEM_ZALLOC("xa", sizeof (smb_xa_t));
2353 	xa->xa_refcnt = 1;
2354 	xa->smb_com = sr->smb_com;
2355 	xa->smb_flg = sr->smb_flg;
2356 	xa->smb_flg2 = sr->smb_flg2;
2357 	xa->smb_tid = sr->smb_tid;
2358 	xa->smb_pid = sr->smb_pid;
2359 	xa->smb_uid = sr->smb_uid;
2360 	xa->xa_smb_mid = sr->smb_mid;
2361 	xa->reply_seqnum = sr->reply_seqnum;
2362 	xa->smb_tpscnt = total_parameter_count;
2363 	xa->smb_tdscnt = total_data_count;
2364 	xa->smb_mprcnt = max_parameter_count;
2365 	xa->smb_mdrcnt = max_data_count;
2366 	xa->smb_msrcnt = max_setup_count;
2367 	xa->smb_suwcnt = setup_word_count;
2368 	xa->xa_session = session;
2369 	xa->xa_magic = SMB_XA_MAGIC;
2370 
2371 	/*
2372 	 * The new xa structure is checked against the current list to see
2373 	 * if it exists already.
2374 	 */
2375 	xlist = &session->s_xa_list;
2376 	smb_llist_enter(xlist, RW_WRITER);
2377 	nxa = smb_llist_head(xlist);
2378 	while (nxa) {
2379 		ASSERT(nxa->xa_magic == SMB_XA_MAGIC);
2380 		if (nxa->xa_smb_mid == xa->xa_smb_mid &&
2381 		    nxa->smb_pid == xa->smb_pid &&
2382 		    !SMB_XA_CLOSED(nxa) &&
2383 		    !(nxa->xa_flags & SMB_XA_FLAG_COMPLETE)) {
2384 			smb_llist_exit(xlist);
2385 			MEM_FREE("xa", xa);
2386 			return (NULL);
2387 		}
2388 		nxa = smb_llist_next(xlist, nxa);
2389 	}
2390 	smb_llist_insert_tail(xlist, xa);
2391 	smb_llist_exit(xlist);
2392 	return (xa);
2393 }
2394 
2395 void
2396 smb_xa_delete(smb_xa_t *xa)
2397 {
2398 	ASSERT(xa->xa_refcnt == 0);
2399 	ASSERT(SMB_XA_CLOSED(xa));
2400 
2401 	if (xa->xa_smb_trans_name)
2402 		MEM_FREE("smb", xa->xa_smb_trans_name);
2403 
2404 	if (xa->rep_setup_mb.chain != NULL)
2405 		m_freem(xa->rep_setup_mb.chain);
2406 	if (xa->rep_param_mb.chain != NULL)
2407 		m_freem(xa->rep_param_mb.chain);
2408 	if (xa->rep_data_mb.chain != NULL)
2409 		m_freem(xa->rep_data_mb.chain);
2410 
2411 	xa->xa_magic = (uint32_t)~SMB_XA_MAGIC;
2412 	MEM_FREE("xa", xa);
2413 }
2414 
2415 smb_xa_t *
2416 smb_xa_hold(smb_xa_t *xa)
2417 {
2418 	mutex_enter(&xa->xa_mutex);
2419 	xa->xa_refcnt++;
2420 	ASSERT(xa->xa_refcnt);
2421 	mutex_exit(&xa->xa_mutex);
2422 	return (xa);
2423 }
2424 
2425 void
2426 smb_xa_rele(smb_session_t *session, smb_xa_t *xa)
2427 {
2428 	mutex_enter(&xa->xa_mutex);
2429 	ASSERT(xa->xa_refcnt);
2430 	xa->xa_refcnt--;
2431 	if (SMB_XA_CLOSED(xa) && (xa->xa_refcnt == 0)) {
2432 		mutex_exit(&xa->xa_mutex);
2433 		smb_llist_enter(&session->s_xa_list, RW_WRITER);
2434 		smb_llist_remove(&session->s_xa_list, xa);
2435 		smb_llist_exit(&session->s_xa_list);
2436 		smb_xa_delete(xa);
2437 		return;
2438 	}
2439 	mutex_exit(&xa->xa_mutex);
2440 }
2441 
2442 int
2443 smb_xa_open(smb_xa_t *xa)
2444 {
2445 	int rc;
2446 
2447 	mutex_enter(&xa->xa_mutex);
2448 
2449 	ASSERT((xa->xa_flags & SMB_XA_FLAG_OPEN) == 0);
2450 
2451 	if ((xa->xa_flags & SMB_XA_FLAG_CLOSE) == 0) {
2452 		xa->xa_flags |= SMB_XA_FLAG_OPEN;
2453 		rc = 0;
2454 	} else {
2455 		rc = ERROR_INVALID_HANDLE;
2456 	}
2457 
2458 	mutex_exit(&xa->xa_mutex);
2459 
2460 	return (rc);
2461 }
2462 
2463 void
2464 smb_xa_close(smb_xa_t *xa)
2465 {
2466 	mutex_enter(&xa->xa_mutex);
2467 	xa->xa_flags |= SMB_XA_FLAG_CLOSE;
2468 	xa->xa_flags &= ~SMB_XA_FLAG_OPEN;
2469 
2470 	if (xa->xa_refcnt == 0) {
2471 		mutex_exit(&xa->xa_mutex);
2472 		smb_llist_enter(&xa->xa_session->s_xa_list, RW_WRITER);
2473 		smb_llist_remove(&xa->xa_session->s_xa_list, xa);
2474 		smb_llist_exit(&xa->xa_session->s_xa_list);
2475 		smb_xa_delete(xa);
2476 		return;
2477 	}
2478 
2479 	mutex_exit(&xa->xa_mutex);
2480 }
2481 
2482 int
2483 smb_xa_complete(smb_xa_t *xa)
2484 {
2485 	int rc;
2486 
2487 	mutex_enter(&xa->xa_mutex);
2488 	if (xa->xa_flags & (SMB_XA_FLAG_COMPLETE | SMB_XA_FLAG_CLOSE)) {
2489 		rc = 0;
2490 	} else {
2491 		rc = 1;
2492 		xa->xa_flags |= SMB_XA_FLAG_COMPLETE;
2493 	}
2494 	mutex_exit(&xa->xa_mutex);
2495 	return (rc);
2496 }
2497 
2498 smb_xa_t *
2499 smb_xa_find(
2500     smb_session_t	*session,
2501     uint16_t		pid,
2502     uint16_t		mid)
2503 {
2504 	smb_xa_t	*xa;
2505 	smb_llist_t	*xlist;
2506 
2507 	xlist = &session->s_xa_list;
2508 	smb_llist_enter(xlist, RW_READER);
2509 	xa = smb_llist_head(xlist);
2510 	while (xa) {
2511 		mutex_enter(&xa->xa_mutex);
2512 		if (xa->xa_smb_mid == mid &&
2513 		    xa->smb_pid == pid &&
2514 		    !SMB_XA_CLOSED(xa) &&
2515 		    !(xa->xa_flags & SMB_XA_FLAG_COMPLETE)) {
2516 			xa->xa_refcnt++;
2517 			ASSERT(xa->xa_refcnt);
2518 			mutex_exit(&xa->xa_mutex);
2519 			break;
2520 		}
2521 		mutex_exit(&xa->xa_mutex);
2522 		xa = smb_llist_next(xlist, xa);
2523 	}
2524 	smb_llist_exit(xlist);
2525 	return (xa);
2526 }
2527