xref: /illumos-gate/usr/src/uts/common/fs/smbsrv/smb_common_transact.c (revision e00bdde3c6d406f40f53f3025defadc22f7ec31a)
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 /*
23  * Copyright (c) 2007, 2010, Oracle and/or its affiliates. All rights reserved.
24  * Copyright 2018 Nexenta Systems, Inc.  All rights reserved.
25  * Copyright 2022 RackTop Systems, Inc.
26  */
27 
28 #include <smbsrv/smb_kproto.h>
29 #include <smbsrv/smb_fsops.h>
30 #include <smbsrv/smb_share.h>
31 #include <smbsrv/string.h>
32 #include <smbsrv/nmpipes.h>
33 #include <smbsrv/mailslot.h>
34 #include <smb/winioctl.h>
35 
36 /*
37  * count of bytes in server response packet
38  * except parameters and data. Note that setup
39  * word count is zero.
40  */
41 #define	RESP_HEADER_LEN		24
42 
43 /*
44  * We started by using common functions for transaction/transaction2
45  * and transaction_secondary/transaction2_secondary because they
46  * are respectively so similar. However, it turned out to be a bad
47  * idea because of quirky differences. Be sure if you modify one
48  * of these four functions to check and see if the modification should
49  * be applied to its peer.
50  */
51 
52 static int smb_trans_ready(smb_xa_t *);
53 static smb_sdrc_t smb_trans_dispatch(smb_request_t *, smb_xa_t *);
54 static smb_sdrc_t smb_trans2_dispatch(smb_request_t *, smb_xa_t *);
55 
56 smb_sdrc_t
57 smb_pre_transaction(smb_request_t *sr)
58 {
59 	DTRACE_SMB_START(op__Transaction, smb_request_t *, sr);
60 	return (SDRC_SUCCESS);
61 }
62 
63 void
64 smb_post_transaction(smb_request_t *sr)
65 {
66 	DTRACE_SMB_DONE(op__Transaction, smb_request_t *, sr);
67 }
68 
69 smb_sdrc_t
70 smb_com_transaction(smb_request_t *sr)
71 {
72 	int		rc;
73 	unsigned char	msrcnt, suwcnt;
74 	uint16_t	tpscnt, tdscnt, mprcnt, mdrcnt, flags;
75 	uint16_t	pscnt, psoff, dscnt, dsoff;
76 	uint32_t	timeo;
77 	struct smb_xa *xa;
78 	char *stn;
79 	int ready;
80 
81 	if (!STYPE_ISIPC(sr->tid_tree->t_res_type)) {
82 		smbsr_error(sr, 0, ERRDOS, ERRnoaccess);
83 		return (SDRC_ERROR);
84 	}
85 
86 	rc = smbsr_decode_vwv(sr, SMB_TRANSHDR_ED_FMT,
87 	    &tpscnt, &tdscnt, &mprcnt, &mdrcnt, &msrcnt, &flags,
88 	    &timeo, &pscnt, &psoff, &dscnt, &dsoff, &suwcnt);
89 
90 	if (rc != 0)
91 		return (SDRC_ERROR);
92 
93 	xa = smb_xa_create(sr->session, sr, tpscnt, tdscnt, mprcnt, mdrcnt,
94 	    msrcnt, suwcnt);
95 	if (xa == NULL) {
96 		smbsr_error(sr, 0, ERRSRV, ERRnoroom);
97 		return (SDRC_ERROR);
98 	}
99 
100 	/* Should be some alignment stuff here in SMB? */
101 	if (sr->smb_flg2 & SMB_FLAGS2_UNICODE) {
102 		rc = smbsr_decode_data(sr, "%.U", sr, &stn);
103 	} else {
104 		rc = smbsr_decode_data(sr, "%s", sr,  &stn);
105 	}
106 	if (rc != 0) {
107 		smb_xa_rele(sr->session, xa);
108 		return (SDRC_ERROR);
109 	}
110 
111 	xa->xa_pipe_name = smb_mem_strdup(stn);
112 	xa->smb_flags  = flags;
113 	xa->smb_timeout = timeo;
114 	xa->req_disp_param = pscnt;
115 	xa->req_disp_data  = dscnt;
116 
117 	if (smb_mbc_copy(&xa->req_setup_mb, &sr->smb_vwv,
118 	    sr->smb_vwv.chain_offset, suwcnt * 2)) {
119 		smb_xa_rele(sr->session, xa);
120 		smbsr_error(sr, 0, ERRDOS, ERRbadformat);
121 		return (SDRC_ERROR);
122 	}
123 	if (smb_mbc_copy(&xa->req_param_mb, &sr->command, psoff, pscnt)) {
124 		smb_xa_rele(sr->session, xa);
125 		smbsr_error(sr, 0, ERRDOS, ERRbadformat);
126 		return (SDRC_ERROR);
127 	}
128 	if (smb_mbc_copy(&xa->req_data_mb, &sr->command, dsoff, dscnt)) {
129 		smb_xa_rele(sr->session, xa);
130 		smbsr_error(sr, 0, ERRDOS, ERRbadformat);
131 		return (SDRC_ERROR);
132 	}
133 
134 	ready = smb_trans_ready(xa);
135 
136 	if (smb_xa_open(xa)) {
137 		smb_xa_rele(sr->session, xa);
138 		smbsr_error(sr, 0, ERRSRV, ERRsrverror);
139 		return (SDRC_ERROR);
140 	}
141 	sr->r_xa = xa;
142 
143 	if (!ready) {
144 		rc = smbsr_encode_empty_result(sr);
145 		return ((rc == 0) ? SDRC_SUCCESS : SDRC_ERROR);
146 	}
147 
148 	if (!smb_xa_complete(xa)) {
149 		smb_xa_close(xa);
150 		smbsr_error(sr, 0, ERRDOS, ERRbadformat);
151 		return (SDRC_ERROR);
152 	}
153 
154 	return (smb_trans_dispatch(sr, xa));
155 }
156 
157 smb_sdrc_t
158 smb_pre_transaction_secondary(smb_request_t *sr)
159 {
160 	DTRACE_SMB_START(op__TransactionSecondary, smb_request_t *, sr);
161 	return (SDRC_SUCCESS);
162 }
163 
164 void
165 smb_post_transaction_secondary(smb_request_t *sr)
166 {
167 	DTRACE_SMB_DONE(op__TransactionSecondary, smb_request_t *, sr);
168 }
169 
170 smb_sdrc_t
171 smb_com_transaction_secondary(smb_request_t *sr)
172 {
173 	uint16_t tpscnt, tdscnt, pscnt, psdisp;
174 	uint16_t dscnt, dsoff, dsdisp, psoff;
175 	smb_xa_t *xa;
176 	int rc;
177 
178 	if ((xa = smbsr_lookup_xa(sr)) == 0) {
179 		smbsr_error(sr, 0, ERRSRV, ERRsrverror);
180 		return (SDRC_ERROR);
181 	}
182 
183 	if (sr->session->signing.flags & SMB_SIGNING_ENABLED) {
184 		if (smb_sign_check_secondary(sr, xa->reply_seqnum) != 0) {
185 			smbsr_error(sr, NT_STATUS_ACCESS_DENIED,
186 			    ERRDOS, ERRnoaccess);
187 			return (SDRC_ERROR);
188 		}
189 	}
190 
191 	if (xa->smb_com != SMB_COM_TRANSACTION) {
192 		return (SDRC_DROP_VC);
193 	}
194 
195 	rc = smbsr_decode_vwv(sr, SMB_TRANSSHDR_ED_FMT, &tpscnt, &tdscnt,
196 	    &pscnt, &psoff, &psdisp, &dscnt, &dsoff, &dsdisp);
197 
198 	if (rc != 0)
199 		return (SDRC_ERROR);
200 
201 	mutex_enter(&xa->xa_mutex);
202 	if (xa->smb_tpscnt > tpscnt)
203 		xa->smb_tpscnt = tpscnt;
204 	if (xa->smb_tdscnt > tdscnt)
205 		xa->smb_tdscnt = tdscnt;
206 	xa->req_disp_param = psdisp + pscnt;
207 	xa->req_disp_data  = dsdisp + dscnt;
208 
209 	/*
210 	 * The words psdisp, dsdisp, tell us what displacement
211 	 * into the entire trans parameter and data buffers
212 	 * where we should put the params & data that are
213 	 * delivered by this request.  [MS-CIFS] says all the
214 	 * parameters and data SHOULD be sent sequentially, so
215 	 * so we can normally reassemble by simply appending.
216 	 * However, the components MAY come out of order, so
217 	 * check and set the current offset.  This is rare,
218 	 * and we might like to know when this happens, so
219 	 * fire some static dtrace probes when it does.
220 	 */
221 	if (xa->req_param_mb.chain_offset != psdisp) {
222 		DTRACE_PROBE2(trans_param_disp,
223 		    smb_xa_t *, xa, uint16_t, psdisp);
224 		xa->req_param_mb.chain_offset = psdisp;
225 	}
226 	if (xa->req_data_mb.chain_offset != dsdisp) {
227 		DTRACE_PROBE2(trans_data_disp,
228 		    smb_xa_t *, xa, uint16_t, dsdisp);
229 		xa->req_data_mb.chain_offset = dsdisp;
230 	}
231 
232 	if (smb_mbc_copy(&xa->req_param_mb, &sr->command, psoff, pscnt)) {
233 		mutex_exit(&xa->xa_mutex);
234 		smb_xa_close(xa);
235 		smbsr_error(sr, 0, ERRDOS, ERRbadformat);
236 		return (SDRC_ERROR);
237 	}
238 	if (smb_mbc_copy(&xa->req_data_mb, &sr->command, dsoff, dscnt)) {
239 		mutex_exit(&xa->xa_mutex);
240 		smb_xa_close(xa);
241 		smbsr_error(sr, 0, ERRDOS, ERRbadformat);
242 		return (SDRC_ERROR);
243 	}
244 	mutex_exit(&xa->xa_mutex);
245 
246 	if (!smb_trans_ready(xa))
247 		return (SDRC_NO_REPLY);
248 
249 	if (!smb_xa_complete(xa))
250 		return (SDRC_NO_REPLY);
251 
252 	return (smb_trans_dispatch(sr, xa));
253 }
254 
255 smb_sdrc_t
256 smb_pre_ioctl(smb_request_t *sr)
257 {
258 	DTRACE_SMB_START(op__Ioctl, smb_request_t *, sr);
259 	return (SDRC_SUCCESS);
260 }
261 
262 void
263 smb_post_ioctl(smb_request_t *sr)
264 {
265 	DTRACE_SMB_DONE(op__Ioctl, smb_request_t *, sr);
266 }
267 
268 smb_sdrc_t
269 smb_com_ioctl(smb_request_t *sr)
270 {
271 	uint16_t fid, category, function, tpscnt, tdscnt, mprcnt;
272 	uint16_t mdrcnt, pscnt, pdoff, dscnt, dsoff;
273 	uint32_t timeout;
274 	int rc;
275 
276 	rc = smbsr_decode_vwv(sr, "wwwwwwwl2.wwww", &fid, &category, &function,
277 	    &tpscnt, &tdscnt, &mprcnt, &mdrcnt, &timeout, &pscnt,
278 	    &pdoff, &dscnt, &dsoff);
279 
280 	if (rc != 0)
281 		return (SDRC_ERROR);
282 
283 	return (SDRC_NOT_IMPLEMENTED);
284 }
285 
286 smb_sdrc_t
287 smb_pre_transaction2(smb_request_t *sr)
288 {
289 	DTRACE_SMB_START(op__Transaction2, smb_request_t *, sr);
290 	return (SDRC_SUCCESS);
291 }
292 
293 void
294 smb_post_transaction2(smb_request_t *sr)
295 {
296 	DTRACE_SMB_DONE(op__Transaction2, smb_request_t *, sr);
297 }
298 
299 smb_sdrc_t
300 smb_com_transaction2(struct smb_request *sr)
301 {
302 	unsigned char	msrcnt, suwcnt;
303 	uint16_t	tpscnt, tdscnt, mprcnt, mdrcnt, flags;
304 	uint16_t	pscnt, psoff, dscnt, dsoff;
305 	uint32_t	timeo;
306 	smb_xa_t *xa;
307 	int ready;
308 	int rc;
309 
310 	rc = smbsr_decode_vwv(sr, SMB_TRANSHDR_ED_FMT, &tpscnt, &tdscnt,
311 	    &mprcnt, &mdrcnt, &msrcnt, &flags, &timeo, &pscnt, &psoff, &dscnt,
312 	    &dsoff, &suwcnt);
313 
314 	if (rc != 0)
315 		return (SDRC_ERROR);
316 
317 	xa = smb_xa_create(sr->session, sr, tpscnt, tdscnt, mprcnt, mdrcnt,
318 	    msrcnt, suwcnt);
319 	if (xa == 0) {
320 		smbsr_error(sr, 0, ERRSRV, ERRnoroom);
321 		return (SDRC_ERROR);
322 	}
323 
324 	xa->smb_flags  = flags;
325 	xa->smb_timeout = timeo;
326 	xa->req_disp_param = pscnt;
327 	xa->req_disp_data  = dscnt;
328 
329 	if (smb_mbc_copy(&xa->req_setup_mb, &sr->smb_vwv,
330 	    sr->smb_vwv.chain_offset, suwcnt*2)) {
331 		smb_xa_rele(sr->session, xa);
332 		smbsr_error(sr, 0, ERRDOS, ERRbadformat);
333 		return (SDRC_ERROR);
334 	}
335 	if (smb_mbc_copy(&xa->req_param_mb, &sr->command, psoff, pscnt)) {
336 		smb_xa_rele(sr->session, xa);
337 		smbsr_error(sr, 0, ERRDOS, ERRbadformat);
338 		return (SDRC_ERROR);
339 	}
340 	if (smb_mbc_copy(&xa->req_data_mb, &sr->command, dsoff, dscnt)) {
341 		smb_xa_rele(sr->session, xa);
342 		smbsr_error(sr, 0, ERRDOS, ERRbadformat);
343 		return (SDRC_ERROR);
344 	}
345 
346 	ready = smb_trans_ready(xa);
347 
348 	if (smb_xa_open(xa)) {
349 		smb_xa_rele(sr->session, xa);
350 		smbsr_error(sr, 0, ERRSRV, ERRsrverror);
351 		return (SDRC_ERROR);
352 	}
353 	sr->r_xa = xa;
354 
355 	if (!ready) {
356 		rc = smbsr_encode_empty_result(sr);
357 		return ((rc == 0) ? SDRC_SUCCESS : SDRC_ERROR);
358 	}
359 
360 	if (!smb_xa_complete(xa)) {
361 		smb_xa_close(xa);
362 		smbsr_error(sr, 0, ERRDOS, ERRbadformat);
363 		return (SDRC_ERROR);
364 	}
365 
366 	return (smb_trans2_dispatch(sr, xa));
367 }
368 
369 smb_sdrc_t
370 smb_pre_transaction2_secondary(smb_request_t *sr)
371 {
372 	DTRACE_SMB_START(op__Transaction2Secondary, smb_request_t *, sr);
373 	return (SDRC_SUCCESS);
374 }
375 
376 void
377 smb_post_transaction2_secondary(smb_request_t *sr)
378 {
379 	DTRACE_SMB_DONE(op__Transaction2Secondary, smb_request_t *, sr);
380 }
381 
382 smb_sdrc_t
383 smb_com_transaction2_secondary(smb_request_t *sr)
384 {
385 	uint16_t tpscnt, tdscnt, fid;
386 	uint16_t pscnt, psoff, psdisp, dscnt, dsoff, dsdisp;
387 	smb_xa_t *xa;
388 	int rc;
389 
390 	if ((xa = smbsr_lookup_xa(sr)) == 0) {
391 		smbsr_error(sr, 0, ERRSRV, ERRsrverror);
392 		return (SDRC_ERROR);
393 	}
394 
395 	if (sr->session->signing.flags & SMB_SIGNING_ENABLED) {
396 		if (smb_sign_check_secondary(sr, xa->reply_seqnum) != 0) {
397 			smbsr_error(sr, NT_STATUS_ACCESS_DENIED,
398 			    ERRDOS, ERRnoaccess);
399 			return (SDRC_ERROR);
400 		}
401 	}
402 
403 	if (xa->smb_com != SMB_COM_TRANSACTION2) {
404 		return (SDRC_DROP_VC);
405 	}
406 
407 	rc = smbsr_decode_vwv(sr, SMB_TRANS2SHDR_ED_FMT, &tpscnt, &tdscnt,
408 	    &pscnt, &psoff, &psdisp, &dscnt, &dsoff, &dsdisp, &fid);
409 
410 	if (rc != 0)
411 		return (SDRC_ERROR);
412 
413 	mutex_enter(&xa->xa_mutex);
414 	if (xa->smb_tpscnt > tpscnt)
415 		xa->smb_tpscnt = tpscnt;
416 	if (xa->smb_tdscnt > tdscnt)
417 		xa->smb_tdscnt = tdscnt;
418 	if (fid != 0xFFFF)
419 		xa->xa_smb_fid = fid;
420 	xa->req_disp_param = psdisp + pscnt;
421 	xa->req_disp_data  = dsdisp + dscnt;
422 
423 	/*
424 	 * See comment in smb_com_transaction_secondary
425 	 */
426 	if (xa->req_param_mb.chain_offset != psdisp) {
427 		DTRACE_PROBE2(trans_param_disp,
428 		    smb_xa_t *, xa, uint16_t, psdisp);
429 		xa->req_param_mb.chain_offset = psdisp;
430 	}
431 	if (xa->req_data_mb.chain_offset != dsdisp) {
432 		DTRACE_PROBE2(trans_data_disp,
433 		    smb_xa_t *, xa, uint16_t, dsdisp);
434 		xa->req_data_mb.chain_offset = dsdisp;
435 	}
436 
437 	if (smb_mbc_copy(&xa->req_param_mb, &sr->command, psoff, pscnt)) {
438 		mutex_exit(&xa->xa_mutex);
439 		smb_xa_close(xa);
440 		smbsr_error(sr, 0, ERRDOS, ERRbadformat);
441 		return (SDRC_ERROR);
442 	}
443 	if (smb_mbc_copy(&xa->req_data_mb, &sr->command, dsoff, dscnt)) {
444 		mutex_exit(&xa->xa_mutex);
445 		smb_xa_close(xa);
446 		smbsr_error(sr, 0, ERRDOS, ERRbadformat);
447 		return (SDRC_ERROR);
448 	}
449 	mutex_exit(&xa->xa_mutex);
450 
451 	if (!smb_trans_ready(xa))
452 		return (SDRC_NO_REPLY);
453 
454 	if (!smb_xa_complete(xa))
455 		return (SDRC_NO_REPLY);
456 
457 	return (smb_trans2_dispatch(sr, xa));
458 }
459 
460 static smb_sdrc_t
461 smb_nt_trans_dispatch(struct smb_request *sr, struct smb_xa *xa)
462 {
463 	int rc;
464 	int total_bytes, n_setup, n_param, n_data;
465 	int param_off, param_pad, data_off, data_pad;
466 
467 	switch (xa->smb_func) {
468 	case NT_TRANSACT_CREATE:
469 		if ((rc = smb_pre_nt_transact_create(sr, xa)) == 0)
470 			rc = smb_nt_transact_create(sr, xa);
471 		smb_post_nt_transact_create(sr, xa);
472 		break;
473 	case NT_TRANSACT_NOTIFY_CHANGE:
474 		rc = smb_nt_transact_notify_change(sr, xa);
475 		break;
476 	case NT_TRANSACT_QUERY_SECURITY_DESC:
477 		rc = smb_nt_transact_query_security_info(sr, xa);
478 		break;
479 	case NT_TRANSACT_SET_SECURITY_DESC:
480 		rc = smb_nt_transact_set_security_info(sr, xa);
481 		break;
482 	case NT_TRANSACT_IOCTL:
483 		rc = smb_nt_transact_ioctl(sr, xa);
484 		break;
485 	case NT_TRANSACT_QUERY_QUOTA:
486 		rc = smb_nt_transact_query_quota(sr, xa);
487 		break;
488 	case NT_TRANSACT_SET_QUOTA:
489 		rc = smb_nt_transact_set_quota(sr, xa);
490 		break;
491 	case NT_TRANSACT_RENAME:
492 		rc = smb_nt_transact_rename(sr, xa);
493 		break;
494 
495 	default:
496 		smbsr_error(sr, 0, ERRSRV, ERRsmbcmd);
497 		return (SDRC_ERROR);
498 	}
499 
500 	switch (rc) {
501 	case SDRC_SUCCESS:
502 		break;
503 
504 	case SDRC_DROP_VC:
505 	case SDRC_NO_REPLY:
506 	case SDRC_ERROR:
507 	case SDRC_SR_KEPT:
508 		return (rc);
509 
510 	case SDRC_NOT_IMPLEMENTED:
511 		smbsr_error(sr, 0, ERRSRV, ERRsmbcmd);
512 		return (SDRC_ERROR);
513 
514 	default:
515 		break;
516 	}
517 
518 	n_setup = MBC_LENGTH(&xa->rep_setup_mb);
519 	n_param = MBC_LENGTH(&xa->rep_param_mb);
520 	n_data  = MBC_LENGTH(&xa->rep_data_mb);
521 
522 	if (xa->smb_msrcnt < n_setup ||
523 	    xa->smb_mprcnt < n_param ||
524 	    xa->smb_mdrcnt < n_data) {
525 		smbsr_error(sr, 0, ERRSRV, ERRsmbcmd);
526 		return (SDRC_ERROR);
527 	}
528 
529 	/* neato, blast it over there */
530 
531 	n_setup = (n_setup + 1) / 2;		/* Conver to setup words */
532 	param_pad = 1;				/* must be one */
533 	param_off = param_pad + 32 + 37 + (n_setup << 1) + 2;
534 	data_pad = (4 - ((param_off + n_param) & 3)) % 4; /* Pad to 4 byte */
535 	data_off = param_off + n_param + data_pad; /* Param off from hdr */
536 	total_bytes = param_pad + n_param + data_pad + n_data;
537 
538 	rc = smbsr_encode_result(sr, 18+n_setup, total_bytes,
539 	    "b3.llllllllbCw#.C#.C",
540 	    18 + n_setup,		/* wct */
541 	    n_param,			/* Total Parameter Bytes */
542 	    n_data,			/* Total Data Bytes */
543 	    n_param,			/* Total Parameter Bytes this buffer */
544 	    param_off,			/* Param offset from header start */
545 	    0,				/* Param displacement */
546 	    n_data,			/* Total Data Bytes this buffer */
547 	    data_off,			/* Data offset from header start */
548 	    0,				/* Data displacement */
549 	    n_setup,			/* suwcnt */
550 	    &xa->rep_setup_mb,		/* setup[] */
551 	    total_bytes,		/* Total data bytes */
552 	    param_pad,
553 	    &xa->rep_param_mb,
554 	    data_pad,
555 	    &xa->rep_data_mb);
556 	return ((rc == 0) ? SDRC_SUCCESS : SDRC_ERROR);
557 }
558 
559 smb_sdrc_t
560 smb_pre_nt_transact(smb_request_t *sr)
561 {
562 	DTRACE_SMB_START(op__NtTransact, smb_request_t *, sr);
563 	return (SDRC_SUCCESS);
564 }
565 
566 void
567 smb_post_nt_transact(smb_request_t *sr)
568 {
569 	DTRACE_SMB_DONE(op__NtTransact, smb_request_t *, sr);
570 }
571 
572 smb_sdrc_t
573 smb_com_nt_transact(struct smb_request *sr)
574 {
575 	uint16_t	Function;
576 	unsigned char	MaxSetupCount, SetupCount;
577 	uint32_t	TotalParameterCount, TotalDataCount;
578 	uint32_t	MaxParameterCount, MaxDataCount, pscnt;
579 	uint32_t	psoff, dscnt, dsoff;
580 	smb_xa_t *xa;
581 	int ready;
582 	int rc;
583 
584 	rc = smbsr_decode_vwv(sr, SMB_NT_TRANSHDR_ED_FMT, &MaxSetupCount,
585 	    &TotalParameterCount, &TotalDataCount, &MaxParameterCount,
586 	    &MaxDataCount, &pscnt, &psoff, &dscnt,
587 	    &dsoff, &SetupCount, &Function);
588 
589 	if (rc != 0)
590 		return (SDRC_ERROR);
591 
592 	xa = smb_xa_create(sr->session, sr, TotalParameterCount, TotalDataCount,
593 	    MaxParameterCount, MaxDataCount, MaxSetupCount, SetupCount);
594 	if (xa == 0) {
595 		smbsr_error(sr, 0, ERRSRV, ERRnoroom);
596 		return (SDRC_ERROR);
597 	}
598 
599 	xa->smb_flags  = 0;
600 	xa->smb_timeout = 0;
601 	xa->smb_func = Function;
602 	xa->req_disp_param = pscnt;
603 	xa->req_disp_data  = dscnt;
604 
605 	if (smb_mbc_copy(&xa->req_setup_mb, &sr->smb_vwv,
606 	    sr->smb_vwv.chain_offset, SetupCount * 2)) {
607 		smb_xa_rele(sr->session, xa);
608 		smbsr_error(sr, 0, ERRDOS, ERRbadformat);
609 		return (SDRC_ERROR);
610 	}
611 	if (smb_mbc_copy(&xa->req_param_mb, &sr->command, psoff, pscnt)) {
612 		smb_xa_rele(sr->session, xa);
613 		smbsr_error(sr, 0, ERRDOS, ERRbadformat);
614 		return (SDRC_ERROR);
615 	}
616 	if (smb_mbc_copy(&xa->req_data_mb, &sr->command, dsoff, dscnt)) {
617 		smb_xa_rele(sr->session, xa);
618 		smbsr_error(sr, 0, ERRDOS, ERRbadformat);
619 		return (SDRC_ERROR);
620 	}
621 
622 	ready = smb_trans_ready(xa);
623 
624 	if (smb_xa_open(xa)) {
625 		smb_xa_rele(sr->session, xa);
626 		smbsr_error(sr, 0, ERRSRV, ERRsrverror);
627 		return (SDRC_ERROR);
628 	}
629 	sr->r_xa = xa;
630 
631 	if (!ready) {
632 		rc = smbsr_encode_empty_result(sr);
633 		return ((rc == 0) ? SDRC_SUCCESS : SDRC_ERROR);
634 	}
635 
636 	if (!smb_xa_complete(xa)) {
637 		smb_xa_close(xa);
638 		smbsr_error(sr, 0, ERRDOS, ERRbadformat);
639 		return (SDRC_ERROR);
640 	}
641 
642 	return (smb_nt_trans_dispatch(sr, xa));
643 }
644 
645 smb_sdrc_t
646 smb_pre_nt_transact_secondary(smb_request_t *sr)
647 {
648 	DTRACE_SMB_START(op__NtTransactSecondary, smb_request_t *, sr);
649 	return (SDRC_SUCCESS);
650 }
651 
652 void
653 smb_post_nt_transact_secondary(smb_request_t *sr)
654 {
655 	DTRACE_SMB_DONE(op__NtTransactSecondary, smb_request_t *, sr);
656 }
657 
658 smb_sdrc_t
659 smb_com_nt_transact_secondary(struct smb_request *sr)
660 {
661 	uint16_t tpscnt, tdscnt, fid;
662 	uint16_t pscnt, psoff, psdisp, dscnt, dsoff, dsdisp;
663 	smb_xa_t *xa;
664 	int rc;
665 
666 	if ((xa = smbsr_lookup_xa(sr)) == 0) {
667 		smbsr_error(sr, 0, ERRSRV, ERRsrverror);
668 		return (SDRC_ERROR);
669 	}
670 
671 	if (sr->session->signing.flags & SMB_SIGNING_ENABLED) {
672 		if (smb_sign_check_secondary(sr, xa->reply_seqnum) != 0) {
673 			smbsr_error(sr, NT_STATUS_ACCESS_DENIED,
674 			    ERRDOS, ERRnoaccess);
675 			return (SDRC_ERROR);
676 		}
677 	}
678 
679 	if (xa->smb_com != SMB_COM_TRANSACTION2) {
680 		return (SDRC_DROP_VC);
681 	}
682 
683 	rc = smbsr_decode_vwv(sr, SMB_TRANS2SHDR_ED_FMT, &tpscnt, &tdscnt,
684 	    &pscnt, &psoff, &psdisp, &dscnt, &dsoff, &dsdisp, &fid);
685 
686 	if (rc != 0)
687 		return (SDRC_ERROR);
688 
689 	mutex_enter(&xa->xa_mutex);
690 	if (xa->smb_tpscnt > tpscnt)
691 		xa->smb_tpscnt = tpscnt;
692 	if (xa->smb_tdscnt > tdscnt)
693 		xa->smb_tdscnt = tdscnt;
694 	if (fid != 0xFFFF)
695 		xa->xa_smb_fid = fid;
696 	xa->req_disp_param = psdisp + pscnt;
697 	xa->req_disp_data  = dsdisp + dscnt;
698 
699 	/*
700 	 * See comment in smb_com_transaction_secondary
701 	 */
702 	if (xa->req_param_mb.chain_offset != psdisp) {
703 		DTRACE_PROBE2(trans_param_disp,
704 		    smb_xa_t *, xa, uint16_t, psdisp);
705 		xa->req_param_mb.chain_offset = psdisp;
706 	}
707 	if (xa->req_data_mb.chain_offset != dsdisp) {
708 		DTRACE_PROBE2(trans_data_disp,
709 		    smb_xa_t *, xa, uint16_t, dsdisp);
710 		xa->req_data_mb.chain_offset = dsdisp;
711 	}
712 
713 	if (smb_mbc_copy(&xa->req_param_mb, &sr->command, psoff, pscnt)) {
714 		mutex_exit(&xa->xa_mutex);
715 		smb_xa_close(xa);
716 		smbsr_error(sr, 0, ERRDOS, ERRbadformat);
717 		return (SDRC_ERROR);
718 	}
719 	if (smb_mbc_copy(&xa->req_data_mb, &sr->command, dsoff, dscnt)) {
720 		mutex_exit(&xa->xa_mutex);
721 		smb_xa_close(xa);
722 		smbsr_error(sr, 0, ERRDOS, ERRbadformat);
723 		return (SDRC_ERROR);
724 	}
725 	mutex_exit(&xa->xa_mutex);
726 
727 	if (!smb_trans_ready(xa))
728 		return (SDRC_NO_REPLY);
729 
730 	if (!smb_xa_complete(xa))
731 		return (SDRC_NO_REPLY);
732 
733 	return (smb_nt_trans_dispatch(sr, xa));
734 }
735 
736 static int
737 smb_trans_ready(smb_xa_t *xa)
738 {
739 	int rc;
740 
741 	mutex_enter(&xa->xa_mutex);
742 	rc = xa->req_disp_data >= xa->smb_tdscnt &&
743 	    xa->req_disp_param >= xa->smb_tpscnt;
744 	mutex_exit(&xa->xa_mutex);
745 
746 	return (rc);
747 }
748 
749 static void
750 smb_encode_SHARE_INFO_1(struct mbuf_chain *output, struct mbuf_chain *text,
751     char *oem_name, uint16_t type, char *comment)
752 {
753 	(void) smb_mbc_encodef(output, "13c.wl", oem_name,
754 	    type, MBC_LENGTH(text));
755 
756 	(void) smb_mbc_encodef(text, "s", comment ? comment : "");
757 }
758 
759 static void
760 smb_encode_SHARE_INFO_2(struct mbuf_chain *output, struct mbuf_chain *text,
761     smb_request_t *sr, char *oem_name, uint16_t type,
762     char *comment, uint16_t access, char *path, char *password)
763 {
764 	unsigned char pword[9];
765 
766 	bzero(pword, sizeof (pword));
767 	(void) strncpy((char *)pword, password, sizeof (pword));
768 	smb_encode_SHARE_INFO_1(output, text, oem_name, type, comment);
769 	(void) smb_mbc_encodef(output, "wwwl9c.",
770 	    access,
771 	    sr->sr_cfg->skc_maxconnections,
772 	    smb_server_get_session_count(sr->sr_server),
773 	    MBC_LENGTH(text),
774 	    pword);
775 	(void) smb_mbc_encodef(text, "s", path);
776 }
777 
778 int smb_trans_share_enum = 0;
779 
780 /*
781  * This is a legacy interface, no longer supported.
782  * Clients now use MS-RPC for share enumeration.
783  * Does not implement access-based enumeration (ABE)
784  * so do not enable if you care about share list ABE.
785  */
786 int
787 smb_trans_net_share_enum(struct smb_request *sr, struct smb_xa *xa)
788 {
789 	uint16_t pid_hi, pid_lo;
790 
791 	/*
792 	 * Number of data bytes that will
793 	 * be sent in the current response
794 	 */
795 	uint16_t data_scnt;
796 
797 	/*
798 	 * Total number of data bytes that
799 	 * are sent till now. This is only
800 	 * used for calculating current data
801 	 * displacement
802 	 */
803 	uint16_t tot_data_scnt;
804 
805 	/*
806 	 * Number of parameter bytes should
807 	 * be sent for the current response.
808 	 * It is 8 for the 1st response and
809 	 * 0 for others
810 	 */
811 	uint16_t param_scnt;
812 
813 	/* number of setup and parameter bytes */
814 	uint16_t n_setup, n_param;
815 
816 	/* data and parameter displacement */
817 	uint16_t data_disp, param_disp;
818 
819 	/* parameter and data offset and pad */
820 	int param_off, param_pad, data_off, data_pad;
821 
822 	/*
823 	 * total bytes of parameters and data
824 	 * in the packet, plus the pad bytes.
825 	 */
826 	int tot_packet_bytes;
827 
828 	boolean_t first_resp;
829 
830 	char fmt[16];
831 	struct mbuf_chain reply;
832 
833 	uint16_t level;
834 	uint16_t pkt_bufsize;
835 	smb_enumshare_info_t esi;
836 	char *sent_buf;
837 
838 	ASSERT(sr->uid_user);
839 
840 	if (smb_trans_share_enum == 0)
841 		return (SDRC_NOT_IMPLEMENTED);
842 
843 	if (smb_mbc_decodef(&xa->req_param_mb, "ww", &level,
844 	    &esi.es_bufsize) != 0)
845 		return (SDRC_NOT_IMPLEMENTED);
846 
847 	if (level != 1) {
848 		/*
849 		 * Only level 1 is valid for NetShareEnum
850 		 * None of the error codes in the spec are meaningful
851 		 * here. This error code is returned by Windows.
852 		 */
853 		(void) smb_mbc_encodef(&xa->rep_param_mb, "wwww",
854 		    ERROR_INVALID_LEVEL, 0, 0, 0);
855 		return (SDRC_SUCCESS);
856 	}
857 
858 	esi.es_buf = smb_srm_zalloc(sr, esi.es_bufsize);
859 	esi.es_posix_uid = crgetuid(sr->uid_user->u_cred);
860 	smb_kshare_enum(sr->sr_server, &esi);
861 
862 	/* client buffer size is not big enough to hold any shares */
863 	if (esi.es_nsent == 0) {
864 		(void) smb_mbc_encodef(&xa->rep_param_mb, "wwww",
865 		    ERROR_MORE_DATA, 0, esi.es_nsent, esi.es_ntotal);
866 		return (SDRC_SUCCESS);
867 	}
868 
869 	/*
870 	 * Initialize the reply mbuf chain.  Note that we re-initialize
871 	 * this on each pass through the loop below.
872 	 */
873 	MBC_SETUP(&reply, smb_maxbufsize);
874 
875 	/*
876 	 * The rep_setup_mb is already initialized in smb_trans_dispatch().
877 	 * Calling MBC_INIT() will initialized the structure and so the
878 	 * pointer to the mbuf chains will be lost. Therefore, we need
879 	 * to free the resources before calling MBC_INIT() again.
880 	 */
881 	n_setup = 0;	/* Setup count for NetShareEnum SMB is 0 */
882 	MBC_FLUSH(&xa->rep_setup_mb);
883 
884 	n_param = 8;
885 	pkt_bufsize = sr->session->smb_msg_size -
886 	    (SMB_HEADER_ED_LEN + RESP_HEADER_LEN + n_param);
887 
888 	tot_data_scnt = 0;
889 	sent_buf = esi.es_buf;
890 	first_resp = B_TRUE;
891 
892 	while (tot_data_scnt < esi.es_datasize) {
893 		data_scnt = esi.es_datasize - tot_data_scnt;
894 		if (data_scnt > pkt_bufsize)
895 			data_scnt = pkt_bufsize;
896 		MBC_FLUSH(&xa->rep_data_mb);
897 
898 		(void) sprintf(fmt, "%dc", data_scnt);
899 		(void) smb_mbc_encodef(&xa->rep_data_mb, fmt, sent_buf);
900 
901 		sent_buf += data_scnt;
902 		tot_data_scnt += data_scnt;
903 
904 		/* Only the 1st response packet contains parameters */
905 		param_scnt = (first_resp) ? n_param : 0;
906 		param_pad = 1;				/* always one */
907 		param_off = SMB_HEADER_ED_LEN + RESP_HEADER_LEN;
908 		param_disp = (first_resp) ? 0 : n_param;
909 
910 		MBC_FLUSH(&xa->rep_param_mb);
911 
912 		if (first_resp) {
913 			first_resp = B_FALSE;
914 			(void) smb_mbc_encodef(&xa->rep_param_mb, "wwww",
915 			    (esi.es_ntotal > esi.es_nsent)
916 			    ? ERROR_MORE_DATA : 0,
917 			    0, esi.es_nsent, esi.es_ntotal);
918 		}
919 
920 		data_pad = (param_off + n_param) & 1;	/* Pad to short */
921 
922 		/* data off from hdr start */
923 		data_off = param_off + param_scnt + data_pad;
924 		data_disp = tot_data_scnt - data_scnt;
925 		tot_packet_bytes = param_pad + param_scnt + data_pad +
926 		    data_scnt;
927 
928 		pid_hi = sr->smb_pid >> 16;
929 		pid_lo = (uint16_t)sr->smb_pid;
930 
931 		MBC_FLUSH(&reply);
932 		(void) smb_mbc_encodef(&reply, SMB_HEADER_ED_FMT,
933 		    sr->first_smb_com,
934 		    sr->smb_rcls,
935 		    sr->smb_reh,
936 		    sr->smb_err,
937 		    sr->smb_flg | SMB_FLAGS_REPLY,
938 		    sr->smb_flg2,
939 		    pid_hi,
940 		    sr->smb_sig,
941 		    sr->smb_tid,
942 		    pid_lo,
943 		    sr->smb_uid,
944 		    sr->smb_mid);
945 
946 		(void) smb_mbc_encodef(&reply,
947 		    "bww2.wwwwwwb.Cw#.C#.C",
948 		    10 + n_setup,	/* wct */
949 		    n_param,		/* Total Parameter Bytes */
950 		    esi.es_datasize,	/* Total Data Bytes */
951 		    param_scnt,		/* Total Parameter Bytes this buffer */
952 		    param_off,		/* Param offset from header start */
953 		    param_disp,		/* Param displacement */
954 		    data_scnt,		/* Total Data Bytes this buffer */
955 		    data_off,		/* Data offset from header start */
956 		    data_disp,		/* Data displacement */
957 		    n_setup,		/* suwcnt */
958 		    &xa->rep_setup_mb,	/* setup[] */
959 		    tot_packet_bytes,	/* Total data bytes */
960 		    param_pad,
961 		    &xa->rep_param_mb,
962 		    data_pad,
963 		    &xa->rep_data_mb);
964 
965 		if (sr->session->signing.flags & SMB_SIGNING_ENABLED)
966 			smb_sign_reply(sr, &reply);
967 
968 		(void) smb_session_send(sr->session, 0, &reply);
969 
970 	}
971 
972 	m_freem(reply.chain);
973 
974 	return (SDRC_NO_REPLY);
975 }
976 
977 int smb_trans_share_getinfo = 0;
978 
979 /*
980  * This is a legacy interface, no longer supported.
981  * Clients now use MS-RPC to get share information.
982  * Does not implement access-based enumeration (ABE)
983  * so do not enable if you care about share list ABE.
984  */
985 int
986 smb_trans_net_share_getinfo(smb_request_t *sr, struct smb_xa *xa)
987 {
988 	uint16_t		level, max_bytes, access;
989 	struct mbuf_chain	str_mb;
990 	char			*share;
991 	char			*password;
992 	smb_kshare_t		*si;
993 
994 	if (smb_trans_share_getinfo == 0)
995 		return (SDRC_NOT_IMPLEMENTED);
996 
997 	if (smb_mbc_decodef(&xa->req_param_mb, "%sww", sr,
998 	    &share, &level, &max_bytes) != 0)
999 		return (SDRC_NOT_IMPLEMENTED);
1000 
1001 	si = smb_kshare_lookup(sr->sr_server, share);
1002 	if ((si == NULL) || (si->shr_oemname == NULL)) {
1003 		(void) smb_mbc_encodef(&xa->rep_param_mb, "www",
1004 		    NERR_NetNameNotFound, 0, 0);
1005 		if (si)
1006 			smb_kshare_release(sr->sr_server, si);
1007 		return (SDRC_SUCCESS);
1008 	}
1009 
1010 	access = SHARE_ACCESS_ALL;
1011 	password = "";
1012 
1013 	MBC_INIT(&str_mb, max_bytes);
1014 
1015 	switch (level) {
1016 	case 0 :
1017 		(void) smb_mbc_encodef(&xa->rep_data_mb, "13c",
1018 		    si->shr_oemname);
1019 		break;
1020 
1021 	case 1 :
1022 		smb_encode_SHARE_INFO_1(&xa->rep_data_mb, &str_mb,
1023 		    si->shr_oemname, si->shr_type, si->shr_cmnt);
1024 		break;
1025 
1026 	case 2 :
1027 		smb_encode_SHARE_INFO_2(&xa->rep_data_mb, &str_mb, sr,
1028 		    si->shr_oemname, si->shr_type, si->shr_cmnt, access,
1029 		    si->shr_path, password);
1030 		break;
1031 
1032 	default:
1033 		smb_kshare_release(sr->sr_server, si);
1034 		(void) smb_mbc_encodef(&xa->rep_param_mb, "www",
1035 		    ERROR_INVALID_LEVEL, 0, 0);
1036 		m_freem(str_mb.chain);
1037 		return (SDRC_NOT_IMPLEMENTED);
1038 	}
1039 
1040 	smb_kshare_release(sr->sr_server, si);
1041 	(void) smb_mbc_encodef(&xa->rep_param_mb, "www", NERR_Success,
1042 	    -MBC_LENGTH(&xa->rep_data_mb),
1043 	    MBC_LENGTH(&xa->rep_data_mb) + MBC_LENGTH(&str_mb));
1044 	(void) smb_mbc_encodef(&xa->rep_data_mb, "C", &str_mb);
1045 	m_freem(str_mb.chain);
1046 	return (SDRC_SUCCESS);
1047 }
1048 
1049 int
1050 smb_trans_net_workstation_getinfo(struct smb_request *sr, struct smb_xa *xa)
1051 {
1052 	uint16_t		level, max_bytes;
1053 	struct mbuf_chain	str_mb;
1054 	char *domain;
1055 	char *hostname;
1056 
1057 	if ((smb_mbc_decodef(&xa->req_param_mb, "ww",
1058 	    &level, &max_bytes) != 0) ||
1059 	    (level != 10)) {
1060 		(void) smb_mbc_encodef(&xa->rep_param_mb, "wwww",
1061 		    NERR_BadTransactConfig, 0, 0, 0);
1062 		return (SDRC_SUCCESS);
1063 	}
1064 
1065 	domain = sr->sr_cfg->skc_nbdomain;
1066 	hostname = sr->sr_cfg->skc_hostname;
1067 
1068 	MBC_INIT(&str_mb, max_bytes);
1069 
1070 	(void) smb_mbc_encodef(&str_mb, "."); /* Prevent NULL pointers */
1071 
1072 	(void) smb_mbc_encodef(&xa->rep_data_mb, "l", MBC_LENGTH(&str_mb));
1073 	(void) smb_mbc_encodef(&str_mb, "s", hostname);
1074 	(void) smb_mbc_encodef(&xa->rep_data_mb, "l", MBC_LENGTH(&str_mb));
1075 	(void) smb_mbc_encodef(&str_mb, "s", "nobody");
1076 	(void) smb_mbc_encodef(&xa->rep_data_mb, "l", MBC_LENGTH(&str_mb));
1077 	(void) smb_mbc_encodef(&str_mb, "s", domain);
1078 	(void) smb_mbc_encodef(&xa->rep_data_mb, "bbl",
1079 	    (uint8_t)sr->sr_cfg->skc_version.sv_major,
1080 	    (uint8_t)sr->sr_cfg->skc_version.sv_minor,
1081 	    MBC_LENGTH(&str_mb));
1082 	(void) smb_mbc_encodef(&str_mb, "s", domain);
1083 	(void) smb_mbc_encodef(&xa->rep_data_mb, "l", MBC_LENGTH(&str_mb));
1084 	(void) smb_mbc_encodef(&str_mb, "s", domain);
1085 
1086 	(void) smb_mbc_encodef(&xa->rep_param_mb, "www", 0,
1087 	    -MBC_LENGTH(&xa->rep_data_mb),
1088 	    MBC_LENGTH(&xa->rep_data_mb) + MBC_LENGTH(&str_mb));
1089 	(void) smb_mbc_encodef(&xa->rep_data_mb, "C", &str_mb);
1090 	m_freem(str_mb.chain);
1091 	return (SDRC_SUCCESS);
1092 }
1093 
1094 int
1095 smb_trans_net_user_getinfo(struct smb_request *sr, struct smb_xa *xa)
1096 {
1097 	uint16_t		level, max_bytes;
1098 	unsigned char		*user;
1099 	int rc;
1100 
1101 	rc = smb_mbc_decodef(&xa->req_param_mb, "%sww", sr,
1102 	    &user,
1103 	    &level,
1104 	    &max_bytes);
1105 
1106 	if (rc != 0)
1107 		return (SDRC_NOT_IMPLEMENTED);
1108 
1109 	(void) smb_mbc_encodef(&xa->rep_param_mb, "www",
1110 	    NERR_UserNotFound, 0, 0);
1111 	return (SDRC_SUCCESS);
1112 }
1113 
1114 smb_sdrc_t
1115 smb_trans_net_server_getinfo(struct smb_request *sr, struct smb_xa *xa)
1116 {
1117 	uint16_t		level, buf_size;
1118 	uint16_t		avail_data, max_data;
1119 	char			server_name[16];
1120 	struct mbuf_chain	str_mb;
1121 
1122 	if (smb_mbc_decodef(&xa->req_param_mb, "ww", &level, &buf_size) != 0)
1123 		return (SDRC_ERROR);
1124 
1125 	max_data = MBC_MAXBYTES(&xa->rep_data_mb);
1126 
1127 	MBC_INIT(&str_mb, buf_size);
1128 
1129 	bzero(server_name, sizeof (server_name));
1130 	(void) strncpy(server_name, sr->sr_cfg->skc_hostname,
1131 	    sizeof (server_name));
1132 
1133 	/* valid levels are 0 and 1 */
1134 	switch (level) {
1135 	case 0:
1136 		(void) smb_mbc_encodef(&xa->rep_data_mb, "16c", server_name);
1137 		break;
1138 
1139 	case 1:
1140 		(void) smb_mbc_encodef(&str_mb, "s",
1141 		    sr->sr_cfg->skc_system_comment);
1142 		(void) smb_mbc_encodef(&xa->rep_data_mb, "16cbbll", server_name,
1143 		    (uint8_t)sr->sr_cfg->skc_version.sv_major,
1144 		    (uint8_t)sr->sr_cfg->skc_version.sv_minor,
1145 		    MY_SERVER_TYPE, max_data - MBC_LENGTH(&str_mb));
1146 		break;
1147 
1148 	default:
1149 		(void) smb_mbc_encodef(&xa->rep_param_mb, "www",
1150 		    ERROR_INVALID_LEVEL, 0, 0);
1151 		m_freem(str_mb.chain);
1152 		return (SDRC_SUCCESS);
1153 	}
1154 
1155 	avail_data = MBC_LENGTH(&xa->rep_data_mb) + MBC_LENGTH(&str_mb);
1156 	(void) smb_mbc_encodef(&xa->rep_param_mb, "www",
1157 	    NERR_Success, max_data - avail_data, avail_data);
1158 	(void) smb_mbc_encodef(&xa->rep_data_mb, "C", &str_mb);
1159 	m_freem(str_mb.chain);
1160 	return (SDRC_SUCCESS);
1161 }
1162 
1163 /*
1164  * 6.4 The NetServerEnum2 RAP Service
1165  *
1166  * The NetServerEnum2 RAP service lists all computers of the specified type
1167  * or types that are visible in the specified domains. It may also
1168  * enumerate domains.
1169  *
1170  * The following definition uses the notation and terminology defined in
1171  * the CIFS Remote Administration Protocol specification, which is required
1172  * in order to make it well-defined. The definition is:
1173  *
1174  *     uint16_t NetServerEnum2 (
1175  *         uint16_t  sLevel,
1176  *         RCVBUF          pbBuffer,
1177  *         RCVBUFLEN       cbBuffer,
1178  *         ENTCOUNT        pcEntriesRead,
1179  *         uint16_t  *pcTotalAvail,
1180  *         uint32_t   fServerType,
1181  *         char            *pszDomain,
1182  *     );
1183  *
1184  * where:
1185  *
1186  *    sLevel specifies the level of detail (0 or 1) requested.
1187  *
1188  *    pbBuffer points to the buffer to receive the returned data. If the
1189  *    function is successful, the buffer contains a sequence of
1190  *    server_info_x structures, where x is 0 or 1, depending on the
1191  *    level of detail requested.
1192  *
1193  *    cbBuffer specifies the size, in bytes, of the buffer pointed to by
1194  *    the pbBuffer parameter.
1195  *
1196  *    pcEntriesRead points to a 16 bit variable that receives a count of
1197  *    the number of servers enumerated in the buffer. This count is
1198  *    valid only if NetServerEnum2 returns the NERR_Success or
1199  *    ERROR_MORE_DATA values.
1200  *
1201  *    pcTotal Avail points to a 16 bit variable that receives a count of
1202  *    the total number of available entries. This count is valid only if
1203  *    NetServerEnum2 returns the NERR_Success or ERROR_MORE_DATA values.
1204  *
1205  *     fServerType specifies the type or types of computers to enumerate.
1206  *     Computers that match at least one of the specified types are
1207  *     returned in the buffer. Possible values are defined in the request
1208  *     parameters section.
1209  *
1210  *    pszDomain points to a null-terminated string that contains the
1211  *    name of the workgroup in which to enumerate computers of the
1212  *    specified type or types. If the pszDomain parameter is a null
1213  *    string or a null pointer, servers are enumerated for the current
1214  *    domain of the computer.
1215  *
1216  * 6.4.1 Transaction Request Parameters section
1217  *
1218  * The Transaction request parameters section in this instance contains:
1219  * . The 16 bit function number for NetServerEnum2 which is 104.
1220  * . The parameter descriptor string which is "WrLehDz".
1221  * . The data descriptor string for the (returned) data which is "B16" for
1222  *   level detail 0 or "B16BBDz" for level detail 1.
1223  * . The actual parameters as described by the parameter descriptor
1224  *   string.
1225  *
1226  * The parameters are:
1227  * . A 16 bit integer with a value of 0 or 1 (corresponding to the "W" in
1228  *   the parameter descriptor string. This represents the level of detail
1229  *   the server is expected to return
1230  * . A 16 bit integer that contains the size of the receive buffer.
1231  * . A 32 bit integer that represents the type of servers the function
1232  *   should enumerate. The possible values may be any of the following or
1233  *   a combination of the following:
1234  *
1235  * SV_TYPE_WORKSTATION        0x00000001 All workstations
1236  * SV_TYPE_SERVER             0x00000002 All servers
1237  * SV_TYPE_SQLSERVER          0x00000004 Any server running with SQL
1238  *                                       server
1239  * SV_TYPE_DOMAIN_CTRL        0x00000008 Primary domain controller
1240  * SV_TYPE_DOMAIN_BAKCTRL     0x00000010 Backup domain controller
1241  * SV_TYPE_TIME_SOURCE        0x00000020 Server running the timesource
1242  *                                       service
1243  * SV_TYPE_AFP                0x00000040 Apple File Protocol servers
1244  * SV_TYPE_NOVELL             0x00000080 Novell servers
1245  * SV_TYPE_DOMAIN_MEMBER      0x00000100 Domain Member
1246  * SV_TYPE_PRINTQ_SERVER      0x00000200 Server sharing print queue
1247  * SV_TYPE_DIALIN_SERVER      0x00000400 Server running dialin service.
1248  * SV_TYPE_XENIX_SERVER       0x00000800 Xenix server
1249  * SV_TYPE_NT                 0x00001000 NT server
1250  * SV_TYPE_WFW                0x00002000 Server running Windows for
1251  *                                       Workgroups
1252  * SV_TYPE_SERVER_NT          0x00008000 Windows NT non DC server
1253  * SV_TYPE_POTENTIAL_BROWSER  0x00010000 Server that can run the browser
1254  *                                       service
1255  * SV_TYPE_BACKUP_BROWSER     0x00020000 Backup browser server
1256  * SV_TYPE_MASTER_BROWSER     0x00040000 Master browser server
1257  * SV_TYPE_DOMAIN_MASTER      0x00080000 Domain Master Browser server
1258  * SV_TYPE_LOCAL_LIST_ONLY    0x40000000 Enumerate only entries marked
1259  *                                       "local"
1260  * SV_TYPE_DOMAIN_ENUM        0x80000000 Enumerate Domains. The pszDomain
1261  *                                       parameter must be NULL.
1262  *
1263  * . A null terminated ASCII string representing the pszDomain parameter
1264  *   described above
1265  *
1266  * 6.4.2 Transaction Request Data section
1267  *
1268  * There is no data or auxiliary data to send as part of the request.
1269  *
1270  * 6.4.3 Transaction Response Parameters section
1271  *
1272  * The transaction response parameters section consists of:
1273  * . A 16 bit word indicating the return status. The possible values are:
1274  *
1275  * Code                   Value  Description
1276  * NERR_Success           0      No errors encountered
1277  * ERROR_MORE_DATA        234    Additional data is available
1278  * NERR_ServerNotStarted  2114   The RAP service on the remote computer
1279  *                               is not running
1280  * NERR_BadTransactConfig 2141   The server is not configured for
1281  *                               transactions, IPC$ is not shared
1282  *
1283  * . A 16 bit "converter" word.
1284  * . A 16 bit number representing the number of entries returned.
1285  * . A 16 bit number representing the total number of available entries.
1286  *   If the supplied buffer is large enough, this will equal the number of
1287  *   entries returned.
1288  *
1289  * 6.4.4 Transaction Response Data section
1290  *
1291  * The return data section consists of a number of SERVER_INFO_1 structures.
1292  * The number of such structures present is determined by the third entry
1293  * (described above) in the return parameters section.
1294  *
1295  * At level detail 0, the Transaction response data section contains a
1296  * number of SERVER_INFO_0 data structure. The number of such structures is
1297  * equal to the 16 bit number returned by the server in the third parameter
1298  * in the Transaction response parameter section. The SERVER_INFO_0 data
1299  * structure is defined as:
1300  *
1301  *     struct SERVER_INFO_0 {
1302  *         char        sv0_name[16];
1303  *     };
1304  *
1305  *  where:
1306  *
1307  *    sv0_name is a null-terminated string that specifies the name of a
1308  *    computer or domain .
1309  *
1310  * At level detail 1, the Transaction response data section contains a
1311  * number of SERVER_INFO_1 data structure. The number of such structures is
1312  * equal to the 16 bit number returned by the server in the third parameter
1313  * in the Transaction response parameter section. The SERVER_INFO_1 data
1314  * structure is defined as:
1315  *
1316  *     struct SERVER_INFO_1 {
1317  *         char            sv1_name[16];
1318  *         char            sv1_version_major;
1319  *         char            sv1_version_minor;
1320  *         uint32_t   sv1_type;
1321  *         char        *sv1_comment_or_master_browser;
1322  *     };
1323  *
1324  *    sv1_name contains a null-terminated string that specifies the name
1325  *    of a computer, or a domain name if SV_TYPE_DOMAIN_ENUM is set in
1326  *    sv1_type.
1327  *
1328  *    sv1_version_major whatever was specified in the HostAnnouncement
1329  *    or DomainAnnouncement frame with which the entry was registered.
1330  *
1331  *    sv1_version_minor whatever was specified in the HostAnnouncement
1332  *    or DomainAnnouncement frame with which the entry was registered.
1333  *
1334  *    sv1_type specifies the type of software the computer is running.
1335  *    The member can be one or a combination of the values defined above
1336  *    in the Transaction request parameters section for fServerType.
1337  *
1338  *
1339  *    sv1_comment_or_master_browser points to a null-terminated string. If
1340  *    the sv1_type indicates that the entry is for a domain, this
1341  *    specifies the name of server running the domain master browser;
1342  *    otherwise, it specifies a comment describing the server. The comment
1343  *    can be a null string or the pointer may be a null pointer.
1344  *
1345  *    In case there are multiple SERVER_INFO_1 data structures to
1346  *    return, the server may put all these fixed length structures in
1347  *    the return buffer, leave some space and then put all the variable
1348  *    length data (the actual value of the sv1_comment strings) at the
1349  *    end of the buffer.
1350  *
1351  * There is no auxiliary data to receive.
1352  */
1353 
1354 int
1355 smb_trans_net_server_enum2(struct smb_request *sr, struct smb_xa *xa)
1356 {
1357 	uint16_t opcode, level, max_bytes;
1358 	uint32_t server_type;
1359 	unsigned char *domain;
1360 	struct mbuf_chain str_mb;
1361 	char *hostname, *s;
1362 	smb_kmod_cfg_t *si;
1363 
1364 	if (smb_mbc_decodef(&xa->req_param_mb,
1365 	    "%wsswwls", sr, &opcode, &s, &s,
1366 	    &level, &max_bytes, &server_type, &domain) != 0)
1367 		return (SDRC_NOT_IMPLEMENTED);
1368 
1369 	si = sr->sr_cfg;
1370 
1371 	if (smb_strcasecmp(si->skc_nbdomain, (char *)domain, 0) != 0) {
1372 		(void) smb_mbc_encodef(&xa->rep_param_mb, "wwww", 0, 0, 0, 0);
1373 		return (SDRC_SUCCESS);
1374 	}
1375 
1376 	if ((server_type & MY_SERVER_TYPE) == 0) {
1377 		(void) smb_mbc_encodef(&xa->rep_param_mb, "wwww", 0, 0, 0, 0);
1378 		return (SDRC_SUCCESS);
1379 	}
1380 
1381 	MBC_INIT(&str_mb, max_bytes);
1382 
1383 	hostname = si->skc_hostname;
1384 
1385 	(void) smb_mbc_encodef(&xa->rep_data_mb, "16c", hostname);
1386 	if (level == 1) {
1387 		(void) smb_mbc_encodef(&xa->rep_data_mb, "bbll",
1388 		    (uint8_t)sr->sr_cfg->skc_version.sv_major,
1389 		    (uint8_t)sr->sr_cfg->skc_version.sv_minor,
1390 		    MY_SERVER_TYPE, MBC_LENGTH(&str_mb));
1391 		(void) smb_mbc_encodef(&str_mb, "s", si->skc_system_comment);
1392 	}
1393 
1394 	(void) smb_mbc_encodef(&xa->rep_param_mb, "wwww", 0,
1395 	    -MBC_LENGTH(&xa->rep_data_mb), 1, 1);
1396 	(void) smb_mbc_encodef(&xa->rep_data_mb, "m", str_mb.chain);
1397 	return (SDRC_SUCCESS);
1398 }
1399 
1400 static boolean_t
1401 is_supported_mailslot(const char *mailslot)
1402 {
1403 	static char *mailslots[] = {
1404 		PIPE_LANMAN,
1405 		MAILSLOT_LANMAN,
1406 		MAILSLOT_BROWSE,
1407 		MAILSLOT_MSBROWSE
1408 	};
1409 
1410 	int i;
1411 
1412 	for (i = 0; i < sizeof (mailslots)/sizeof (mailslots[0]); ++i)
1413 		if (smb_strcasecmp(mailslot, mailslots[i], 0) == 0)
1414 			return (B_TRUE);
1415 
1416 	return (B_FALSE);
1417 }
1418 
1419 /*
1420  * smb_trans_nmpipe
1421  *
1422  * This is used for RPC bind and request transactions.
1423  *
1424  * If the data available from the pipe is larger than the maximum
1425  * data size requested by the client, return as much as requested.
1426  * The residual data remains in the pipe until the client comes back
1427  * with a read request or closes the pipe.
1428  *
1429  * When we read less than what's available, we MUST return the
1430  * status NT_STATUS_BUFFER_OVERFLOW (or ERRDOS/ERROR_MORE_DATA)
1431  */
1432 static smb_sdrc_t
1433 smb_trans_nmpipe(smb_request_t *sr, smb_xa_t *xa)
1434 {
1435 	smb_fsctl_t fsctl;
1436 	uint32_t status;
1437 
1438 	smbsr_lookup_file(sr);
1439 	if (sr->fid_ofile == NULL) {
1440 		smbsr_error(sr, NT_STATUS_INVALID_HANDLE,
1441 		    ERRDOS, ERRbadfid);
1442 		return (SDRC_ERROR);
1443 	}
1444 
1445 	/*
1446 	 * A little confusing perhaps, but the fsctl "input" is what we
1447 	 * write to the pipe (from the transaction "send" data), and the
1448 	 * fsctl "output" is what we read from the pipe (and becomes the
1449 	 * transaction receive data).
1450 	 */
1451 	fsctl.CtlCode = FSCTL_PIPE_TRANSCEIVE;
1452 	fsctl.InputCount = xa->smb_tdscnt; /* write count */
1453 	fsctl.OutputCount = 0; /* minimum to read from the pipe */
1454 	fsctl.MaxOutputResp = xa->smb_mdrcnt;	/* max to read */
1455 	fsctl.in_mbc = &xa->req_data_mb; /* write from here */
1456 	fsctl.out_mbc = &xa->rep_data_mb; /* read into here */
1457 
1458 	status = smb_opipe_transceive(sr, &fsctl);
1459 	if (status) {
1460 		smbsr_status(sr, status, 0, 0);
1461 		if (NT_SC_SEVERITY(status) == NT_STATUS_SEVERITY_ERROR)
1462 			return (SDRC_ERROR);
1463 		/* Warnings like NT_STATUS_BUFFER_OVERFLOW are OK */
1464 	}
1465 
1466 	return (SDRC_SUCCESS);
1467 }
1468 
1469 static smb_sdrc_t
1470 smb_trans_dispatch(smb_request_t *sr, smb_xa_t *xa)
1471 {
1472 	int		rc, pos;
1473 	int		total_bytes, n_setup, n_param, n_data;
1474 	int		param_off, param_pad, data_off, data_pad;
1475 	uint16_t	opcode;
1476 	uint16_t	devstate;
1477 	char		*req_fmt;
1478 	char		*rep_fmt;
1479 
1480 	if (xa->smb_suwcnt > 0) {
1481 		rc = smb_mbc_decodef(&xa->req_setup_mb, "ww", &opcode,
1482 		    &sr->smb_fid);
1483 		if (rc != 0)
1484 			goto trans_err_not_supported;
1485 		switch (opcode) {
1486 		case TRANS_SET_NMPIPE_STATE:
1487 			if ((rc = smb_mbc_decodef(&xa->req_param_mb, "w",
1488 			    &devstate)) != 0)
1489 				goto trans_err_not_supported;
1490 
1491 			rc = SDRC_SUCCESS;
1492 			break;
1493 
1494 		case TRANS_TRANSACT_NMPIPE:
1495 			rc = smb_trans_nmpipe(sr, xa);
1496 			break;
1497 
1498 		case TRANS_WAIT_NMPIPE:
1499 			delay(SEC_TO_TICK(1));
1500 			rc = SDRC_SUCCESS;
1501 			break;
1502 
1503 		default:
1504 			goto trans_err_not_supported;
1505 		}
1506 	} else {
1507 		if (!is_supported_mailslot(xa->xa_pipe_name))
1508 			goto trans_err_not_supported;
1509 
1510 		if ((rc = smb_mbc_decodef(&xa->req_param_mb, "%wss", sr,
1511 		    &opcode, &req_fmt, &rep_fmt)) != 0)
1512 			goto trans_err_not_supported;
1513 
1514 		switch (opcode) {
1515 		case API_WshareEnum:
1516 			rc = smb_trans_net_share_enum(sr, xa);
1517 			break;
1518 
1519 		case API_WshareGetInfo:
1520 			rc = smb_trans_net_share_getinfo(sr, xa);
1521 			break;
1522 
1523 		case API_WserverGetInfo:
1524 			rc = smb_trans_net_server_getinfo(sr, xa);
1525 			break;
1526 
1527 		case API_WUserGetInfo:
1528 			rc = smb_trans_net_user_getinfo(sr, xa);
1529 			break;
1530 
1531 		case API_WWkstaGetInfo:
1532 			rc = smb_trans_net_workstation_getinfo(sr, xa);
1533 			break;
1534 
1535 		case API_NetServerEnum2:
1536 			rc = smb_trans_net_server_enum2(sr, xa);
1537 			break;
1538 
1539 		default:
1540 			goto trans_err_not_supported;
1541 		}
1542 	}
1543 
1544 	switch (rc) {
1545 	case SDRC_SUCCESS:
1546 		break;
1547 
1548 	case SDRC_DROP_VC:
1549 	case SDRC_NO_REPLY:
1550 	case SDRC_ERROR:
1551 		return (rc);
1552 
1553 	case SDRC_NOT_IMPLEMENTED:
1554 		goto trans_err_not_supported;
1555 
1556 	default:
1557 		break;
1558 	}
1559 
1560 	n_setup = MBC_LENGTH(&xa->rep_setup_mb);
1561 	n_param = MBC_LENGTH(&xa->rep_param_mb);
1562 	n_data  = MBC_LENGTH(&xa->rep_data_mb);
1563 
1564 	if (xa->smb_msrcnt < n_setup ||
1565 	    xa->smb_mprcnt < n_param ||
1566 	    xa->smb_mdrcnt < n_data) {
1567 		goto trans_err_too_small;
1568 	}
1569 
1570 	/* neato, blast it over there */
1571 
1572 	n_setup = (n_setup + 1) / 2;		/* Convert to setup words */
1573 	param_pad = 1;				/* always one */
1574 	param_off = param_pad + 32 + 21 + (n_setup << 1) + 2;
1575 	data_pad = (param_off + n_param) & 1;	/* Pad to short */
1576 	/* Param off from hdr start */
1577 	data_off = param_off + n_param + data_pad;
1578 	total_bytes = param_pad + n_param + data_pad + n_data;
1579 
1580 	rc = smbsr_encode_result(sr, 10+n_setup, total_bytes,
1581 	    "bww2.wwwwwwb.Cw#.C#.C",
1582 	    10 + n_setup,		/* wct */
1583 	    n_param,			/* Total Parameter Bytes */
1584 	    n_data,			/* Total Data Bytes */
1585 	    n_param,			/* Total Parameter Bytes this buffer */
1586 	    param_off,			/* Param offset from header start */
1587 	    0,				/* Param displacement */
1588 	    n_data,			/* Total Data Bytes this buffer */
1589 	    data_off,			/* Data offset from header start */
1590 	    0,				/* Data displacement */
1591 	    n_setup,			/* suwcnt */
1592 	    &xa->rep_setup_mb, /* setup[] */
1593 	    total_bytes,		/* Total data bytes */
1594 	    param_pad,
1595 	    &xa->rep_param_mb,
1596 	    data_pad,
1597 	    &xa->rep_data_mb);
1598 	return ((rc == 0) ? SDRC_SUCCESS : SDRC_ERROR);
1599 
1600 trans_err_too_small:
1601 	rc = NERR_BufTooSmall;
1602 	goto trans_err;
1603 
1604 trans_err_not_supported:
1605 	rc = ERROR_NOT_SUPPORTED;
1606 	goto trans_err;
1607 
1608 trans_err:
1609 	pos = MBC_LENGTH(&sr->reply) + 23;
1610 	rc = smbsr_encode_result(sr, 10, 4, "bww2.wwwwwwb.www",
1611 	    10,		/* wct */
1612 	    4, 0,	/* tpscnt tdscnt */
1613 	    4, pos, 0,	/* pscnt psoff psdisp */
1614 	    0, 0, 0,	/* dscnt dsoff dsdisp */
1615 	    0,		/* suwcnt */
1616 	    4,		/* bcc */
1617 	    rc,
1618 	    0);		/* converter word? */
1619 	return ((rc == 0) ? SDRC_SUCCESS : SDRC_ERROR);
1620 }
1621 
1622 static smb_sdrc_t
1623 smb_trans2_dispatch(smb_request_t *sr, smb_xa_t *xa)
1624 {
1625 	int		rc, pos;
1626 	int		total_bytes, n_setup, n_param, n_data;
1627 	int		param_off, param_pad, data_off;
1628 	uint16_t	data_pad;
1629 	uint16_t	opcode;
1630 	uint16_t  nt_unknown_secret = 0x0100;
1631 	char *fmt;
1632 
1633 	n_data = xa->smb_mdrcnt;
1634 
1635 	if (smb_mbc_decodef(&xa->req_setup_mb, "w", &opcode) != 0)
1636 		goto trans_err_not_supported;
1637 
1638 	/*
1639 	 * Save this for /proc to read later.
1640 	 */
1641 	xa->smb_func = opcode;
1642 
1643 	/* for now, only respond to the */
1644 	switch (opcode) {
1645 	case TRANS2_OPEN2:
1646 		rc = smb_com_trans2_open2(sr, xa);
1647 		break;
1648 
1649 	case TRANS2_CREATE_DIRECTORY:
1650 		rc = smb_com_trans2_create_directory(sr, xa);
1651 		break;
1652 
1653 	case TRANS2_FIND_FIRST2:
1654 		/*
1655 		 * Should have enough room to send the response
1656 		 * data back to client.
1657 		 */
1658 		if (n_data == 0) {
1659 			smbsr_error(sr, NT_STATUS_INFO_LENGTH_MISMATCH,
1660 			    ERRDOS, ERROR_BAD_LENGTH);
1661 			return (SDRC_ERROR);
1662 		}
1663 		rc = smb_com_trans2_find_first2(sr, xa);
1664 		break;
1665 
1666 	case TRANS2_FIND_NEXT2:
1667 		/*
1668 		 * Should have enough room to send the response
1669 		 * data back to client.
1670 		 */
1671 		if (n_data == 0) {
1672 			smbsr_error(sr, NT_STATUS_INFO_LENGTH_MISMATCH,
1673 			    ERRDOS, ERROR_BAD_LENGTH);
1674 			return (SDRC_ERROR);
1675 		}
1676 		rc = smb_com_trans2_find_next2(sr, xa);
1677 		break;
1678 
1679 	case TRANS2_QUERY_FS_INFORMATION:
1680 		/*
1681 		 * Should have enough room to send the response
1682 		 * data back to client.
1683 		 */
1684 		if (n_data == 0) {
1685 			smbsr_error(sr, NT_STATUS_INFO_LENGTH_MISMATCH,
1686 			    ERRDOS, ERROR_BAD_LENGTH);
1687 			return (SDRC_ERROR);
1688 		}
1689 		rc = smb_com_trans2_query_fs_information(sr, xa);
1690 		break;
1691 
1692 	case TRANS2_SET_FS_INFORMATION:
1693 		rc = smb_com_trans2_set_fs_information(sr, xa);
1694 		break;
1695 
1696 	case TRANS2_QUERY_PATH_INFORMATION:
1697 		/*
1698 		 * Should have enough room to send the response
1699 		 * data back to client.
1700 		 */
1701 		if (n_data == 0) {
1702 			smbsr_error(sr, NT_STATUS_INFO_LENGTH_MISMATCH,
1703 			    ERRDOS, ERROR_BAD_LENGTH);
1704 			return (SDRC_ERROR);
1705 		}
1706 		rc = smb_com_trans2_query_path_information(sr, xa);
1707 		break;
1708 
1709 	case TRANS2_QUERY_FILE_INFORMATION:
1710 		/*
1711 		 * Should have enough room to send the response
1712 		 * data back to client.
1713 		 */
1714 		if (n_data == 0) {
1715 			smbsr_error(sr, NT_STATUS_INFO_LENGTH_MISMATCH,
1716 			    ERRDOS, ERROR_BAD_LENGTH);
1717 			return (SDRC_ERROR);
1718 		}
1719 		rc = smb_com_trans2_query_file_information(sr, xa);
1720 		break;
1721 
1722 	case TRANS2_SET_PATH_INFORMATION:
1723 		rc = smb_com_trans2_set_path_information(sr, xa);
1724 		break;
1725 
1726 	case TRANS2_SET_FILE_INFORMATION:
1727 		rc = smb_com_trans2_set_file_information(sr, xa);
1728 		break;
1729 
1730 	case TRANS2_GET_DFS_REFERRAL:
1731 		rc = smb_com_trans2_get_dfs_referral(sr, xa);
1732 		break;
1733 
1734 	default:
1735 		(void) smb_mbc_encodef(&xa->rep_param_mb, "w", 0);
1736 		goto trans_err_not_supported;
1737 	}
1738 
1739 	switch (rc) {
1740 	case SDRC_SUCCESS:
1741 		break;
1742 
1743 	case SDRC_DROP_VC:
1744 	case SDRC_NO_REPLY:
1745 	case SDRC_ERROR:
1746 		return (rc);
1747 
1748 	case SDRC_NOT_IMPLEMENTED:
1749 		goto trans_err_not_supported;
1750 
1751 	default:
1752 		break;
1753 	}
1754 
1755 	n_setup = MBC_LENGTH(&xa->rep_setup_mb);
1756 	n_param = MBC_LENGTH(&xa->rep_param_mb);
1757 	n_data  = MBC_LENGTH(&xa->rep_data_mb);
1758 
1759 	if (xa->smb_msrcnt < n_setup ||
1760 	    xa->smb_mprcnt < n_param ||
1761 	    xa->smb_mdrcnt < n_data) {
1762 		goto trans_err_too_small;
1763 	}
1764 
1765 	/* neato, blast it over there */
1766 
1767 	n_setup = (n_setup + 1) / 2;		/* Conver to setup words */
1768 	param_pad = 1;				/* must be one */
1769 	param_off = param_pad + 32 + 21 + (n_setup << 1) + 2;
1770 
1771 	/*
1772 	 * Including the nt_unknown_secret value persuades netmon to
1773 	 * display the correct data format for QueryPathInfo and
1774 	 * QueryFileInfo.
1775 	 */
1776 	if (opcode == TRANS2_QUERY_FILE_INFORMATION ||
1777 	    opcode == TRANS2_QUERY_PATH_INFORMATION) {
1778 		data_pad = sizeof (uint16_t);
1779 		data_off = param_off + n_param + data_pad;
1780 		fmt = "bww2.wwwwwwb.Cw#.CwC";
1781 		nt_unknown_secret = 0x0100;
1782 	}
1783 	else
1784 	{
1785 		data_pad = (param_off + n_param) & 1; /* Pad to short */
1786 		/* Param off from hdr start */
1787 		data_off = param_off + n_param + data_pad;
1788 		fmt = "bww2.wwwwwwb.Cw#.C#.C";
1789 		nt_unknown_secret = data_pad;
1790 	}
1791 
1792 	total_bytes = param_pad + n_param + data_pad + n_data;
1793 
1794 	rc = smbsr_encode_result(sr, 10+n_setup, total_bytes,
1795 	    fmt,
1796 	    10 + n_setup,		/* wct */
1797 	    n_param,			/* Total Parameter Bytes */
1798 	    n_data /* + data_pad */,	/* Total Data Bytes */
1799 	    n_param,			/* Total Parameter Bytes this buffer */
1800 	    param_off,			/* Param offset from header start */
1801 	    0,				/* Param displacement */
1802 	    n_data /* + data_pad */,	/* Total Data Bytes this buffer */
1803 	    data_off,			/* Data offset from header start */
1804 	    0,				/* Data displacement */
1805 	    n_setup,			/* suwcnt */
1806 	    &xa->rep_setup_mb,		/* setup[] */
1807 	    total_bytes,		/* Total data bytes */
1808 	    param_pad,
1809 	    &xa->rep_param_mb,
1810 	    nt_unknown_secret,
1811 	    &xa->rep_data_mb);
1812 	return ((rc == 0) ? SDRC_SUCCESS : SDRC_ERROR);
1813 
1814 trans_err_too_small:
1815 	rc = NERR_BufTooSmall;
1816 	goto trans_err;
1817 
1818 trans_err_not_supported:
1819 	rc = ERROR_NOT_SUPPORTED;
1820 	goto trans_err;
1821 
1822 trans_err:
1823 	pos = MBC_LENGTH(&sr->reply) + 23;
1824 	rc = smbsr_encode_result(sr, 10, 4, "bww2.wwwwwwb.www",
1825 	    10,		/* wct */
1826 	    4, 0,	/* tpscnt tdscnt */
1827 	    4, pos, 0,	/* pscnt psoff psdisp */
1828 	    0, 0, 0,	/* dscnt dsoff dsdisp */
1829 	    0,		/* suwcnt */
1830 	    4,		/* bcc */
1831 	    rc,
1832 	    0);		/* converter word? */
1833 	return ((rc == 0) ? SDRC_SUCCESS : SDRC_ERROR);
1834 }
1835 
1836 static uint32_t smb_xa_max_setup_count = 200;
1837 static uint32_t smb_xa_max_param_count = 32 * 1024;
1838 static uint32_t smb_xa_max_data_count  = 64 * 1024;
1839 
1840 smb_xa_t *
1841 smb_xa_create(
1842     smb_session_t	*session,
1843     smb_request_t	*sr,
1844     uint32_t		total_parameter_count,
1845     uint32_t		total_data_count,
1846     uint32_t		max_parameter_count,
1847     uint32_t		max_data_count,
1848     uint32_t		max_setup_count,
1849     uint32_t		setup_word_count)
1850 {
1851 	smb_xa_t	*xa, *nxa;
1852 	smb_llist_t	*xlist;
1853 
1854 	/*
1855 	 * Sanity check what the client says it will send.
1856 	 * Caller handles NULL return as ERRnoroom.
1857 	 */
1858 	if (setup_word_count > smb_xa_max_setup_count)
1859 		return (NULL);
1860 	if (total_parameter_count > smb_xa_max_param_count)
1861 		return (NULL);
1862 	if (total_data_count > smb_xa_max_data_count)
1863 		return (NULL);
1864 
1865 	/*
1866 	 * Limit what the client asks us to allocate for
1867 	 * returned setup, params, data.
1868 	 */
1869 	if (max_setup_count > smb_xa_max_setup_count)
1870 		max_setup_count = smb_xa_max_setup_count;
1871 	if (max_parameter_count > smb_xa_max_param_count)
1872 		max_parameter_count = smb_xa_max_param_count;
1873 	if (max_data_count > smb_xa_max_data_count)
1874 		max_data_count = smb_xa_max_data_count;
1875 
1876 	xa = kmem_zalloc(sizeof (smb_xa_t), KM_SLEEP);
1877 	xa->xa_refcnt = 1;
1878 	xa->smb_com = sr->smb_com;
1879 	xa->smb_flg = sr->smb_flg;
1880 	xa->smb_flg2 = sr->smb_flg2;
1881 	xa->smb_tid = sr->smb_tid;
1882 	xa->smb_pid = sr->smb_pid;
1883 	xa->smb_uid = sr->smb_uid;
1884 	xa->xa_smb_mid = sr->smb_mid;
1885 	xa->xa_smb_fid = 0xFFFF;
1886 	xa->reply_seqnum = sr->reply_seqnum;
1887 	xa->smb_tpscnt = total_parameter_count;
1888 	xa->smb_tdscnt = total_data_count;
1889 	xa->smb_mprcnt = max_parameter_count;
1890 	xa->smb_mdrcnt = max_data_count;
1891 	xa->smb_msrcnt = max_setup_count;
1892 	xa->smb_suwcnt = setup_word_count;
1893 	xa->xa_session = session;
1894 	xa->xa_magic = SMB_XA_MAGIC;
1895 
1896 	/* request parts */
1897 	xa->req_setup_mb.max_bytes = setup_word_count * 2;
1898 	xa->req_param_mb.max_bytes = total_parameter_count;
1899 	xa->req_data_mb.max_bytes  = total_data_count;
1900 
1901 	/* reply parts */
1902 	xa->rep_setup_mb.max_bytes = max_setup_count * 2;
1903 	xa->rep_param_mb.max_bytes = max_parameter_count;
1904 	xa->rep_data_mb.max_bytes =  max_data_count;
1905 
1906 	/*
1907 	 * The new xa structure is checked against the current list to see
1908 	 * if it exists already.
1909 	 */
1910 	xlist = &session->s_xa_list;
1911 	smb_llist_enter(xlist, RW_WRITER);
1912 	nxa = smb_llist_head(xlist);
1913 	while (nxa) {
1914 		ASSERT(nxa->xa_magic == SMB_XA_MAGIC);
1915 		if (nxa->xa_smb_mid == xa->xa_smb_mid &&
1916 		    nxa->smb_pid == xa->smb_pid &&
1917 		    !SMB_XA_CLOSED(nxa) &&
1918 		    !(nxa->xa_flags & SMB_XA_FLAG_COMPLETE)) {
1919 			smb_llist_exit(xlist);
1920 			kmem_free(xa, sizeof (smb_xa_t));
1921 			return (NULL);
1922 		}
1923 		nxa = smb_llist_next(xlist, nxa);
1924 	}
1925 	smb_llist_insert_tail(xlist, xa);
1926 	smb_llist_exit(xlist);
1927 	return (xa);
1928 }
1929 
1930 void
1931 smb_xa_delete(smb_xa_t *xa)
1932 {
1933 	ASSERT(xa->xa_refcnt == 0);
1934 	ASSERT(SMB_XA_CLOSED(xa));
1935 
1936 	if (xa->xa_pipe_name)
1937 		smb_mem_free(xa->xa_pipe_name);
1938 
1939 	/* request parts */
1940 	if (xa->req_setup_mb.chain != NULL)
1941 		m_freem(xa->req_setup_mb.chain);
1942 	if (xa->req_param_mb.chain != NULL)
1943 		m_freem(xa->req_param_mb.chain);
1944 	if (xa->req_data_mb.chain != NULL)
1945 		m_freem(xa->req_data_mb.chain);
1946 
1947 	/* reply parts */
1948 	if (xa->rep_setup_mb.chain != NULL)
1949 		m_freem(xa->rep_setup_mb.chain);
1950 	if (xa->rep_param_mb.chain != NULL)
1951 		m_freem(xa->rep_param_mb.chain);
1952 	if (xa->rep_data_mb.chain != NULL)
1953 		m_freem(xa->rep_data_mb.chain);
1954 
1955 	xa->xa_magic = (uint32_t)~SMB_XA_MAGIC;
1956 	kmem_free(xa, sizeof (smb_xa_t));
1957 }
1958 
1959 smb_xa_t *
1960 smb_xa_hold(smb_xa_t *xa)
1961 {
1962 	mutex_enter(&xa->xa_mutex);
1963 	xa->xa_refcnt++;
1964 	ASSERT(xa->xa_refcnt);
1965 	mutex_exit(&xa->xa_mutex);
1966 	return (xa);
1967 }
1968 
1969 void
1970 smb_xa_rele(smb_session_t *session, smb_xa_t *xa)
1971 {
1972 	mutex_enter(&xa->xa_mutex);
1973 	ASSERT(xa->xa_refcnt);
1974 	xa->xa_refcnt--;
1975 	if (SMB_XA_CLOSED(xa) && (xa->xa_refcnt == 0)) {
1976 		mutex_exit(&xa->xa_mutex);
1977 		smb_llist_enter(&session->s_xa_list, RW_WRITER);
1978 		smb_llist_remove(&session->s_xa_list, xa);
1979 		smb_llist_exit(&session->s_xa_list);
1980 		smb_xa_delete(xa);
1981 		return;
1982 	}
1983 	mutex_exit(&xa->xa_mutex);
1984 }
1985 
1986 int
1987 smb_xa_open(smb_xa_t *xa)
1988 {
1989 	int rc;
1990 
1991 	mutex_enter(&xa->xa_mutex);
1992 
1993 	ASSERT((xa->xa_flags & SMB_XA_FLAG_OPEN) == 0);
1994 
1995 	if ((xa->xa_flags & SMB_XA_FLAG_CLOSE) == 0) {
1996 		xa->xa_flags |= SMB_XA_FLAG_OPEN;
1997 		rc = 0;
1998 	} else {
1999 		rc = ERROR_INVALID_HANDLE;
2000 	}
2001 
2002 	mutex_exit(&xa->xa_mutex);
2003 
2004 	return (rc);
2005 }
2006 
2007 void
2008 smb_xa_close(smb_xa_t *xa)
2009 {
2010 	mutex_enter(&xa->xa_mutex);
2011 	xa->xa_flags |= SMB_XA_FLAG_CLOSE;
2012 	xa->xa_flags &= ~SMB_XA_FLAG_OPEN;
2013 
2014 	if (xa->xa_refcnt == 0) {
2015 		mutex_exit(&xa->xa_mutex);
2016 		smb_llist_enter(&xa->xa_session->s_xa_list, RW_WRITER);
2017 		smb_llist_remove(&xa->xa_session->s_xa_list, xa);
2018 		smb_llist_exit(&xa->xa_session->s_xa_list);
2019 		smb_xa_delete(xa);
2020 		return;
2021 	}
2022 
2023 	mutex_exit(&xa->xa_mutex);
2024 }
2025 
2026 int
2027 smb_xa_complete(smb_xa_t *xa)
2028 {
2029 	int rc;
2030 
2031 	mutex_enter(&xa->xa_mutex);
2032 	if (xa->xa_flags & (SMB_XA_FLAG_COMPLETE | SMB_XA_FLAG_CLOSE)) {
2033 		rc = 0; /* error ("not complete") */
2034 	} else {
2035 		rc = 1; /* Yes, "complete" */
2036 		xa->xa_flags |= SMB_XA_FLAG_COMPLETE;
2037 
2038 		/*
2039 		 * During trans & trans-secondary processing,
2040 		 * we copied the request data into these.
2041 		 * Now we want to parse them, so we need to
2042 		 * move the "finger" back to the beginning.
2043 		 */
2044 		xa->req_setup_mb.chain_offset = 0;
2045 		xa->req_param_mb.chain_offset = 0;
2046 		xa->req_data_mb.chain_offset  = 0;
2047 	}
2048 
2049 	mutex_exit(&xa->xa_mutex);
2050 	return (rc);
2051 }
2052 
2053 smb_xa_t *
2054 smb_xa_find(
2055     smb_session_t	*session,
2056     uint32_t		pid,
2057     uint16_t		mid)
2058 {
2059 	smb_xa_t	*xa;
2060 	smb_llist_t	*xlist;
2061 
2062 	xlist = &session->s_xa_list;
2063 	smb_llist_enter(xlist, RW_READER);
2064 	xa = smb_llist_head(xlist);
2065 	while (xa) {
2066 		mutex_enter(&xa->xa_mutex);
2067 		if (xa->xa_smb_mid == mid &&
2068 		    xa->smb_pid == pid &&
2069 		    !SMB_XA_CLOSED(xa) &&
2070 		    !(xa->xa_flags & SMB_XA_FLAG_COMPLETE)) {
2071 			xa->xa_refcnt++;
2072 			ASSERT(xa->xa_refcnt);
2073 			mutex_exit(&xa->xa_mutex);
2074 			break;
2075 		}
2076 		mutex_exit(&xa->xa_mutex);
2077 		xa = smb_llist_next(xlist, xa);
2078 	}
2079 	smb_llist_exit(xlist);
2080 	return (xa);
2081 }
2082