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