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