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