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