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