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