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