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