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