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