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