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