xref: /illumos-gate/usr/src/uts/common/fs/smbsrv/smb_common_transact.c (revision bce01b59de50fe66a0267f4aa23e1d6e60d973d9)
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  */
21148c5f43SAlan Wright 
22da6c28aaSamw /*
23c5866007SKeyur Desai  * Copyright (c) 2007, 2010, Oracle and/or its affiliates. All rights reserved.
2468b2bbf2SGordon Ross  * Copyright 2014 Nexenta Systems, Inc.  All rights reserved.
25da6c28aaSamw  */
26da6c28aaSamw 
27bbf6f00cSJordan Brown #include <smbsrv/smb_kproto.h>
28da6c28aaSamw #include <smbsrv/smb_fsops.h>
293db3f65cSamw #include <smbsrv/smb_share.h>
30bbf6f00cSJordan Brown #include <smbsrv/string.h>
31da6c28aaSamw #include <smbsrv/nmpipes.h>
32da6c28aaSamw #include <smbsrv/mailslot.h>
33da6c28aaSamw 
34da6c28aaSamw /*
35da6c28aaSamw  * count of bytes in server response packet
36da6c28aaSamw  * except parameters and data. Note that setup
37da6c28aaSamw  * word count is zero.
38da6c28aaSamw  */
39da6c28aaSamw #define	RESP_HEADER_LEN		24
40da6c28aaSamw 
41da6c28aaSamw /*
42b1352070SAlan Wright  * We started by using common functions for transaction/transaction2
43da6c28aaSamw  * and transaction_secondary/transaction2_secondary because they
44da6c28aaSamw  * are respectively so similar. However, it turned out to be a bad
45da6c28aaSamw  * idea because of quirky differences. Be sure if you modify one
46da6c28aaSamw  * of these four functions to check and see if the modification should
47da6c28aaSamw  * be applied to its peer.
48da6c28aaSamw  */
49da6c28aaSamw 
509fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States static int smb_trans_ready(smb_xa_t *);
519fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States static smb_sdrc_t smb_trans_dispatch(smb_request_t *, smb_xa_t *);
529fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States static smb_sdrc_t smb_trans2_dispatch(smb_request_t *, smb_xa_t *);
53da6c28aaSamw 
547b59d02dSjb150015 smb_sdrc_t
55faa1795aSjb150015 smb_pre_transaction(smb_request_t *sr)
56faa1795aSjb150015 {
57faa1795aSjb150015 	DTRACE_SMB_1(op__Transaction__start, smb_request_t *, sr);
58faa1795aSjb150015 	return (SDRC_SUCCESS);
59faa1795aSjb150015 }
60faa1795aSjb150015 
61faa1795aSjb150015 void
62faa1795aSjb150015 smb_post_transaction(smb_request_t *sr)
63faa1795aSjb150015 {
64faa1795aSjb150015 	DTRACE_SMB_1(op__Transaction__done, smb_request_t *, sr);
65faa1795aSjb150015 }
66faa1795aSjb150015 
67faa1795aSjb150015 smb_sdrc_t
68faa1795aSjb150015 smb_com_transaction(smb_request_t *sr)
69da6c28aaSamw {
70da6c28aaSamw 	int		rc;
71da6c28aaSamw 	unsigned char	msrcnt, suwcnt;
72da6c28aaSamw 	uint16_t	tpscnt, tdscnt, mprcnt, mdrcnt, flags;
73da6c28aaSamw 	uint16_t	pscnt, psoff, dscnt, dsoff;
74da6c28aaSamw 	uint32_t	timeo;
75da6c28aaSamw 	struct smb_xa *xa;
76da6c28aaSamw 	char *stn;
77da6c28aaSamw 	int ready;
78da6c28aaSamw 
79da6c28aaSamw 	rc = smbsr_decode_vwv(sr, SMB_TRANSHDR_ED_FMT,
80da6c28aaSamw 	    &tpscnt, &tdscnt, &mprcnt, &mdrcnt, &msrcnt, &flags,
81da6c28aaSamw 	    &timeo, &pscnt, &psoff, &dscnt, &dsoff, &suwcnt);
82da6c28aaSamw 
837b59d02dSjb150015 	if (rc != 0)
84faa1795aSjb150015 		return (SDRC_ERROR);
85da6c28aaSamw 
86da6c28aaSamw 	xa = smb_xa_create(sr->session, sr, tpscnt, tdscnt, mprcnt, mdrcnt,
87da6c28aaSamw 	    msrcnt, suwcnt);
88da6c28aaSamw 	if (xa == NULL) {
89dc20a302Sas200622 		smbsr_error(sr, 0, ERRSRV, ERRnoroom);
90faa1795aSjb150015 		return (SDRC_ERROR);
91da6c28aaSamw 	}
92da6c28aaSamw 
93da6c28aaSamw 	/* Should be some alignment stuff here in SMB? */
94da6c28aaSamw 	if (sr->smb_flg2 & SMB_FLAGS2_UNICODE) {
95da6c28aaSamw 		rc = smbsr_decode_data(sr, "%.U", sr, &stn);
96da6c28aaSamw 	} else {
97da6c28aaSamw 		rc = smbsr_decode_data(sr, "%s", sr,  &stn);
98da6c28aaSamw 	}
99da6c28aaSamw 	if (rc != 0) {
100da6c28aaSamw 		smb_xa_rele(sr->session, xa);
101faa1795aSjb150015 		return (SDRC_ERROR);
102da6c28aaSamw 	}
103da6c28aaSamw 
1049fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States 	xa->xa_pipe_name = smb_mem_strdup(stn);
105da6c28aaSamw 	xa->smb_flags  = flags;
106da6c28aaSamw 	xa->smb_timeout = timeo;
107da6c28aaSamw 	xa->req_disp_param = pscnt;
108da6c28aaSamw 	xa->req_disp_data  = dscnt;
109da6c28aaSamw 
1107f3ef643SGordon Ross 	if (smb_mbc_copy(&xa->req_setup_mb, &sr->smb_vwv,
111da6c28aaSamw 	    sr->smb_vwv.chain_offset, suwcnt * 2)) {
112da6c28aaSamw 		smb_xa_rele(sr->session, xa);
113dc20a302Sas200622 		smbsr_error(sr, 0, ERRDOS, ERRbadformat);
114faa1795aSjb150015 		return (SDRC_ERROR);
115da6c28aaSamw 	}
1167f3ef643SGordon Ross 	if (smb_mbc_copy(&xa->req_param_mb, &sr->command, psoff, pscnt)) {
117da6c28aaSamw 		smb_xa_rele(sr->session, xa);
118dc20a302Sas200622 		smbsr_error(sr, 0, ERRDOS, ERRbadformat);
119faa1795aSjb150015 		return (SDRC_ERROR);
120da6c28aaSamw 	}
1217f3ef643SGordon Ross 	if (smb_mbc_copy(&xa->req_data_mb, &sr->command, dsoff, dscnt)) {
122da6c28aaSamw 		smb_xa_rele(sr->session, xa);
123dc20a302Sas200622 		smbsr_error(sr, 0, ERRDOS, ERRbadformat);
124faa1795aSjb150015 		return (SDRC_ERROR);
125da6c28aaSamw 	}
126da6c28aaSamw 
127da6c28aaSamw 	ready = smb_trans_ready(xa);
128da6c28aaSamw 
129da6c28aaSamw 	if (smb_xa_open(xa)) {
130da6c28aaSamw 		smb_xa_rele(sr->session, xa);
131ccc71be5SGordon Ross 		smbsr_error(sr, 0, ERRSRV, ERRsrverror);
132faa1795aSjb150015 		return (SDRC_ERROR);
133da6c28aaSamw 	}
134da6c28aaSamw 	sr->r_xa = xa;
135da6c28aaSamw 
136da6c28aaSamw 	if (!ready) {
1377b59d02dSjb150015 		rc = smbsr_encode_empty_result(sr);
138faa1795aSjb150015 		return ((rc == 0) ? SDRC_SUCCESS : SDRC_ERROR);
139da6c28aaSamw 	}
140da6c28aaSamw 
141da6c28aaSamw 	if (!smb_xa_complete(xa)) {
142da6c28aaSamw 		smb_xa_close(xa);
143dc20a302Sas200622 		smbsr_error(sr, 0, ERRDOS, ERRbadformat);
144faa1795aSjb150015 		return (SDRC_ERROR);
145da6c28aaSamw 	}
146da6c28aaSamw 
147da6c28aaSamw 	return (smb_trans_dispatch(sr, xa));
148da6c28aaSamw }
149da6c28aaSamw 
1507b59d02dSjb150015 smb_sdrc_t
151faa1795aSjb150015 smb_pre_transaction_secondary(smb_request_t *sr)
152faa1795aSjb150015 {
153faa1795aSjb150015 	DTRACE_SMB_1(op__TransactionSecondary__start, smb_request_t *, sr);
154faa1795aSjb150015 	return (SDRC_SUCCESS);
155faa1795aSjb150015 }
156faa1795aSjb150015 
157faa1795aSjb150015 void
158faa1795aSjb150015 smb_post_transaction_secondary(smb_request_t *sr)
159faa1795aSjb150015 {
160faa1795aSjb150015 	DTRACE_SMB_1(op__TransactionSecondary__done, smb_request_t *, sr);
161faa1795aSjb150015 }
162faa1795aSjb150015 
163faa1795aSjb150015 smb_sdrc_t
164faa1795aSjb150015 smb_com_transaction_secondary(smb_request_t *sr)
165da6c28aaSamw {
166da6c28aaSamw 	uint16_t tpscnt, tdscnt, pscnt, psdisp;
167da6c28aaSamw 	uint16_t dscnt, dsoff, dsdisp, psoff;
168da6c28aaSamw 	smb_xa_t *xa;
169da6c28aaSamw 	int rc;
170da6c28aaSamw 
171da6c28aaSamw 	if ((xa = smbsr_lookup_xa(sr)) == 0) {
172dc20a302Sas200622 		smbsr_error(sr, 0, ERRSRV, ERRsrverror);
173faa1795aSjb150015 		return (SDRC_ERROR);
174da6c28aaSamw 	}
175da6c28aaSamw 
176da6c28aaSamw 	if (sr->session->signing.flags & SMB_SIGNING_ENABLED) {
177da6c28aaSamw 		if (smb_sign_check_secondary(sr, xa->reply_seqnum) != 0) {
178dc20a302Sas200622 			smbsr_error(sr, NT_STATUS_ACCESS_DENIED,
179da6c28aaSamw 			    ERRDOS, ERRnoaccess);
180faa1795aSjb150015 			return (SDRC_ERROR);
181da6c28aaSamw 		}
182da6c28aaSamw 	}
183da6c28aaSamw 
184da6c28aaSamw 	if (xa->smb_com != SMB_COM_TRANSACTION) {
185da6c28aaSamw 		return (SDRC_DROP_VC);
186da6c28aaSamw 	}
187da6c28aaSamw 
188da6c28aaSamw 	rc = smbsr_decode_vwv(sr, SMB_TRANSSHDR_ED_FMT, &tpscnt, &tdscnt,
189da6c28aaSamw 	    &pscnt, &psoff, &psdisp, &dscnt, &dsoff, &dsdisp);
190da6c28aaSamw 
1917b59d02dSjb150015 	if (rc != 0)
192faa1795aSjb150015 		return (SDRC_ERROR);
193da6c28aaSamw 
194da6c28aaSamw 	mutex_enter(&xa->xa_mutex);
1957f3ef643SGordon Ross 	if (xa->smb_tpscnt > tpscnt)
1967f3ef643SGordon Ross 		xa->smb_tpscnt = tpscnt;
1977f3ef643SGordon Ross 	if (xa->smb_tdscnt > tdscnt)
1987f3ef643SGordon Ross 		xa->smb_tdscnt = tdscnt;
199da6c28aaSamw 	xa->req_disp_param = psdisp + pscnt;
200da6c28aaSamw 	xa->req_disp_data  = dsdisp + dscnt;
201da6c28aaSamw 
2027f3ef643SGordon Ross 	/*
2037f3ef643SGordon Ross 	 * The words psdisp, dsdisp, tell us what displacement
2047f3ef643SGordon Ross 	 * into the entire trans parameter and data buffers
2057f3ef643SGordon Ross 	 * where we should put the params & data that are
2067f3ef643SGordon Ross 	 * delivered by this request.  [MS-CIFS] says all the
2077f3ef643SGordon Ross 	 * parameters and data SHOULD be sent sequentially, so
2087f3ef643SGordon Ross 	 * so we can normally reassemble by simply appending.
2097f3ef643SGordon Ross 	 * However, the components MAY come out of order, so
2107f3ef643SGordon Ross 	 * check and set the current offset.  This is rare,
2117f3ef643SGordon Ross 	 * and we might like to know when this happens, so
2127f3ef643SGordon Ross 	 * fire some static dtrace probes when it does.
2137f3ef643SGordon Ross 	 */
2147f3ef643SGordon Ross 	if (xa->req_param_mb.chain_offset != psdisp) {
2157f3ef643SGordon Ross 		DTRACE_PROBE2(trans_param_disp,
2167f3ef643SGordon Ross 		    smb_xa_t *, xa, uint16_t, psdisp);
2177f3ef643SGordon Ross 		xa->req_param_mb.chain_offset = psdisp;
2187f3ef643SGordon Ross 	}
2197f3ef643SGordon Ross 	if (xa->req_data_mb.chain_offset != dsdisp) {
2207f3ef643SGordon Ross 		DTRACE_PROBE2(trans_data_disp,
2217f3ef643SGordon Ross 		    smb_xa_t *, xa, uint16_t, dsdisp);
2227f3ef643SGordon Ross 		xa->req_data_mb.chain_offset = dsdisp;
2237f3ef643SGordon Ross 	}
2247f3ef643SGordon Ross 
2257f3ef643SGordon Ross 	if (smb_mbc_copy(&xa->req_param_mb, &sr->command, psoff, pscnt)) {
226da6c28aaSamw 		mutex_exit(&xa->xa_mutex);
227da6c28aaSamw 		smb_xa_close(xa);
228dc20a302Sas200622 		smbsr_error(sr, 0, ERRDOS, ERRbadformat);
229faa1795aSjb150015 		return (SDRC_ERROR);
230da6c28aaSamw 	}
2317f3ef643SGordon Ross 	if (smb_mbc_copy(&xa->req_data_mb, &sr->command, dsoff, dscnt)) {
232da6c28aaSamw 		mutex_exit(&xa->xa_mutex);
233da6c28aaSamw 		smb_xa_close(xa);
234dc20a302Sas200622 		smbsr_error(sr, 0, ERRDOS, ERRbadformat);
235faa1795aSjb150015 		return (SDRC_ERROR);
236da6c28aaSamw 	}
237da6c28aaSamw 	mutex_exit(&xa->xa_mutex);
238da6c28aaSamw 
239da6c28aaSamw 	if (!smb_trans_ready(xa))
240da6c28aaSamw 		return (SDRC_NO_REPLY);
241da6c28aaSamw 
242da6c28aaSamw 	if (!smb_xa_complete(xa))
243da6c28aaSamw 		return (SDRC_NO_REPLY);
244da6c28aaSamw 
245da6c28aaSamw 	return (smb_trans_dispatch(sr, xa));
246da6c28aaSamw }
247da6c28aaSamw 
2487b59d02dSjb150015 smb_sdrc_t
249faa1795aSjb150015 smb_pre_ioctl(smb_request_t *sr)
250faa1795aSjb150015 {
251faa1795aSjb150015 	DTRACE_SMB_1(op__Ioctl__start, smb_request_t *, sr);
252faa1795aSjb150015 	return (SDRC_SUCCESS);
253faa1795aSjb150015 }
254faa1795aSjb150015 
255faa1795aSjb150015 void
256faa1795aSjb150015 smb_post_ioctl(smb_request_t *sr)
257faa1795aSjb150015 {
258faa1795aSjb150015 	DTRACE_SMB_1(op__Ioctl__done, smb_request_t *, sr);
259faa1795aSjb150015 }
260faa1795aSjb150015 
261faa1795aSjb150015 smb_sdrc_t
262faa1795aSjb150015 smb_com_ioctl(smb_request_t *sr)
263da6c28aaSamw {
264da6c28aaSamw 	uint16_t fid, category, function, tpscnt, tdscnt, mprcnt;
265da6c28aaSamw 	uint16_t mdrcnt, pscnt, pdoff, dscnt, dsoff;
266da6c28aaSamw 	uint32_t timeout;
267da6c28aaSamw 	int rc;
268da6c28aaSamw 
269da6c28aaSamw 	rc = smbsr_decode_vwv(sr, "wwwwwwwl2.wwww", &fid, &category, &function,
270da6c28aaSamw 	    &tpscnt, &tdscnt, &mprcnt, &mdrcnt, &timeout, &pscnt,
271da6c28aaSamw 	    &pdoff, &dscnt, &dsoff);
272da6c28aaSamw 
2737b59d02dSjb150015 	if (rc != 0)
274faa1795aSjb150015 		return (SDRC_ERROR);
275da6c28aaSamw 
276faa1795aSjb150015 	return (SDRC_NOT_IMPLEMENTED);
277da6c28aaSamw }
278da6c28aaSamw 
279faa1795aSjb150015 smb_sdrc_t
280faa1795aSjb150015 smb_pre_transaction2(smb_request_t *sr)
281da6c28aaSamw {
282faa1795aSjb150015 	DTRACE_SMB_1(op__Transaction2__start, smb_request_t *, sr);
283faa1795aSjb150015 	return (SDRC_SUCCESS);
284faa1795aSjb150015 }
285faa1795aSjb150015 
286faa1795aSjb150015 void
287faa1795aSjb150015 smb_post_transaction2(smb_request_t *sr)
288faa1795aSjb150015 {
289faa1795aSjb150015 	DTRACE_SMB_1(op__Transaction2__done, smb_request_t *, sr);
290da6c28aaSamw }
291da6c28aaSamw 
2927b59d02dSjb150015 smb_sdrc_t
293da6c28aaSamw smb_com_transaction2(struct smb_request *sr)
294da6c28aaSamw {
295da6c28aaSamw 	unsigned char	msrcnt, suwcnt;
296da6c28aaSamw 	uint16_t	tpscnt, tdscnt, mprcnt, mdrcnt, flags;
297da6c28aaSamw 	uint16_t	pscnt, psoff, dscnt, dsoff;
298da6c28aaSamw 	uint32_t	timeo;
299da6c28aaSamw 	smb_xa_t *xa;
300da6c28aaSamw 	int ready;
301da6c28aaSamw 	int rc;
302da6c28aaSamw 
303da6c28aaSamw 	rc = smbsr_decode_vwv(sr, SMB_TRANSHDR_ED_FMT, &tpscnt, &tdscnt,
304da6c28aaSamw 	    &mprcnt, &mdrcnt, &msrcnt, &flags, &timeo, &pscnt, &psoff, &dscnt,
305da6c28aaSamw 	    &dsoff, &suwcnt);
306da6c28aaSamw 
3077b59d02dSjb150015 	if (rc != 0)
308faa1795aSjb150015 		return (SDRC_ERROR);
309da6c28aaSamw 
310da6c28aaSamw 	xa = smb_xa_create(sr->session, sr, tpscnt, tdscnt, mprcnt, mdrcnt,
311da6c28aaSamw 	    msrcnt, suwcnt);
312da6c28aaSamw 	if (xa == 0) {
313dc20a302Sas200622 		smbsr_error(sr, 0, ERRSRV, ERRnoroom);
314faa1795aSjb150015 		return (SDRC_ERROR);
315da6c28aaSamw 	}
316da6c28aaSamw 
317da6c28aaSamw 	xa->smb_flags  = flags;
318da6c28aaSamw 	xa->smb_timeout = timeo;
319da6c28aaSamw 	xa->req_disp_param = pscnt;
320da6c28aaSamw 	xa->req_disp_data  = dscnt;
321da6c28aaSamw 
3227f3ef643SGordon Ross 	if (smb_mbc_copy(&xa->req_setup_mb, &sr->smb_vwv,
323da6c28aaSamw 	    sr->smb_vwv.chain_offset, suwcnt*2)) {
324da6c28aaSamw 		smb_xa_rele(sr->session, xa);
325dc20a302Sas200622 		smbsr_error(sr, 0, ERRDOS, ERRbadformat);
326faa1795aSjb150015 		return (SDRC_ERROR);
327da6c28aaSamw 	}
3287f3ef643SGordon Ross 	if (smb_mbc_copy(&xa->req_param_mb, &sr->command, psoff, pscnt)) {
329da6c28aaSamw 		smb_xa_rele(sr->session, xa);
330dc20a302Sas200622 		smbsr_error(sr, 0, ERRDOS, ERRbadformat);
331faa1795aSjb150015 		return (SDRC_ERROR);
332da6c28aaSamw 	}
3337f3ef643SGordon Ross 	if (smb_mbc_copy(&xa->req_data_mb, &sr->command, dsoff, dscnt)) {
334da6c28aaSamw 		smb_xa_rele(sr->session, xa);
335dc20a302Sas200622 		smbsr_error(sr, 0, ERRDOS, ERRbadformat);
336faa1795aSjb150015 		return (SDRC_ERROR);
337da6c28aaSamw 	}
338da6c28aaSamw 
339da6c28aaSamw 	ready = smb_trans_ready(xa);
340da6c28aaSamw 
341da6c28aaSamw 	if (smb_xa_open(xa)) {
342da6c28aaSamw 		smb_xa_rele(sr->session, xa);
343ccc71be5SGordon Ross 		smbsr_error(sr, 0, ERRSRV, ERRsrverror);
344faa1795aSjb150015 		return (SDRC_ERROR);
345da6c28aaSamw 	}
346da6c28aaSamw 	sr->r_xa = xa;
347da6c28aaSamw 
348da6c28aaSamw 	if (!ready) {
3497b59d02dSjb150015 		rc = smbsr_encode_empty_result(sr);
350faa1795aSjb150015 		return ((rc == 0) ? SDRC_SUCCESS : SDRC_ERROR);
351da6c28aaSamw 	}
352da6c28aaSamw 
353da6c28aaSamw 	if (!smb_xa_complete(xa)) {
354da6c28aaSamw 		smb_xa_close(xa);
355dc20a302Sas200622 		smbsr_error(sr, 0, ERRDOS, ERRbadformat);
356faa1795aSjb150015 		return (SDRC_ERROR);
357da6c28aaSamw 	}
358da6c28aaSamw 
359da6c28aaSamw 	return (smb_trans2_dispatch(sr, xa));
360da6c28aaSamw }
361da6c28aaSamw 
3627b59d02dSjb150015 smb_sdrc_t
363faa1795aSjb150015 smb_pre_transaction2_secondary(smb_request_t *sr)
364faa1795aSjb150015 {
365faa1795aSjb150015 	DTRACE_SMB_1(op__Transaction2Secondary__start, smb_request_t *, sr);
366faa1795aSjb150015 	return (SDRC_SUCCESS);
367faa1795aSjb150015 }
368faa1795aSjb150015 
369faa1795aSjb150015 void
370faa1795aSjb150015 smb_post_transaction2_secondary(smb_request_t *sr)
371faa1795aSjb150015 {
372faa1795aSjb150015 	DTRACE_SMB_1(op__Transaction2Secondary__done, smb_request_t *, sr);
373faa1795aSjb150015 }
374faa1795aSjb150015 
375faa1795aSjb150015 smb_sdrc_t
376faa1795aSjb150015 smb_com_transaction2_secondary(smb_request_t *sr)
377da6c28aaSamw {
378da6c28aaSamw 	uint16_t tpscnt, tdscnt, fid;
379da6c28aaSamw 	uint16_t pscnt, psoff, psdisp, dscnt, dsoff, dsdisp;
380da6c28aaSamw 	smb_xa_t *xa;
381da6c28aaSamw 	int rc;
382da6c28aaSamw 
383da6c28aaSamw 	if ((xa = smbsr_lookup_xa(sr)) == 0) {
384dc20a302Sas200622 		smbsr_error(sr, 0, ERRSRV, ERRsrverror);
385faa1795aSjb150015 		return (SDRC_ERROR);
386da6c28aaSamw 	}
387da6c28aaSamw 
388da6c28aaSamw 	if (sr->session->signing.flags & SMB_SIGNING_ENABLED) {
389da6c28aaSamw 		if (smb_sign_check_secondary(sr, xa->reply_seqnum) != 0) {
390dc20a302Sas200622 			smbsr_error(sr, NT_STATUS_ACCESS_DENIED,
391da6c28aaSamw 			    ERRDOS, ERRnoaccess);
392faa1795aSjb150015 			return (SDRC_ERROR);
393da6c28aaSamw 		}
394da6c28aaSamw 	}
395da6c28aaSamw 
396da6c28aaSamw 	if (xa->smb_com != SMB_COM_TRANSACTION2) {
397da6c28aaSamw 		return (SDRC_DROP_VC);
398da6c28aaSamw 	}
399da6c28aaSamw 
400da6c28aaSamw 	rc = smbsr_decode_vwv(sr, SMB_TRANS2SHDR_ED_FMT, &tpscnt, &tdscnt,
401da6c28aaSamw 	    &pscnt, &psoff, &psdisp, &dscnt, &dsoff, &dsdisp, &fid);
402da6c28aaSamw 
4037b59d02dSjb150015 	if (rc != 0)
404faa1795aSjb150015 		return (SDRC_ERROR);
405da6c28aaSamw 
406da6c28aaSamw 	mutex_enter(&xa->xa_mutex);
4077f3ef643SGordon Ross 	if (xa->smb_tpscnt > tpscnt)
4087f3ef643SGordon Ross 		xa->smb_tpscnt = tpscnt;
4097f3ef643SGordon Ross 	if (xa->smb_tdscnt > tdscnt)
4107f3ef643SGordon Ross 		xa->smb_tdscnt = tdscnt;
4117f3ef643SGordon Ross 	if (fid != 0xFFFF)
4127f3ef643SGordon Ross 		xa->xa_smb_fid = fid;
413da6c28aaSamw 	xa->req_disp_param = psdisp + pscnt;
414da6c28aaSamw 	xa->req_disp_data  = dsdisp + dscnt;
415da6c28aaSamw 
4167f3ef643SGordon Ross 	/*
4177f3ef643SGordon Ross 	 * See comment in smb_com_transaction_secondary
4187f3ef643SGordon Ross 	 */
4197f3ef643SGordon Ross 	if (xa->req_param_mb.chain_offset != psdisp) {
4207f3ef643SGordon Ross 		DTRACE_PROBE2(trans_param_disp,
4217f3ef643SGordon Ross 		    smb_xa_t *, xa, uint16_t, psdisp);
4227f3ef643SGordon Ross 		xa->req_param_mb.chain_offset = psdisp;
4237f3ef643SGordon Ross 	}
4247f3ef643SGordon Ross 	if (xa->req_data_mb.chain_offset != dsdisp) {
4257f3ef643SGordon Ross 		DTRACE_PROBE2(trans_data_disp,
4267f3ef643SGordon Ross 		    smb_xa_t *, xa, uint16_t, dsdisp);
4277f3ef643SGordon Ross 		xa->req_data_mb.chain_offset = dsdisp;
4287f3ef643SGordon Ross 	}
4297f3ef643SGordon Ross 
4307f3ef643SGordon Ross 	if (smb_mbc_copy(&xa->req_param_mb, &sr->command, psoff, pscnt)) {
431da6c28aaSamw 		mutex_exit(&xa->xa_mutex);
432da6c28aaSamw 		smb_xa_close(xa);
433dc20a302Sas200622 		smbsr_error(sr, 0, ERRDOS, ERRbadformat);
434faa1795aSjb150015 		return (SDRC_ERROR);
435da6c28aaSamw 	}
4367f3ef643SGordon Ross 	if (smb_mbc_copy(&xa->req_data_mb, &sr->command, dsoff, dscnt)) {
437da6c28aaSamw 		mutex_exit(&xa->xa_mutex);
438da6c28aaSamw 		smb_xa_close(xa);
439dc20a302Sas200622 		smbsr_error(sr, 0, ERRDOS, ERRbadformat);
440faa1795aSjb150015 		return (SDRC_ERROR);
441da6c28aaSamw 	}
442da6c28aaSamw 	mutex_exit(&xa->xa_mutex);
443da6c28aaSamw 
444da6c28aaSamw 	if (!smb_trans_ready(xa))
445da6c28aaSamw 		return (SDRC_NO_REPLY);
446da6c28aaSamw 
447da6c28aaSamw 	if (!smb_xa_complete(xa))
448da6c28aaSamw 		return (SDRC_NO_REPLY);
449da6c28aaSamw 
450da6c28aaSamw 	return (smb_trans2_dispatch(sr, xa));
451da6c28aaSamw }
452da6c28aaSamw 
4537b59d02dSjb150015 static smb_sdrc_t
454da6c28aaSamw smb_nt_trans_dispatch(struct smb_request *sr, struct smb_xa *xa)
455da6c28aaSamw {
456da6c28aaSamw 	int rc;
457da6c28aaSamw 	int total_bytes, n_setup, n_param, n_data;
458da6c28aaSamw 	int param_off, param_pad, data_off, data_pad;
459da6c28aaSamw 
460da6c28aaSamw 	switch (xa->smb_func) {
461da6c28aaSamw 	case NT_TRANSACT_CREATE:
462faa1795aSjb150015 		if ((rc = smb_pre_nt_transact_create(sr, xa)) == 0)
463da6c28aaSamw 			rc = smb_nt_transact_create(sr, xa);
464faa1795aSjb150015 		smb_post_nt_transact_create(sr, xa);
465da6c28aaSamw 		break;
466da6c28aaSamw 	case NT_TRANSACT_NOTIFY_CHANGE:
467da6c28aaSamw 		rc = smb_nt_transact_notify_change(sr, xa);
468da6c28aaSamw 		break;
469da6c28aaSamw 	case NT_TRANSACT_QUERY_SECURITY_DESC:
470da6c28aaSamw 		rc = smb_nt_transact_query_security_info(sr, xa);
471da6c28aaSamw 		break;
472da6c28aaSamw 	case NT_TRANSACT_SET_SECURITY_DESC:
473da6c28aaSamw 		rc = smb_nt_transact_set_security_info(sr, xa);
474da6c28aaSamw 		break;
475da6c28aaSamw 	case NT_TRANSACT_IOCTL:
476da6c28aaSamw 		rc = smb_nt_transact_ioctl(sr, xa);
477da6c28aaSamw 		break;
478da6c28aaSamw 	case NT_TRANSACT_QUERY_QUOTA:
4799fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States 		rc = smb_nt_transact_query_quota(sr, xa);
480b1352070SAlan Wright 		break;
481da6c28aaSamw 	case NT_TRANSACT_SET_QUOTA:
4829fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States 		rc = smb_nt_transact_set_quota(sr, xa);
4839fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States 		break;
484bbf6f00cSJordan Brown 	case NT_TRANSACT_RENAME:
485bbf6f00cSJordan Brown 		rc = smb_nt_transact_rename(sr, xa);
486bbf6f00cSJordan Brown 		break;
487bbf6f00cSJordan Brown 
488da6c28aaSamw 	default:
489dc20a302Sas200622 		smbsr_error(sr, 0, ERRSRV, ERRsmbcmd);
490faa1795aSjb150015 		return (SDRC_ERROR);
491da6c28aaSamw 	}
492da6c28aaSamw 
493da6c28aaSamw 	switch (rc) {
494faa1795aSjb150015 	case SDRC_SUCCESS:
495da6c28aaSamw 		break;
496da6c28aaSamw 
497da6c28aaSamw 	case SDRC_DROP_VC:
498da6c28aaSamw 	case SDRC_NO_REPLY:
499faa1795aSjb150015 	case SDRC_ERROR:
50059229f98Sjose borrego 	case SDRC_SR_KEPT:
501da6c28aaSamw 		return (rc);
502da6c28aaSamw 
503faa1795aSjb150015 	case SDRC_NOT_IMPLEMENTED:
504dc20a302Sas200622 		smbsr_error(sr, 0, ERRSRV, ERRsmbcmd);
505faa1795aSjb150015 		return (SDRC_ERROR);
506da6c28aaSamw 
507da6c28aaSamw 	default:
508da6c28aaSamw 		break;
509da6c28aaSamw 	}
510da6c28aaSamw 
511da6c28aaSamw 	n_setup = MBC_LENGTH(&xa->rep_setup_mb);
512da6c28aaSamw 	n_param = MBC_LENGTH(&xa->rep_param_mb);
513da6c28aaSamw 	n_data  = MBC_LENGTH(&xa->rep_data_mb);
514da6c28aaSamw 
515da6c28aaSamw 	if (xa->smb_msrcnt < n_setup ||
516da6c28aaSamw 	    xa->smb_mprcnt < n_param ||
517da6c28aaSamw 	    xa->smb_mdrcnt < n_data) {
518dc20a302Sas200622 		smbsr_error(sr, 0, ERRSRV, ERRsmbcmd);
519faa1795aSjb150015 		return (SDRC_ERROR);
520da6c28aaSamw 	}
521da6c28aaSamw 
522da6c28aaSamw 	/* neato, blast it over there */
523da6c28aaSamw 
524da6c28aaSamw 	n_setup = (n_setup + 1) / 2;		/* Conver to setup words */
525da6c28aaSamw 	param_pad = 1;				/* must be one */
526da6c28aaSamw 	param_off = param_pad + 32 + 37 + (n_setup << 1) + 2;
527da6c28aaSamw 	data_pad = (4 - ((param_off + n_param) & 3)) % 4; /* Pad to 4 byte */
528da6c28aaSamw 	data_off = param_off + n_param + data_pad; /* Param off from hdr */
529da6c28aaSamw 	total_bytes = param_pad + n_param + data_pad + n_data;
530da6c28aaSamw 
5317b59d02dSjb150015 	rc = smbsr_encode_result(sr, 18+n_setup, total_bytes,
532da6c28aaSamw 	    "b3.llllllllbCw#.C#.C",
533da6c28aaSamw 	    18 + n_setup,		/* wct */
534da6c28aaSamw 	    n_param,			/* Total Parameter Bytes */
535da6c28aaSamw 	    n_data,			/* Total Data Bytes */
536da6c28aaSamw 	    n_param,			/* Total Parameter Bytes this buffer */
537da6c28aaSamw 	    param_off,			/* Param offset from header start */
538da6c28aaSamw 	    0,				/* Param displacement */
539da6c28aaSamw 	    n_data,			/* Total Data Bytes this buffer */
540da6c28aaSamw 	    data_off,			/* Data offset from header start */
541da6c28aaSamw 	    0,				/* Data displacement */
542da6c28aaSamw 	    n_setup,			/* suwcnt */
543da6c28aaSamw 	    &xa->rep_setup_mb,		/* setup[] */
544da6c28aaSamw 	    total_bytes,		/* Total data bytes */
545da6c28aaSamw 	    param_pad,
546da6c28aaSamw 	    &xa->rep_param_mb,
547da6c28aaSamw 	    data_pad,
548da6c28aaSamw 	    &xa->rep_data_mb);
549faa1795aSjb150015 	return ((rc == 0) ? SDRC_SUCCESS : SDRC_ERROR);
550da6c28aaSamw }
551da6c28aaSamw 
552faa1795aSjb150015 smb_sdrc_t
553faa1795aSjb150015 smb_pre_nt_transact(smb_request_t *sr)
554faa1795aSjb150015 {
555faa1795aSjb150015 	DTRACE_SMB_1(op__NtTransact__start, smb_request_t *, sr);
556faa1795aSjb150015 	return (SDRC_SUCCESS);
557faa1795aSjb150015 }
558faa1795aSjb150015 
559faa1795aSjb150015 void
560faa1795aSjb150015 smb_post_nt_transact(smb_request_t *sr)
561faa1795aSjb150015 {
562faa1795aSjb150015 	DTRACE_SMB_1(op__NtTransact__done, smb_request_t *, sr);
563faa1795aSjb150015 }
564da6c28aaSamw 
5657b59d02dSjb150015 smb_sdrc_t
566da6c28aaSamw smb_com_nt_transact(struct smb_request *sr)
567da6c28aaSamw {
568da6c28aaSamw 	uint16_t	Function;
569da6c28aaSamw 	unsigned char	MaxSetupCount, SetupCount;
570da6c28aaSamw 	uint32_t	TotalParameterCount, TotalDataCount;
571da6c28aaSamw 	uint32_t	MaxParameterCount, MaxDataCount, pscnt;
572da6c28aaSamw 	uint32_t	psoff, dscnt, dsoff;
573da6c28aaSamw 	smb_xa_t *xa;
574da6c28aaSamw 	int ready;
575da6c28aaSamw 	int rc;
576da6c28aaSamw 
577da6c28aaSamw 	rc = smbsr_decode_vwv(sr, SMB_NT_TRANSHDR_ED_FMT, &MaxSetupCount,
578da6c28aaSamw 	    &TotalParameterCount, &TotalDataCount, &MaxParameterCount,
579da6c28aaSamw 	    &MaxDataCount, &pscnt, &psoff, &dscnt,
580da6c28aaSamw 	    &dsoff, &SetupCount, &Function);
581da6c28aaSamw 
5827b59d02dSjb150015 	if (rc != 0)
583faa1795aSjb150015 		return (SDRC_ERROR);
584da6c28aaSamw 
585da6c28aaSamw 	xa = smb_xa_create(sr->session, sr, TotalParameterCount, TotalDataCount,
586da6c28aaSamw 	    MaxParameterCount, MaxDataCount, MaxSetupCount, SetupCount);
587da6c28aaSamw 	if (xa == 0) {
588dc20a302Sas200622 		smbsr_error(sr, 0, ERRSRV, ERRnoroom);
589faa1795aSjb150015 		return (SDRC_ERROR);
590da6c28aaSamw 	}
591da6c28aaSamw 
592da6c28aaSamw 	xa->smb_flags  = 0;
593da6c28aaSamw 	xa->smb_timeout = 0;
594da6c28aaSamw 	xa->smb_func = Function;
595da6c28aaSamw 	xa->req_disp_param = pscnt;
596da6c28aaSamw 	xa->req_disp_data  = dscnt;
597da6c28aaSamw 
5987f3ef643SGordon Ross 	if (smb_mbc_copy(&xa->req_setup_mb, &sr->smb_vwv,
599da6c28aaSamw 	    sr->smb_vwv.chain_offset, SetupCount * 2)) {
600da6c28aaSamw 		smb_xa_rele(sr->session, xa);
601dc20a302Sas200622 		smbsr_error(sr, 0, ERRDOS, ERRbadformat);
602faa1795aSjb150015 		return (SDRC_ERROR);
603da6c28aaSamw 	}
6047f3ef643SGordon Ross 	if (smb_mbc_copy(&xa->req_param_mb, &sr->command, psoff, pscnt)) {
605da6c28aaSamw 		smb_xa_rele(sr->session, xa);
606dc20a302Sas200622 		smbsr_error(sr, 0, ERRDOS, ERRbadformat);
607faa1795aSjb150015 		return (SDRC_ERROR);
608da6c28aaSamw 	}
6097f3ef643SGordon Ross 	if (smb_mbc_copy(&xa->req_data_mb, &sr->command, dsoff, dscnt)) {
610da6c28aaSamw 		smb_xa_rele(sr->session, xa);
611dc20a302Sas200622 		smbsr_error(sr, 0, ERRDOS, ERRbadformat);
612faa1795aSjb150015 		return (SDRC_ERROR);
613da6c28aaSamw 	}
614da6c28aaSamw 
615da6c28aaSamw 	ready = smb_trans_ready(xa);
616da6c28aaSamw 
617da6c28aaSamw 	if (smb_xa_open(xa)) {
618da6c28aaSamw 		smb_xa_rele(sr->session, xa);
619ccc71be5SGordon Ross 		smbsr_error(sr, 0, ERRSRV, ERRsrverror);
620faa1795aSjb150015 		return (SDRC_ERROR);
621da6c28aaSamw 	}
622da6c28aaSamw 	sr->r_xa = xa;
623da6c28aaSamw 
624da6c28aaSamw 	if (!ready) {
6257b59d02dSjb150015 		rc = smbsr_encode_empty_result(sr);
626faa1795aSjb150015 		return ((rc == 0) ? SDRC_SUCCESS : SDRC_ERROR);
627da6c28aaSamw 	}
628da6c28aaSamw 
629da6c28aaSamw 	if (!smb_xa_complete(xa)) {
630da6c28aaSamw 		smb_xa_close(xa);
631dc20a302Sas200622 		smbsr_error(sr, 0, ERRDOS, ERRbadformat);
632faa1795aSjb150015 		return (SDRC_ERROR);
633da6c28aaSamw 	}
634da6c28aaSamw 
635da6c28aaSamw 	return (smb_nt_trans_dispatch(sr, xa));
636da6c28aaSamw }
637da6c28aaSamw 
638faa1795aSjb150015 smb_sdrc_t
639faa1795aSjb150015 smb_pre_nt_transact_secondary(smb_request_t *sr)
640faa1795aSjb150015 {
641faa1795aSjb150015 	DTRACE_SMB_1(op__NtTransactSecondary__start, smb_request_t *, sr);
642faa1795aSjb150015 	return (SDRC_SUCCESS);
643faa1795aSjb150015 }
644faa1795aSjb150015 
645faa1795aSjb150015 void
646faa1795aSjb150015 smb_post_nt_transact_secondary(smb_request_t *sr)
647faa1795aSjb150015 {
648faa1795aSjb150015 	DTRACE_SMB_1(op__NtTransactSecondary__done, smb_request_t *, sr);
649faa1795aSjb150015 }
650da6c28aaSamw 
6517b59d02dSjb150015 smb_sdrc_t
652da6c28aaSamw smb_com_nt_transact_secondary(struct smb_request *sr)
653da6c28aaSamw {
654da6c28aaSamw 	uint16_t tpscnt, tdscnt, fid;
655da6c28aaSamw 	uint16_t pscnt, psoff, psdisp, dscnt, dsoff, dsdisp;
656da6c28aaSamw 	smb_xa_t *xa;
657da6c28aaSamw 	int rc;
658da6c28aaSamw 
659da6c28aaSamw 	if ((xa = smbsr_lookup_xa(sr)) == 0) {
660dc20a302Sas200622 		smbsr_error(sr, 0, ERRSRV, ERRsrverror);
661faa1795aSjb150015 		return (SDRC_ERROR);
662da6c28aaSamw 	}
663da6c28aaSamw 
664da6c28aaSamw 	if (sr->session->signing.flags & SMB_SIGNING_ENABLED) {
665da6c28aaSamw 		if (smb_sign_check_secondary(sr, xa->reply_seqnum) != 0) {
666dc20a302Sas200622 			smbsr_error(sr, NT_STATUS_ACCESS_DENIED,
667da6c28aaSamw 			    ERRDOS, ERRnoaccess);
668faa1795aSjb150015 			return (SDRC_ERROR);
669da6c28aaSamw 		}
670da6c28aaSamw 	}
671da6c28aaSamw 
672da6c28aaSamw 	if (xa->smb_com != SMB_COM_TRANSACTION2) {
673da6c28aaSamw 		return (SDRC_DROP_VC);
674da6c28aaSamw 	}
675da6c28aaSamw 
676da6c28aaSamw 	rc = smbsr_decode_vwv(sr, SMB_TRANS2SHDR_ED_FMT, &tpscnt, &tdscnt,
677da6c28aaSamw 	    &pscnt, &psoff, &psdisp, &dscnt, &dsoff, &dsdisp, &fid);
678da6c28aaSamw 
6797b59d02dSjb150015 	if (rc != 0)
680faa1795aSjb150015 		return (SDRC_ERROR);
681da6c28aaSamw 
682da6c28aaSamw 	mutex_enter(&xa->xa_mutex);
6837f3ef643SGordon Ross 	if (xa->smb_tpscnt > tpscnt)
6847f3ef643SGordon Ross 		xa->smb_tpscnt = tpscnt;
6857f3ef643SGordon Ross 	if (xa->smb_tdscnt > tdscnt)
6867f3ef643SGordon Ross 		xa->smb_tdscnt = tdscnt;
6877f3ef643SGordon Ross 	if (fid != 0xFFFF)
6887f3ef643SGordon Ross 		xa->xa_smb_fid = fid;
689da6c28aaSamw 	xa->req_disp_param = psdisp + pscnt;
690da6c28aaSamw 	xa->req_disp_data  = dsdisp + dscnt;
691da6c28aaSamw 
6927f3ef643SGordon Ross 	/*
6937f3ef643SGordon Ross 	 * See comment in smb_com_transaction_secondary
6947f3ef643SGordon Ross 	 */
6957f3ef643SGordon Ross 	if (xa->req_param_mb.chain_offset != psdisp) {
6967f3ef643SGordon Ross 		DTRACE_PROBE2(trans_param_disp,
6977f3ef643SGordon Ross 		    smb_xa_t *, xa, uint16_t, psdisp);
6987f3ef643SGordon Ross 		xa->req_param_mb.chain_offset = psdisp;
6997f3ef643SGordon Ross 	}
7007f3ef643SGordon Ross 	if (xa->req_data_mb.chain_offset != dsdisp) {
7017f3ef643SGordon Ross 		DTRACE_PROBE2(trans_data_disp,
7027f3ef643SGordon Ross 		    smb_xa_t *, xa, uint16_t, dsdisp);
7037f3ef643SGordon Ross 		xa->req_data_mb.chain_offset = dsdisp;
7047f3ef643SGordon Ross 	}
7057f3ef643SGordon Ross 
7067f3ef643SGordon Ross 	if (smb_mbc_copy(&xa->req_param_mb, &sr->command, psoff, pscnt)) {
707da6c28aaSamw 		mutex_exit(&xa->xa_mutex);
708da6c28aaSamw 		smb_xa_close(xa);
709dc20a302Sas200622 		smbsr_error(sr, 0, ERRDOS, ERRbadformat);
710faa1795aSjb150015 		return (SDRC_ERROR);
711da6c28aaSamw 	}
7127f3ef643SGordon Ross 	if (smb_mbc_copy(&xa->req_data_mb, &sr->command, dsoff, dscnt)) {
713da6c28aaSamw 		mutex_exit(&xa->xa_mutex);
714da6c28aaSamw 		smb_xa_close(xa);
715dc20a302Sas200622 		smbsr_error(sr, 0, ERRDOS, ERRbadformat);
716faa1795aSjb150015 		return (SDRC_ERROR);
717da6c28aaSamw 	}
718da6c28aaSamw 	mutex_exit(&xa->xa_mutex);
719da6c28aaSamw 
720da6c28aaSamw 	if (!smb_trans_ready(xa))
721da6c28aaSamw 		return (SDRC_NO_REPLY);
722da6c28aaSamw 
723da6c28aaSamw 	if (!smb_xa_complete(xa))
724da6c28aaSamw 		return (SDRC_NO_REPLY);
725da6c28aaSamw 
726da6c28aaSamw 	return (smb_nt_trans_dispatch(sr, xa));
727da6c28aaSamw }
728da6c28aaSamw 
7297b59d02dSjb150015 static int
7309fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States smb_trans_ready(smb_xa_t *xa)
731da6c28aaSamw {
732da6c28aaSamw 	int rc;
733da6c28aaSamw 
734da6c28aaSamw 	mutex_enter(&xa->xa_mutex);
735da6c28aaSamw 	rc = xa->req_disp_data >= xa->smb_tdscnt &&
736da6c28aaSamw 	    xa->req_disp_param >= xa->smb_tpscnt;
737da6c28aaSamw 	mutex_exit(&xa->xa_mutex);
738da6c28aaSamw 
739da6c28aaSamw 	return (rc);
740da6c28aaSamw }
741da6c28aaSamw 
7423ad684d6Sjb150015 static void
7433ad684d6Sjb150015 smb_encode_SHARE_INFO_1(struct mbuf_chain *output, struct mbuf_chain *text,
7443ad684d6Sjb150015     char *oem_name, uint16_t type, char *comment)
745da6c28aaSamw {
7463db3f65cSamw 	(void) smb_mbc_encodef(output, "13c.wl", oem_name,
7473ad684d6Sjb150015 	    type, MBC_LENGTH(text));
748da6c28aaSamw 
7493db3f65cSamw 	(void) smb_mbc_encodef(text, "s", comment ? comment : "");
7506537f381Sas200622 }
751da6c28aaSamw 
7523ad684d6Sjb150015 static void
7533ad684d6Sjb150015 smb_encode_SHARE_INFO_2(struct mbuf_chain *output, struct mbuf_chain *text,
7543ad684d6Sjb150015 	smb_request_t *sr, char *oem_name, uint16_t type,
7553ad684d6Sjb150015 	char *comment, uint16_t access, char *path, char *password)
756da6c28aaSamw {
757da6c28aaSamw 	unsigned char pword[9];
758da6c28aaSamw 
759da6c28aaSamw 	bzero(pword, sizeof (pword));
760da6c28aaSamw 	(void) strncpy((char *)pword, password, sizeof (pword));
7613ad684d6Sjb150015 	smb_encode_SHARE_INFO_1(output, text, oem_name, type, comment);
7623db3f65cSamw 	(void) smb_mbc_encodef(output, "wwwl9c.",
763da6c28aaSamw 	    access,
764faa1795aSjb150015 	    sr->sr_cfg->skc_maxconnections,
7658622ec45SGordon Ross 	    smb_server_get_session_count(sr->sr_server),
766da6c28aaSamw 	    MBC_LENGTH(text),
7673ad684d6Sjb150015 	    pword);
7683db3f65cSamw 	(void) smb_mbc_encodef(text, "s", path);
769da6c28aaSamw }
770da6c28aaSamw 
771da6c28aaSamw int
772da6c28aaSamw smb_trans_net_share_enum(struct smb_request *sr, struct smb_xa *xa)
773da6c28aaSamw {
774da6c28aaSamw 	/*
775da6c28aaSamw 	 * Number of data bytes that will
776da6c28aaSamw 	 * be sent in the current response
777da6c28aaSamw 	 */
778da6c28aaSamw 	uint16_t data_scnt;
779da6c28aaSamw 
780da6c28aaSamw 	/*
781da6c28aaSamw 	 * Total number of data bytes that
782da6c28aaSamw 	 * are sent till now. This is only
783da6c28aaSamw 	 * used for calculating current data
784da6c28aaSamw 	 * displacement
785da6c28aaSamw 	 */
786da6c28aaSamw 	uint16_t tot_data_scnt;
787da6c28aaSamw 
788da6c28aaSamw 	/*
789da6c28aaSamw 	 * Number of parameter bytes should
790da6c28aaSamw 	 * be sent for the current response.
791da6c28aaSamw 	 * It is 8 for the 1st response and
792da6c28aaSamw 	 * 0 for others
793da6c28aaSamw 	 */
794da6c28aaSamw 	uint16_t param_scnt;
795da6c28aaSamw 
796da6c28aaSamw 	/* number of setup and parameter bytes */
797da6c28aaSamw 	uint16_t n_setup, n_param;
798da6c28aaSamw 
799da6c28aaSamw 	/* data and parameter displacement */
800da6c28aaSamw 	uint16_t data_disp, param_disp;
801da6c28aaSamw 
802da6c28aaSamw 	/* parameter and data offset and pad */
803da6c28aaSamw 	int param_off, param_pad, data_off, data_pad;
804da6c28aaSamw 
805da6c28aaSamw 	/*
806da6c28aaSamw 	 * total bytes of parameters and data
807da6c28aaSamw 	 * in the packet, plus the pad bytes.
808da6c28aaSamw 	 */
809da6c28aaSamw 	int tot_packet_bytes;
810da6c28aaSamw 
8113ad684d6Sjb150015 	boolean_t first_resp;
812da6c28aaSamw 
8133ad684d6Sjb150015 	char fmt[16];
8143ad684d6Sjb150015 	struct mbuf_chain reply;
8153ad684d6Sjb150015 
8163ad684d6Sjb150015 	uint16_t level;
8173ad684d6Sjb150015 	uint16_t pkt_bufsize;
8183ad684d6Sjb150015 	smb_enumshare_info_t esi;
8193ad684d6Sjb150015 	char *sent_buf;
8203ad684d6Sjb150015 
8213ad684d6Sjb150015 	ASSERT(sr->uid_user);
822da6c28aaSamw 
8233db3f65cSamw 	if (smb_mbc_decodef(&xa->req_param_mb, "ww", &level,
8243ad684d6Sjb150015 	    &esi.es_bufsize) != 0)
825faa1795aSjb150015 		return (SDRC_NOT_IMPLEMENTED);
826da6c28aaSamw 
827da6c28aaSamw 	if (level != 1) {
8283ad684d6Sjb150015 		/*
8293ad684d6Sjb150015 		 * Only level 1 is valid for NetShareEnum
8303ad684d6Sjb150015 		 * None of the error codes in the spec are meaningful
8313ad684d6Sjb150015 		 * here. This error code is returned by Windows.
8323ad684d6Sjb150015 		 */
8333db3f65cSamw 		(void) smb_mbc_encodef(&xa->rep_param_mb, "wwww",
8343ad684d6Sjb150015 		    ERROR_INVALID_LEVEL, 0, 0, 0);
835faa1795aSjb150015 		return (SDRC_SUCCESS);
836da6c28aaSamw 	}
837da6c28aaSamw 
838148c5f43SAlan Wright 	esi.es_buf = smb_srm_zalloc(sr, esi.es_bufsize);
839c5866007SKeyur Desai 	esi.es_posix_uid = crgetuid(sr->uid_user->u_cred);
8408622ec45SGordon Ross 	smb_kshare_enum(sr->sr_server, &esi);
841da6c28aaSamw 
8423ad684d6Sjb150015 	/* client buffer size is not big enough to hold any shares */
8433ad684d6Sjb150015 	if (esi.es_nsent == 0) {
8443db3f65cSamw 		(void) smb_mbc_encodef(&xa->rep_param_mb, "wwww",
8453ad684d6Sjb150015 		    ERROR_MORE_DATA, 0, esi.es_nsent, esi.es_ntotal);
846faa1795aSjb150015 		return (SDRC_SUCCESS);
847da6c28aaSamw 	}
848da6c28aaSamw 
849da6c28aaSamw 	/*
8507f3ef643SGordon Ross 	 * Initialize the reply mbuf chain.  Note that we re-initialize
8517f3ef643SGordon Ross 	 * this on each pass through the loop below.
8527f3ef643SGordon Ross 	 */
8537f3ef643SGordon Ross 	MBC_SETUP(&reply, smb_maxbufsize);
8547f3ef643SGordon Ross 
8557f3ef643SGordon Ross 	/*
856da6c28aaSamw 	 * The rep_setup_mb is already initialized in smb_trans_dispatch().
857da6c28aaSamw 	 * Calling MBC_INIT() will initialized the structure and so the
858da6c28aaSamw 	 * pointer to the mbuf chains will be lost. Therefore, we need
859da6c28aaSamw 	 * to free the resources before calling MBC_INIT() again.
860da6c28aaSamw 	 */
8613ad684d6Sjb150015 	n_setup = 0;	/* Setup count for NetShareEnum SMB is 0 */
8627f3ef643SGordon Ross 	MBC_FLUSH(&xa->rep_setup_mb);
863da6c28aaSamw 
8643ad684d6Sjb150015 	n_param = 8;
8653ad684d6Sjb150015 	pkt_bufsize = sr->session->smb_msg_size -
8663ad684d6Sjb150015 	    (SMB_HEADER_ED_LEN + RESP_HEADER_LEN + n_param);
867da6c28aaSamw 
8683ad684d6Sjb150015 	tot_data_scnt = 0;
8693ad684d6Sjb150015 	sent_buf = esi.es_buf;
8703ad684d6Sjb150015 	first_resp = B_TRUE;
8713ad684d6Sjb150015 
8723ad684d6Sjb150015 	while (tot_data_scnt < esi.es_datasize) {
8733ad684d6Sjb150015 		data_scnt = esi.es_datasize - tot_data_scnt;
8743ad684d6Sjb150015 		if (data_scnt > pkt_bufsize)
8753ad684d6Sjb150015 			data_scnt = pkt_bufsize;
8767f3ef643SGordon Ross 		MBC_FLUSH(&xa->rep_data_mb);
8773ad684d6Sjb150015 
8783ad684d6Sjb150015 		(void) sprintf(fmt, "%dc", data_scnt);
8793db3f65cSamw 		(void) smb_mbc_encodef(&xa->rep_data_mb, fmt, sent_buf);
8803ad684d6Sjb150015 
8813ad684d6Sjb150015 		sent_buf += data_scnt;
882da6c28aaSamw 		tot_data_scnt += data_scnt;
883da6c28aaSamw 
884da6c28aaSamw 		/* Only the 1st response packet contains parameters */
885da6c28aaSamw 		param_scnt = (first_resp) ? n_param : 0;
886da6c28aaSamw 		param_pad = 1;				/* always one */
887da6c28aaSamw 		param_off = SMB_HEADER_ED_LEN + RESP_HEADER_LEN;
888da6c28aaSamw 		param_disp = (first_resp) ? 0 : n_param;
889da6c28aaSamw 
8907f3ef643SGordon Ross 		MBC_FLUSH(&xa->rep_param_mb);
8913ad684d6Sjb150015 
892da6c28aaSamw 		if (first_resp) {
8933ad684d6Sjb150015 			first_resp = B_FALSE;
8943db3f65cSamw 			(void) smb_mbc_encodef(&xa->rep_param_mb, "wwww",
8953ad684d6Sjb150015 			    (esi.es_ntotal > esi.es_nsent)
8963ad684d6Sjb150015 			    ? ERROR_MORE_DATA : 0,
8973ad684d6Sjb150015 			    0, esi.es_nsent, esi.es_ntotal);
898da6c28aaSamw 		}
899da6c28aaSamw 
900da6c28aaSamw 		data_pad = (param_off + n_param) & 1;	/* Pad to short */
901da6c28aaSamw 
902da6c28aaSamw 		/* data off from hdr start */
903da6c28aaSamw 		data_off = param_off + param_scnt + data_pad;
904da6c28aaSamw 		data_disp = tot_data_scnt - data_scnt;
905da6c28aaSamw 		tot_packet_bytes = param_pad + param_scnt + data_pad +
906da6c28aaSamw 		    data_scnt;
907da6c28aaSamw 
9087f3ef643SGordon Ross 		MBC_FLUSH(&reply);
9093db3f65cSamw 		(void) smb_mbc_encodef(&reply, SMB_HEADER_ED_FMT,
910da6c28aaSamw 		    sr->first_smb_com,
911da6c28aaSamw 		    sr->smb_rcls,
912da6c28aaSamw 		    sr->smb_reh,
913da6c28aaSamw 		    sr->smb_err,
914da6c28aaSamw 		    sr->smb_flg | SMB_FLAGS_REPLY,
915da6c28aaSamw 		    sr->smb_flg2,
916da6c28aaSamw 		    sr->smb_pid_high,
917da6c28aaSamw 		    sr->smb_sig,
918da6c28aaSamw 		    sr->smb_tid,
919da6c28aaSamw 		    sr->smb_pid,
920da6c28aaSamw 		    sr->smb_uid,
921da6c28aaSamw 		    sr->smb_mid);
922da6c28aaSamw 
9233db3f65cSamw 		(void) smb_mbc_encodef(&reply,
924da6c28aaSamw 		    "bww2.wwwwwwb.Cw#.C#.C",
925da6c28aaSamw 		    10 + n_setup,	/* wct */
926da6c28aaSamw 		    n_param,		/* Total Parameter Bytes */
9273ad684d6Sjb150015 		    esi.es_datasize,	/* Total Data Bytes */
928da6c28aaSamw 		    param_scnt,		/* Total Parameter Bytes this buffer */
929da6c28aaSamw 		    param_off,		/* Param offset from header start */
930da6c28aaSamw 		    param_disp,		/* Param displacement */
931da6c28aaSamw 		    data_scnt,		/* Total Data Bytes this buffer */
932da6c28aaSamw 		    data_off,		/* Data offset from header start */
933da6c28aaSamw 		    data_disp,		/* Data displacement */
934da6c28aaSamw 		    n_setup,		/* suwcnt */
935da6c28aaSamw 		    &xa->rep_setup_mb, 	/* setup[] */
936da6c28aaSamw 		    tot_packet_bytes,	/* Total data bytes */
937da6c28aaSamw 		    param_pad,
938da6c28aaSamw 		    &xa->rep_param_mb,
939da6c28aaSamw 		    data_pad,
940da6c28aaSamw 		    &xa->rep_data_mb);
941da6c28aaSamw 
942da6c28aaSamw 		if (sr->session->signing.flags & SMB_SIGNING_ENABLED)
943b89a8333Snatalie li - Sun Microsystems - Irvine United States 			smb_sign_reply(sr, &reply);
944da6c28aaSamw 
945da6c28aaSamw 		(void) smb_session_send(sr->session, 0, &reply);
9467f3ef643SGordon Ross 
947da6c28aaSamw 	}
948da6c28aaSamw 
9497f3ef643SGordon Ross 	m_freem(reply.chain);
9507f3ef643SGordon Ross 
951da6c28aaSamw 	return (SDRC_NO_REPLY);
952da6c28aaSamw }
953da6c28aaSamw 
954da6c28aaSamw int
9553ad684d6Sjb150015 smb_trans_net_share_getinfo(smb_request_t *sr, struct smb_xa *xa)
956da6c28aaSamw {
9573ad684d6Sjb150015 	uint16_t		level, max_bytes, access;
958da6c28aaSamw 	struct mbuf_chain	str_mb;
959da6c28aaSamw 	char			*share;
960da6c28aaSamw 	char			*password;
961148c5f43SAlan Wright 	smb_kshare_t		*si;
962da6c28aaSamw 
9633db3f65cSamw 	if (smb_mbc_decodef(&xa->req_param_mb, "%sww", sr,
9643ad684d6Sjb150015 	    &share, &level, &max_bytes) != 0)
965faa1795aSjb150015 		return (SDRC_NOT_IMPLEMENTED);
966da6c28aaSamw 
9678622ec45SGordon Ross 	si = smb_kshare_lookup(sr->sr_server, share);
968148c5f43SAlan Wright 	if ((si == NULL) || (si->shr_oemname == NULL)) {
9693db3f65cSamw 		(void) smb_mbc_encodef(&xa->rep_param_mb, "www",
970da6c28aaSamw 		    NERR_NetNameNotFound, 0, 0);
971148c5f43SAlan Wright 		if (si)
9728622ec45SGordon Ross 			smb_kshare_release(sr->sr_server, si);
973faa1795aSjb150015 		return (SDRC_SUCCESS);
974da6c28aaSamw 	}
975da6c28aaSamw 
9763ad684d6Sjb150015 	access = SHARE_ACCESS_ALL;
977da6c28aaSamw 	password = "";
978da6c28aaSamw 
979da6c28aaSamw 	MBC_INIT(&str_mb, max_bytes);
980da6c28aaSamw 
981da6c28aaSamw 	switch (level) {
982da6c28aaSamw 	case 0 :
983148c5f43SAlan Wright 		(void) smb_mbc_encodef(&xa->rep_data_mb, "13c",
984148c5f43SAlan Wright 		    si->shr_oemname);
985da6c28aaSamw 		break;
986da6c28aaSamw 
987da6c28aaSamw 	case 1 :
9883ad684d6Sjb150015 		smb_encode_SHARE_INFO_1(&xa->rep_data_mb, &str_mb,
989148c5f43SAlan Wright 		    si->shr_oemname, si->shr_type, si->shr_cmnt);
990da6c28aaSamw 		break;
991da6c28aaSamw 
992da6c28aaSamw 	case 2 :
9933ad684d6Sjb150015 		smb_encode_SHARE_INFO_2(&xa->rep_data_mb, &str_mb, sr,
994148c5f43SAlan Wright 		    si->shr_oemname, si->shr_type, si->shr_cmnt, access,
995148c5f43SAlan Wright 		    si->shr_path, password);
9963ad684d6Sjb150015 		break;
9973ad684d6Sjb150015 
998da6c28aaSamw 	default:
9998622ec45SGordon Ross 		smb_kshare_release(sr->sr_server, si);
10003db3f65cSamw 		(void) smb_mbc_encodef(&xa->rep_param_mb, "www",
10013ad684d6Sjb150015 		    ERROR_INVALID_LEVEL, 0, 0);
1002da6c28aaSamw 		m_freem(str_mb.chain);
1003faa1795aSjb150015 		return (SDRC_NOT_IMPLEMENTED);
1004da6c28aaSamw 	}
1005da6c28aaSamw 
10068622ec45SGordon Ross 	smb_kshare_release(sr->sr_server, si);
10073db3f65cSamw 	(void) smb_mbc_encodef(&xa->rep_param_mb, "www", NERR_Success,
1008da6c28aaSamw 	    -MBC_LENGTH(&xa->rep_data_mb),
1009da6c28aaSamw 	    MBC_LENGTH(&xa->rep_data_mb) + MBC_LENGTH(&str_mb));
10103db3f65cSamw 	(void) smb_mbc_encodef(&xa->rep_data_mb, "C", &str_mb);
1011da6c28aaSamw 	m_freem(str_mb.chain);
1012faa1795aSjb150015 	return (SDRC_SUCCESS);
1013da6c28aaSamw }
1014da6c28aaSamw 
1015da6c28aaSamw int
10163ad684d6Sjb150015 smb_trans_net_workstation_getinfo(struct smb_request *sr, struct smb_xa *xa)
1017da6c28aaSamw {
10183ad684d6Sjb150015 	uint16_t		level, max_bytes;
1019da6c28aaSamw 	struct mbuf_chain	str_mb;
1020da6c28aaSamw 	char *domain;
1021da6c28aaSamw 	char *hostname;
1022da6c28aaSamw 
10233db3f65cSamw 	if ((smb_mbc_decodef(&xa->req_param_mb, "ww",
10243ad684d6Sjb150015 	    &level, &max_bytes) != 0) ||
1025da6c28aaSamw 	    (level != 10)) {
10263db3f65cSamw 		(void) smb_mbc_encodef(&xa->rep_param_mb, "wwww",
1027da6c28aaSamw 		    NERR_BadTransactConfig, 0, 0, 0);
1028faa1795aSjb150015 		return (SDRC_SUCCESS);
1029da6c28aaSamw 	}
1030da6c28aaSamw 
1031b89a8333Snatalie li - Sun Microsystems - Irvine United States 	domain = sr->sr_cfg->skc_nbdomain;
1032faa1795aSjb150015 	hostname = sr->sr_cfg->skc_hostname;
1033da6c28aaSamw 
1034da6c28aaSamw 	MBC_INIT(&str_mb, max_bytes);
1035da6c28aaSamw 
10363db3f65cSamw 	(void) smb_mbc_encodef(&str_mb, "."); /* Prevent NULL pointers */
1037da6c28aaSamw 
10383db3f65cSamw 	(void) smb_mbc_encodef(&xa->rep_data_mb, "l", MBC_LENGTH(&str_mb));
10393db3f65cSamw 	(void) smb_mbc_encodef(&str_mb, "s", hostname);
10403db3f65cSamw 	(void) smb_mbc_encodef(&xa->rep_data_mb, "l", MBC_LENGTH(&str_mb));
10413db3f65cSamw 	(void) smb_mbc_encodef(&str_mb, "s", "nobody");
10423db3f65cSamw 	(void) smb_mbc_encodef(&xa->rep_data_mb, "l", MBC_LENGTH(&str_mb));
10433db3f65cSamw 	(void) smb_mbc_encodef(&str_mb, "s", domain);
10443db3f65cSamw 	(void) smb_mbc_encodef(&xa->rep_data_mb, "bbl",
1045fd9ee8b5Sjoyce mcintosh 	    (uint8_t)sr->sr_cfg->skc_version.sv_major,
1046fd9ee8b5Sjoyce mcintosh 	    (uint8_t)sr->sr_cfg->skc_version.sv_minor,
10479fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States 	    MBC_LENGTH(&str_mb));
10483db3f65cSamw 	(void) smb_mbc_encodef(&str_mb, "s", domain);
10493db3f65cSamw 	(void) smb_mbc_encodef(&xa->rep_data_mb, "l", MBC_LENGTH(&str_mb));
10503db3f65cSamw 	(void) smb_mbc_encodef(&str_mb, "s", domain);
1051da6c28aaSamw 
10523db3f65cSamw 	(void) smb_mbc_encodef(&xa->rep_param_mb, "www", 0,
1053da6c28aaSamw 	    -MBC_LENGTH(&xa->rep_data_mb),
1054da6c28aaSamw 	    MBC_LENGTH(&xa->rep_data_mb) + MBC_LENGTH(&str_mb));
10553db3f65cSamw 	(void) smb_mbc_encodef(&xa->rep_data_mb, "C", &str_mb);
1056da6c28aaSamw 	m_freem(str_mb.chain);
1057faa1795aSjb150015 	return (SDRC_SUCCESS);
1058da6c28aaSamw }
1059da6c28aaSamw 
1060da6c28aaSamw int
10613ad684d6Sjb150015 smb_trans_net_user_getinfo(struct smb_request *sr, struct smb_xa *xa)
1062da6c28aaSamw {
10633ad684d6Sjb150015 	uint16_t		level, max_bytes;
1064da6c28aaSamw 	unsigned char		*user;
1065da6c28aaSamw 	int rc;
1066da6c28aaSamw 
10673db3f65cSamw 	rc = smb_mbc_decodef(&xa->req_param_mb, "%sww", sr,
1068da6c28aaSamw 	    &user,
1069da6c28aaSamw 	    &level,
1070da6c28aaSamw 	    &max_bytes);
1071da6c28aaSamw 
1072da6c28aaSamw 	if (rc != 0)
1073faa1795aSjb150015 		return (SDRC_NOT_IMPLEMENTED);
1074da6c28aaSamw 
10753db3f65cSamw 	(void) smb_mbc_encodef(&xa->rep_param_mb, "www",
1076da6c28aaSamw 	    NERR_UserNotFound, 0, 0);
1077faa1795aSjb150015 	return (SDRC_SUCCESS);
1078da6c28aaSamw }
1079da6c28aaSamw 
10807b59d02dSjb150015 smb_sdrc_t
10813ad684d6Sjb150015 smb_trans_net_server_getinfo(struct smb_request *sr, struct smb_xa *xa)
1082da6c28aaSamw {
10833ad684d6Sjb150015 	uint16_t		level, buf_size;
10843ad684d6Sjb150015 	uint16_t		avail_data, max_data;
1085da6c28aaSamw 	char			server_name[16];
1086da6c28aaSamw 	struct mbuf_chain	str_mb;
1087da6c28aaSamw 
10883db3f65cSamw 	if (smb_mbc_decodef(&xa->req_param_mb, "ww", &level, &buf_size) != 0)
1089faa1795aSjb150015 		return (SDRC_ERROR);
1090da6c28aaSamw 
10913ad684d6Sjb150015 	max_data = MBC_MAXBYTES(&xa->rep_data_mb);
1092da6c28aaSamw 
1093da6c28aaSamw 	MBC_INIT(&str_mb, buf_size);
1094da6c28aaSamw 
1095da6c28aaSamw 	bzero(server_name, sizeof (server_name));
10963ad684d6Sjb150015 	(void) strncpy(server_name, sr->sr_cfg->skc_hostname,
10973ad684d6Sjb150015 	    sizeof (server_name));
1098da6c28aaSamw 
10993ad684d6Sjb150015 	/* valid levels are 0 and 1 */
1100da6c28aaSamw 	switch (level) {
1101da6c28aaSamw 	case 0:
11023db3f65cSamw 		(void) smb_mbc_encodef(&xa->rep_data_mb, "16c", server_name);
1103da6c28aaSamw 		break;
11043ad684d6Sjb150015 
1105da6c28aaSamw 	case 1:
11063db3f65cSamw 		(void) smb_mbc_encodef(&str_mb, "s",
11073ad684d6Sjb150015 		    sr->sr_cfg->skc_system_comment);
11083db3f65cSamw 		(void) smb_mbc_encodef(&xa->rep_data_mb, "16cbbll", server_name,
1109fd9ee8b5Sjoyce mcintosh 		    (uint8_t)sr->sr_cfg->skc_version.sv_major,
1110fd9ee8b5Sjoyce mcintosh 		    (uint8_t)sr->sr_cfg->skc_version.sv_minor,
11113ad684d6Sjb150015 		    MY_SERVER_TYPE, max_data - MBC_LENGTH(&str_mb));
1112da6c28aaSamw 		break;
11133ad684d6Sjb150015 
1114da6c28aaSamw 	default:
11153db3f65cSamw 		(void) smb_mbc_encodef(&xa->rep_param_mb, "www",
11163ad684d6Sjb150015 		    ERROR_INVALID_LEVEL, 0, 0);
1117da6c28aaSamw 		m_freem(str_mb.chain);
11183ad684d6Sjb150015 		return (SDRC_SUCCESS);
1119da6c28aaSamw 	}
1120da6c28aaSamw 
11213ad684d6Sjb150015 	avail_data = MBC_LENGTH(&xa->rep_data_mb) + MBC_LENGTH(&str_mb);
11223db3f65cSamw 	(void) smb_mbc_encodef(&xa->rep_param_mb, "www",
11233ad684d6Sjb150015 	    NERR_Success, max_data - avail_data, avail_data);
11243db3f65cSamw 	(void) smb_mbc_encodef(&xa->rep_data_mb, "C", &str_mb);
1125da6c28aaSamw 	m_freem(str_mb.chain);
1126faa1795aSjb150015 	return (SDRC_SUCCESS);
1127da6c28aaSamw }
1128da6c28aaSamw 
1129da6c28aaSamw /*
1130da6c28aaSamw  * 6.4 The NetServerEnum2 RAP Service
1131da6c28aaSamw  *
1132da6c28aaSamw  * The NetServerEnum2 RAP service lists all computers of the specified type
1133da6c28aaSamw  * or types that are visible in the specified domains. It may also
1134da6c28aaSamw  * enumerate domains.
1135da6c28aaSamw  *
1136da6c28aaSamw  * The following definition uses the notation and terminology defined in
1137da6c28aaSamw  * the CIFS Remote Administration Protocol specification, which is required
1138da6c28aaSamw  * in order to make it well-defined. The definition is:
1139da6c28aaSamw  *
1140da6c28aaSamw  *     uint16_t NetServerEnum2 (
1141da6c28aaSamw  *         uint16_t  sLevel,
1142da6c28aaSamw  *         RCVBUF          pbBuffer,
1143da6c28aaSamw  *         RCVBUFLEN       cbBuffer,
1144da6c28aaSamw  *         ENTCOUNT        pcEntriesRead,
1145da6c28aaSamw  *         uint16_t  *pcTotalAvail,
1146da6c28aaSamw  *         uint32_t   fServerType,
1147da6c28aaSamw  *         char            *pszDomain,
1148da6c28aaSamw  *     );
1149da6c28aaSamw  *
1150da6c28aaSamw  * where:
1151da6c28aaSamw  *
1152da6c28aaSamw  *    sLevel specifies the level of detail (0 or 1) requested.
1153da6c28aaSamw  *
1154da6c28aaSamw  *    pbBuffer points to the buffer to receive the returned data. If the
1155da6c28aaSamw  *    function is successful, the buffer contains a sequence of
1156da6c28aaSamw  *    server_info_x structures, where x is 0 or 1, depending on the
1157da6c28aaSamw  *    level of detail requested.
1158da6c28aaSamw  *
1159da6c28aaSamw  *    cbBuffer specifies the size, in bytes, of the buffer pointed to by
1160da6c28aaSamw  *    the pbBuffer parameter.
1161da6c28aaSamw  *
1162da6c28aaSamw  *    pcEntriesRead points to a 16 bit variable that receives a count of
1163da6c28aaSamw  *    the number of servers enumerated in the buffer. This count is
1164da6c28aaSamw  *    valid only if NetServerEnum2 returns the NERR_Success or
1165da6c28aaSamw  *    ERROR_MORE_DATA values.
1166da6c28aaSamw  *
1167da6c28aaSamw  *    pcTotal Avail points to a 16 bit variable that receives a count of
1168da6c28aaSamw  *    the total number of available entries. This count is valid only if
1169da6c28aaSamw  *    NetServerEnum2 returns the NERR_Success or ERROR_MORE_DATA values.
1170da6c28aaSamw  *
1171da6c28aaSamw  *     fServerType specifies the type or types of computers to enumerate.
1172da6c28aaSamw  *     Computers that match at least one of the specified types are
1173da6c28aaSamw  *     returned in the buffer. Possible values are defined in the request
1174da6c28aaSamw  *     parameters section.
1175da6c28aaSamw  *
1176da6c28aaSamw  *    pszDomain points to a null-terminated string that contains the
1177da6c28aaSamw  *    name of the workgroup in which to enumerate computers of the
1178da6c28aaSamw  *    specified type or types. If the pszDomain parameter is a null
1179da6c28aaSamw  *    string or a null pointer, servers are enumerated for the current
1180da6c28aaSamw  *    domain of the computer.
1181da6c28aaSamw  *
1182da6c28aaSamw  * 6.4.1 Transaction Request Parameters section
1183da6c28aaSamw  *
1184da6c28aaSamw  * The Transaction request parameters section in this instance contains:
1185da6c28aaSamw  * . The 16 bit function number for NetServerEnum2 which is 104.
1186da6c28aaSamw  * . The parameter descriptor string which is "WrLehDz".
1187da6c28aaSamw  * . The data descriptor string for the (returned) data which is "B16" for
1188da6c28aaSamw  *   level detail 0 or "B16BBDz" for level detail 1.
1189da6c28aaSamw  * . The actual parameters as described by the parameter descriptor
1190da6c28aaSamw  *   string.
1191da6c28aaSamw  *
1192da6c28aaSamw  * The parameters are:
1193da6c28aaSamw  * . A 16 bit integer with a value of 0 or 1 (corresponding to the "W" in
1194da6c28aaSamw  *   the parameter descriptor string. This represents the level of detail
1195da6c28aaSamw  *   the server is expected to return
1196da6c28aaSamw  * . A 16 bit integer that contains the size of the receive buffer.
1197da6c28aaSamw  * . A 32 bit integer that represents the type of servers the function
1198da6c28aaSamw  *   should enumerate. The possible values may be any of the following or
1199da6c28aaSamw  *   a combination of the following:
1200da6c28aaSamw  *
1201da6c28aaSamw  * SV_TYPE_WORKSTATION        0x00000001 All workstations
1202da6c28aaSamw  * SV_TYPE_SERVER             0x00000002 All servers
1203da6c28aaSamw  * SV_TYPE_SQLSERVER          0x00000004 Any server running with SQL
1204da6c28aaSamw  *                                       server
1205da6c28aaSamw  * SV_TYPE_DOMAIN_CTRL        0x00000008 Primary domain controller
1206da6c28aaSamw  * SV_TYPE_DOMAIN_BAKCTRL     0x00000010 Backup domain controller
1207da6c28aaSamw  * SV_TYPE_TIME_SOURCE        0x00000020 Server running the timesource
1208da6c28aaSamw  *                                       service
1209da6c28aaSamw  * SV_TYPE_AFP                0x00000040 Apple File Protocol servers
1210da6c28aaSamw  * SV_TYPE_NOVELL             0x00000080 Novell servers
1211da6c28aaSamw  * SV_TYPE_DOMAIN_MEMBER      0x00000100 Domain Member
1212da6c28aaSamw  * SV_TYPE_PRINTQ_SERVER      0x00000200 Server sharing print queue
1213da6c28aaSamw  * SV_TYPE_DIALIN_SERVER      0x00000400 Server running dialin service.
1214da6c28aaSamw  * SV_TYPE_XENIX_SERVER       0x00000800 Xenix server
1215da6c28aaSamw  * SV_TYPE_NT                 0x00001000 NT server
1216da6c28aaSamw  * SV_TYPE_WFW                0x00002000 Server running Windows for
1217da6c28aaSamw  *                                       Workgroups
1218da6c28aaSamw  * SV_TYPE_SERVER_NT          0x00008000 Windows NT non DC server
1219da6c28aaSamw  * SV_TYPE_POTENTIAL_BROWSER  0x00010000 Server that can run the browser
1220da6c28aaSamw  *                                       service
1221da6c28aaSamw  * SV_TYPE_BACKUP_BROWSER     0x00020000 Backup browser server
1222da6c28aaSamw  * SV_TYPE_MASTER_BROWSER     0x00040000 Master browser server
1223da6c28aaSamw  * SV_TYPE_DOMAIN_MASTER      0x00080000 Domain Master Browser server
1224da6c28aaSamw  * SV_TYPE_LOCAL_LIST_ONLY    0x40000000 Enumerate only entries marked
1225da6c28aaSamw  *                                       "local"
1226da6c28aaSamw  * SV_TYPE_DOMAIN_ENUM        0x80000000 Enumerate Domains. The pszDomain
1227da6c28aaSamw  *                                       parameter must be NULL.
1228da6c28aaSamw  *
1229da6c28aaSamw  * . A null terminated ASCII string representing the pszDomain parameter
1230da6c28aaSamw  *   described above
1231da6c28aaSamw  *
1232da6c28aaSamw  * 6.4.2 Transaction Request Data section
1233da6c28aaSamw  *
1234da6c28aaSamw  * There is no data or auxiliary data to send as part of the request.
1235da6c28aaSamw  *
1236da6c28aaSamw  * 6.4.3 Transaction Response Parameters section
1237da6c28aaSamw  *
1238da6c28aaSamw  * The transaction response parameters section consists of:
1239da6c28aaSamw  * . A 16 bit word indicating the return status. The possible values are:
1240da6c28aaSamw  *
1241da6c28aaSamw  * Code                   Value  Description
1242da6c28aaSamw  * NERR_Success           0      No errors encountered
1243da6c28aaSamw  * ERROR_MORE_DATA        234    Additional data is available
1244da6c28aaSamw  * NERR_ServerNotStarted  2114   The RAP service on the remote computer
1245da6c28aaSamw  *                               is not running
1246da6c28aaSamw  * NERR_BadTransactConfig 2141   The server is not configured for
1247da6c28aaSamw  *                               transactions, IPC$ is not shared
1248da6c28aaSamw  *
1249da6c28aaSamw  * . A 16 bit "converter" word.
1250da6c28aaSamw  * . A 16 bit number representing the number of entries returned.
1251da6c28aaSamw  * . A 16 bit number representing the total number of available entries.
1252da6c28aaSamw  *   If the supplied buffer is large enough, this will equal the number of
1253da6c28aaSamw  *   entries returned.
1254da6c28aaSamw  *
1255da6c28aaSamw  * 6.4.4 Transaction Response Data section
1256da6c28aaSamw  *
1257da6c28aaSamw  * The return data section consists of a number of SERVER_INFO_1 structures.
1258da6c28aaSamw  * The number of such structures present is determined by the third entry
1259da6c28aaSamw  * (described above) in the return parameters section.
1260da6c28aaSamw  *
1261da6c28aaSamw  * At level detail 0, the Transaction response data section contains a
1262da6c28aaSamw  * number of SERVER_INFO_0 data structure. The number of such structures is
1263da6c28aaSamw  * equal to the 16 bit number returned by the server in the third parameter
1264da6c28aaSamw  * in the Transaction response parameter section. The SERVER_INFO_0 data
1265da6c28aaSamw  * structure is defined as:
1266da6c28aaSamw  *
1267da6c28aaSamw  *     struct SERVER_INFO_0 {
1268da6c28aaSamw  *         char        sv0_name[16];
1269da6c28aaSamw  *     };
1270da6c28aaSamw  *
1271da6c28aaSamw  *  where:
1272da6c28aaSamw  *
1273da6c28aaSamw  *    sv0_name is a null-terminated string that specifies the name of a
1274da6c28aaSamw  *    computer or domain .
1275da6c28aaSamw  *
1276da6c28aaSamw  * At level detail 1, the Transaction response data section contains a
1277da6c28aaSamw  * number of SERVER_INFO_1 data structure. The number of such structures is
1278da6c28aaSamw  * equal to the 16 bit number returned by the server in the third parameter
1279da6c28aaSamw  * in the Transaction response parameter section. The SERVER_INFO_1 data
1280da6c28aaSamw  * structure is defined as:
1281da6c28aaSamw  *
1282da6c28aaSamw  *     struct SERVER_INFO_1 {
1283da6c28aaSamw  *         char            sv1_name[16];
1284da6c28aaSamw  *         char            sv1_version_major;
1285da6c28aaSamw  *         char            sv1_version_minor;
1286da6c28aaSamw  *         uint32_t   sv1_type;
1287da6c28aaSamw  *         char        *sv1_comment_or_master_browser;
1288da6c28aaSamw  *     };
1289da6c28aaSamw  *
1290da6c28aaSamw  *    sv1_name contains a null-terminated string that specifies the name
1291da6c28aaSamw  *    of a computer, or a domain name if SV_TYPE_DOMAIN_ENUM is set in
1292da6c28aaSamw  *    sv1_type.
1293da6c28aaSamw  *
1294da6c28aaSamw  *    sv1_version_major whatever was specified in the HostAnnouncement
1295da6c28aaSamw  *    or DomainAnnouncement frame with which the entry was registered.
1296da6c28aaSamw  *
1297da6c28aaSamw  *    sv1_version_minor whatever was specified in the HostAnnouncement
1298da6c28aaSamw  *    or DomainAnnouncement frame with which the entry was registered.
1299da6c28aaSamw  *
1300da6c28aaSamw  *    sv1_type specifies the type of software the computer is running.
1301da6c28aaSamw  *    The member can be one or a combination of the values defined above
1302da6c28aaSamw  *    in the Transaction request parameters section for fServerType.
1303da6c28aaSamw  *
1304da6c28aaSamw  *
1305da6c28aaSamw  *    sv1_comment_or_master_browser points to a null-terminated string. If
1306da6c28aaSamw  *    the sv1_type indicates that the entry is for a domain, this
1307da6c28aaSamw  *    specifies the name of server running the domain master browser;
1308da6c28aaSamw  *    otherwise, it specifies a comment describing the server. The comment
1309da6c28aaSamw  *    can be a null string or the pointer may be a null pointer.
1310da6c28aaSamw  *
1311da6c28aaSamw  *    In case there are multiple SERVER_INFO_1 data structures to
1312da6c28aaSamw  *    return, the server may put all these fixed length structures in
1313da6c28aaSamw  *    the return buffer, leave some space and then put all the variable
1314da6c28aaSamw  *    length data (the actual value of the sv1_comment strings) at the
1315da6c28aaSamw  *    end of the buffer.
1316da6c28aaSamw  *
1317da6c28aaSamw  * There is no auxiliary data to receive.
1318da6c28aaSamw  */
1319da6c28aaSamw 
1320da6c28aaSamw int
1321da6c28aaSamw smb_trans_net_server_enum2(struct smb_request *sr, struct smb_xa *xa)
1322da6c28aaSamw {
1323da6c28aaSamw 	uint16_t opcode, level, max_bytes;
1324da6c28aaSamw 	uint32_t server_type;
1325da6c28aaSamw 	unsigned char *domain;
1326da6c28aaSamw 	struct mbuf_chain str_mb;
1327da6c28aaSamw 	char *hostname, *s;
1328da6c28aaSamw 	smb_kmod_cfg_t *si;
1329da6c28aaSamw 
13303db3f65cSamw 	if (smb_mbc_decodef(&xa->req_param_mb,
13313db3f65cSamw 	    "%wsswwls", sr, &opcode, &s, &s,
1332da6c28aaSamw 	    &level, &max_bytes, &server_type, &domain) != 0)
1333faa1795aSjb150015 		return (SDRC_NOT_IMPLEMENTED);
1334da6c28aaSamw 
1335faa1795aSjb150015 	si = sr->sr_cfg;
1336da6c28aaSamw 
1337bbf6f00cSJordan Brown 	if (smb_strcasecmp(si->skc_nbdomain, (char *)domain, 0) != 0) {
13383db3f65cSamw 		(void) smb_mbc_encodef(&xa->rep_param_mb, "wwww", 0, 0, 0, 0);
1339faa1795aSjb150015 		return (SDRC_SUCCESS);
1340da6c28aaSamw 	}
1341da6c28aaSamw 
1342da6c28aaSamw 	if ((server_type & MY_SERVER_TYPE) == 0) {
13433db3f65cSamw 		(void) smb_mbc_encodef(&xa->rep_param_mb, "wwww", 0, 0, 0, 0);
1344faa1795aSjb150015 		return (SDRC_SUCCESS);
1345da6c28aaSamw 	}
1346da6c28aaSamw 
1347da6c28aaSamw 	MBC_INIT(&str_mb, max_bytes);
1348da6c28aaSamw 
1349da6c28aaSamw 	hostname = si->skc_hostname;
1350da6c28aaSamw 
13513db3f65cSamw 	(void) smb_mbc_encodef(&xa->rep_data_mb, "16c", hostname);
1352da6c28aaSamw 	if (level == 1) {
13533db3f65cSamw 		(void) smb_mbc_encodef(&xa->rep_data_mb, "bbll",
1354fd9ee8b5Sjoyce mcintosh 		    (uint8_t)sr->sr_cfg->skc_version.sv_major,
1355fd9ee8b5Sjoyce mcintosh 		    (uint8_t)sr->sr_cfg->skc_version.sv_minor,
1356da6c28aaSamw 		    MY_SERVER_TYPE, MBC_LENGTH(&str_mb));
13573db3f65cSamw 		(void) smb_mbc_encodef(&str_mb, "s", si->skc_system_comment);
1358da6c28aaSamw 	}
1359da6c28aaSamw 
13603db3f65cSamw 	(void) smb_mbc_encodef(&xa->rep_param_mb, "wwww", 0,
1361da6c28aaSamw 	    -MBC_LENGTH(&xa->rep_data_mb), 1, 1);
13623db3f65cSamw 	(void) smb_mbc_encodef(&xa->rep_data_mb, "m", str_mb.chain);
1363faa1795aSjb150015 	return (SDRC_SUCCESS);
1364da6c28aaSamw }
1365da6c28aaSamw 
1366bbf6f00cSJordan Brown static boolean_t
1367bbf6f00cSJordan Brown is_supported_mailslot(const char *mailslot)
1368da6c28aaSamw {
1369bbf6f00cSJordan Brown 	static char *mailslots[] = {
1370bbf6f00cSJordan Brown 		PIPE_LANMAN,
1371bbf6f00cSJordan Brown 		MAILSLOT_LANMAN,
1372bbf6f00cSJordan Brown 		MAILSLOT_BROWSE,
1373bbf6f00cSJordan Brown 		MAILSLOT_MSBROWSE
1374bbf6f00cSJordan Brown 	};
1375da6c28aaSamw 
1376bbf6f00cSJordan Brown 	int i;
1377bbf6f00cSJordan Brown 
1378bbf6f00cSJordan Brown 	for (i = 0; i < sizeof (mailslots)/sizeof (mailslots[0]); ++i)
1379bbf6f00cSJordan Brown 		if (smb_strcasecmp(mailslot, mailslots[i], 0) == 0)
1380bbf6f00cSJordan Brown 			return (B_TRUE);
1381bbf6f00cSJordan Brown 
1382bbf6f00cSJordan Brown 	return (B_FALSE);
1383bbf6f00cSJordan Brown }
1384bbf6f00cSJordan Brown 
1385bbf6f00cSJordan Brown /*
138668b2bbf2SGordon Ross  * smb_trans_nmpipe
138768b2bbf2SGordon Ross  *
138868b2bbf2SGordon Ross  * This is used for RPC bind and request transactions.
138968b2bbf2SGordon Ross  *
139068b2bbf2SGordon Ross  * If the data available from the pipe is larger than the maximum
139168b2bbf2SGordon Ross  * data size requested by the client, return as much as requested.
139268b2bbf2SGordon Ross  * The residual data remains in the pipe until the client comes back
139368b2bbf2SGordon Ross  * with a read request or closes the pipe.
139468b2bbf2SGordon Ross  *
139568b2bbf2SGordon Ross  * When we read less than what's available, we MUST return the
139668b2bbf2SGordon Ross  * status NT_STATUS_BUFFER_OVERFLOW (or ERRDOS/ERROR_MORE_DATA)
1397bbf6f00cSJordan Brown  */
139868b2bbf2SGordon Ross static smb_sdrc_t
139968b2bbf2SGordon Ross smb_trans_nmpipe(smb_request_t *sr, smb_xa_t *xa)
1400bbf6f00cSJordan Brown {
140168b2bbf2SGordon Ross 	smb_vdb_t	vdb;
140268b2bbf2SGordon Ross 	struct mbuf	*mb;
140368b2bbf2SGordon Ross 	int rc;
1404bbf6f00cSJordan Brown 
140568b2bbf2SGordon Ross 	smbsr_lookup_file(sr);
140668b2bbf2SGordon Ross 	if (sr->fid_ofile == NULL) {
140768b2bbf2SGordon Ross 		smbsr_error(sr, NT_STATUS_INVALID_HANDLE,
140868b2bbf2SGordon Ross 		    ERRDOS, ERRbadfid);
140968b2bbf2SGordon Ross 		return (SDRC_ERROR);
141068b2bbf2SGordon Ross 	}
141168b2bbf2SGordon Ross 
141268b2bbf2SGordon Ross 	rc = smb_mbc_decodef(&xa->req_data_mb, "#B",
141368b2bbf2SGordon Ross 	    xa->smb_tdscnt, &vdb);
141468b2bbf2SGordon Ross 	if (rc != 0) {
141568b2bbf2SGordon Ross 		/* Not enough data sent. */
141668b2bbf2SGordon Ross 		smbsr_error(sr, 0, ERRSRV, ERRerror);
141768b2bbf2SGordon Ross 		return (SDRC_ERROR);
141868b2bbf2SGordon Ross 	}
141968b2bbf2SGordon Ross 
142068b2bbf2SGordon Ross 	rc = smb_opipe_write(sr, &vdb.vdb_uio);
142168b2bbf2SGordon Ross 	if (rc != 0) {
142268b2bbf2SGordon Ross 		smbsr_errno(sr, rc);
142368b2bbf2SGordon Ross 		return (SDRC_ERROR);
142468b2bbf2SGordon Ross 	}
142568b2bbf2SGordon Ross 
142668b2bbf2SGordon Ross 	vdb.vdb_tag = 0;
142768b2bbf2SGordon Ross 	vdb.vdb_uio.uio_iov = &vdb.vdb_iovec[0];
142868b2bbf2SGordon Ross 	vdb.vdb_uio.uio_iovcnt = MAX_IOVEC;
142968b2bbf2SGordon Ross 	vdb.vdb_uio.uio_segflg = UIO_SYSSPACE;
143068b2bbf2SGordon Ross 	vdb.vdb_uio.uio_extflg = UIO_COPY_DEFAULT;
143168b2bbf2SGordon Ross 	vdb.vdb_uio.uio_loffset = (offset_t)0;
143268b2bbf2SGordon Ross 	vdb.vdb_uio.uio_resid = xa->smb_mdrcnt;
143368b2bbf2SGordon Ross 	mb = smb_mbuf_allocate(&vdb.vdb_uio);
143468b2bbf2SGordon Ross 
143568b2bbf2SGordon Ross 	rc = smb_opipe_read(sr, &vdb.vdb_uio);
143668b2bbf2SGordon Ross 	if (rc != 0) {
1437*bce01b59SGordon Ross 		m_freem(mb);
143868b2bbf2SGordon Ross 		smbsr_errno(sr, rc);
143968b2bbf2SGordon Ross 		return (SDRC_ERROR);
144068b2bbf2SGordon Ross 	}
144168b2bbf2SGordon Ross 
144268b2bbf2SGordon Ross 	smb_mbuf_trim(mb, xa->smb_mdrcnt - vdb.vdb_uio.uio_resid);
144368b2bbf2SGordon Ross 	MBC_ATTACH_MBUF(&xa->rep_data_mb, mb);
144468b2bbf2SGordon Ross 
1445*bce01b59SGordon Ross 	/*
1446*bce01b59SGordon Ross 	 * If the output buffer holds a partial pipe message,
1447*bce01b59SGordon Ross 	 * we're supposed to return NT_STATUS_BUFFER_OVERFLOW.
1448*bce01b59SGordon Ross 	 * As we don't have message boundary markers, the best
1449*bce01b59SGordon Ross 	 * we can do is return that status when we have ALL of:
1450*bce01b59SGordon Ross 	 *	Output buffer was < SMB_PIPE_MAX_MSGSIZE
1451*bce01b59SGordon Ross 	 *	We filled the output buffer (resid==0)
1452*bce01b59SGordon Ross 	 *	There's more data (ioctl FIONREAD)
1453*bce01b59SGordon Ross 	 */
1454*bce01b59SGordon Ross 	if (xa->smb_mdrcnt < SMB_PIPE_MAX_MSGSIZE &&
1455*bce01b59SGordon Ross 	    vdb.vdb_uio.uio_resid == 0) {
1456*bce01b59SGordon Ross 		int nread = 0;
1457*bce01b59SGordon Ross 		rc = smb_opipe_get_nread(sr, &nread);
1458*bce01b59SGordon Ross 		if (rc == 0 && nread != 0) {
1459*bce01b59SGordon Ross 			smbsr_status(sr, NT_STATUS_BUFFER_OVERFLOW,
1460*bce01b59SGordon Ross 			    ERRDOS, ERROR_MORE_DATA);
1461*bce01b59SGordon Ross 		}
1462*bce01b59SGordon Ross 	}
1463*bce01b59SGordon Ross 
146468b2bbf2SGordon Ross 	return (SDRC_SUCCESS);
1465da6c28aaSamw }
1466da6c28aaSamw 
14677b59d02dSjb150015 static smb_sdrc_t
14689fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States smb_trans_dispatch(smb_request_t *sr, smb_xa_t *xa)
1469da6c28aaSamw {
1470da6c28aaSamw 	int		rc, pos;
1471da6c28aaSamw 	int		total_bytes, n_setup, n_param, n_data;
1472da6c28aaSamw 	int		param_off, param_pad, data_off, data_pad;
1473da6c28aaSamw 	uint16_t	opcode;
1474da6c28aaSamw 	uint16_t	devstate;
1475da6c28aaSamw 	char		*req_fmt;
1476da6c28aaSamw 	char		*rep_fmt;
1477da6c28aaSamw 
1478da6c28aaSamw 	if (xa->smb_suwcnt > 0 && STYPE_ISIPC(sr->tid_tree->t_res_type)) {
14793db3f65cSamw 		rc = smb_mbc_decodef(&xa->req_setup_mb, "ww", &opcode,
1480da6c28aaSamw 		    &sr->smb_fid);
1481da6c28aaSamw 		if (rc != 0)
1482da6c28aaSamw 			goto trans_err_not_supported;
1483da6c28aaSamw 		switch (opcode) {
1484da6c28aaSamw 		case TRANS_SET_NMPIPE_STATE:
14853db3f65cSamw 			if ((rc = smb_mbc_decodef(&xa->req_param_mb, "w",
1486da6c28aaSamw 			    &devstate)) != 0)
1487da6c28aaSamw 				goto trans_err_not_supported;
1488da6c28aaSamw 
1489faa1795aSjb150015 			rc = SDRC_SUCCESS;
1490da6c28aaSamw 			break;
1491da6c28aaSamw 
1492da6c28aaSamw 		case TRANS_TRANSACT_NMPIPE:
149368b2bbf2SGordon Ross 			rc = smb_trans_nmpipe(sr, xa);
1494da6c28aaSamw 			break;
1495da6c28aaSamw 
1496da6c28aaSamw 		case TRANS_WAIT_NMPIPE:
149768b2bbf2SGordon Ross 			delay(SEC_TO_TICK(1));
1498faa1795aSjb150015 			rc = SDRC_SUCCESS;
1499da6c28aaSamw 			break;
1500da6c28aaSamw 
1501da6c28aaSamw 		default:
1502da6c28aaSamw 			goto trans_err_not_supported;
1503da6c28aaSamw 		}
1504da6c28aaSamw 	} else {
1505bbf6f00cSJordan Brown 		if (!is_supported_mailslot(xa->xa_pipe_name))
1506da6c28aaSamw 			goto trans_err_not_supported;
1507da6c28aaSamw 
15083db3f65cSamw 		if ((rc = smb_mbc_decodef(&xa->req_param_mb, "%wss", sr,
1509da6c28aaSamw 		    &opcode, &req_fmt, &rep_fmt)) != 0)
1510da6c28aaSamw 			goto trans_err_not_supported;
1511da6c28aaSamw 
1512da6c28aaSamw 		switch (opcode) {
1513da6c28aaSamw 		case API_WshareEnum:
1514da6c28aaSamw 			rc = smb_trans_net_share_enum(sr, xa);
1515da6c28aaSamw 			break;
1516da6c28aaSamw 
1517da6c28aaSamw 		case API_WshareGetInfo:
15183ad684d6Sjb150015 			rc = smb_trans_net_share_getinfo(sr, xa);
1519da6c28aaSamw 			break;
1520da6c28aaSamw 
1521da6c28aaSamw 		case API_WserverGetInfo:
15223ad684d6Sjb150015 			rc = smb_trans_net_server_getinfo(sr, xa);
1523da6c28aaSamw 			break;
1524da6c28aaSamw 
1525da6c28aaSamw 		case API_WUserGetInfo:
15263ad684d6Sjb150015 			rc = smb_trans_net_user_getinfo(sr, xa);
1527da6c28aaSamw 			break;
1528da6c28aaSamw 
1529da6c28aaSamw 		case API_WWkstaGetInfo:
15303ad684d6Sjb150015 			rc = smb_trans_net_workstation_getinfo(sr, xa);
1531da6c28aaSamw 			break;
1532da6c28aaSamw 
1533da6c28aaSamw 		case API_NetServerEnum2:
1534da6c28aaSamw 			rc = smb_trans_net_server_enum2(sr, xa);
1535da6c28aaSamw 			break;
1536da6c28aaSamw 
1537da6c28aaSamw 		default:
1538da6c28aaSamw 			goto trans_err_not_supported;
1539da6c28aaSamw 		}
1540da6c28aaSamw 	}
1541da6c28aaSamw 
1542da6c28aaSamw 	switch (rc) {
1543faa1795aSjb150015 	case SDRC_SUCCESS:
1544da6c28aaSamw 		break;
1545da6c28aaSamw 
1546da6c28aaSamw 	case SDRC_DROP_VC:
1547da6c28aaSamw 	case SDRC_NO_REPLY:
1548faa1795aSjb150015 	case SDRC_ERROR:
1549da6c28aaSamw 		return (rc);
1550da6c28aaSamw 
1551faa1795aSjb150015 	case SDRC_NOT_IMPLEMENTED:
1552da6c28aaSamw 		goto trans_err_not_supported;
1553da6c28aaSamw 
1554da6c28aaSamw 	default:
1555da6c28aaSamw 		break;
1556da6c28aaSamw 	}
1557da6c28aaSamw 
1558da6c28aaSamw 	n_setup = MBC_LENGTH(&xa->rep_setup_mb);
1559da6c28aaSamw 	n_param = MBC_LENGTH(&xa->rep_param_mb);
1560da6c28aaSamw 	n_data  = MBC_LENGTH(&xa->rep_data_mb);
1561da6c28aaSamw 
1562da6c28aaSamw 	if (xa->smb_msrcnt < n_setup ||
1563da6c28aaSamw 	    xa->smb_mprcnt < n_param ||
1564da6c28aaSamw 	    xa->smb_mdrcnt < n_data) {
1565da6c28aaSamw 		goto trans_err_too_small;
1566da6c28aaSamw 	}
1567da6c28aaSamw 
1568da6c28aaSamw 	/* neato, blast it over there */
1569da6c28aaSamw 
1570da6c28aaSamw 	n_setup = (n_setup + 1) / 2;		/* Convert to setup words */
1571da6c28aaSamw 	param_pad = 1;				/* always one */
1572da6c28aaSamw 	param_off = param_pad + 32 + 21 + (n_setup << 1) + 2;
1573da6c28aaSamw 	data_pad = (param_off + n_param) & 1;	/* Pad to short */
1574da6c28aaSamw 	/* Param off from hdr start */
1575da6c28aaSamw 	data_off = param_off + n_param + data_pad;
1576da6c28aaSamw 	total_bytes = param_pad + n_param + data_pad + n_data;
1577da6c28aaSamw 
15787b59d02dSjb150015 	rc = smbsr_encode_result(sr, 10+n_setup, total_bytes,
1579da6c28aaSamw 	    "bww2.wwwwwwb.Cw#.C#.C",
1580da6c28aaSamw 	    10 + n_setup,		/* wct */
1581da6c28aaSamw 	    n_param,			/* Total Parameter Bytes */
1582da6c28aaSamw 	    n_data,			/* Total Data Bytes */
1583da6c28aaSamw 	    n_param,			/* Total Parameter Bytes this buffer */
1584da6c28aaSamw 	    param_off,			/* Param offset from header start */
1585da6c28aaSamw 	    0,				/* Param displacement */
1586da6c28aaSamw 	    n_data,			/* Total Data Bytes this buffer */
1587da6c28aaSamw 	    data_off,			/* Data offset from header start */
1588da6c28aaSamw 	    0,				/* Data displacement */
1589da6c28aaSamw 	    n_setup,			/* suwcnt */
1590da6c28aaSamw 	    &xa->rep_setup_mb, /* setup[] */
1591da6c28aaSamw 	    total_bytes,		/* Total data bytes */
1592da6c28aaSamw 	    param_pad,
1593da6c28aaSamw 	    &xa->rep_param_mb,
1594da6c28aaSamw 	    data_pad,
1595da6c28aaSamw 	    &xa->rep_data_mb);
1596faa1795aSjb150015 	return ((rc == 0) ? SDRC_SUCCESS : SDRC_ERROR);
1597da6c28aaSamw 
1598da6c28aaSamw trans_err_too_small:
1599da6c28aaSamw 	rc = NERR_BufTooSmall;
1600da6c28aaSamw 	goto trans_err;
1601da6c28aaSamw 
1602da6c28aaSamw trans_err_not_supported:
1603da6c28aaSamw 	rc = ERROR_NOT_SUPPORTED;
1604da6c28aaSamw 	goto trans_err;
1605da6c28aaSamw 
1606da6c28aaSamw trans_err:
1607da6c28aaSamw 	pos = MBC_LENGTH(&sr->reply) + 23;
16087b59d02dSjb150015 	rc = smbsr_encode_result(sr, 10, 4, "bww2.wwwwwwb.www",
1609da6c28aaSamw 	    10,		/* wct */
1610da6c28aaSamw 	    4, 0,	/* tpscnt tdscnt */
1611da6c28aaSamw 	    4, pos, 0,	/* pscnt psoff psdisp */
1612da6c28aaSamw 	    0, 0, 0,	/* dscnt dsoff dsdisp */
1613da6c28aaSamw 	    0,		/* suwcnt */
1614da6c28aaSamw 	    4,		/* bcc */
1615da6c28aaSamw 	    rc,
1616da6c28aaSamw 	    0);		/* converter word? */
1617faa1795aSjb150015 	return ((rc == 0) ? SDRC_SUCCESS : SDRC_ERROR);
1618da6c28aaSamw }
1619da6c28aaSamw 
16207b59d02dSjb150015 static smb_sdrc_t
16219fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States smb_trans2_dispatch(smb_request_t *sr, smb_xa_t *xa)
1622da6c28aaSamw {
1623da6c28aaSamw 	int		rc, pos;
1624da6c28aaSamw 	int		total_bytes, n_setup, n_param, n_data;
1625b819cea2SGordon Ross 	int		param_off, param_pad, data_off;
1626b819cea2SGordon Ross 	uint16_t	data_pad;
1627da6c28aaSamw 	uint16_t	opcode;
1628da6c28aaSamw 	uint16_t  nt_unknown_secret = 0x0100;
1629da6c28aaSamw 	char *fmt;
1630da6c28aaSamw 
16317f3ef643SGordon Ross 	n_data = xa->smb_mdrcnt;
1632da6c28aaSamw 
16333db3f65cSamw 	if (smb_mbc_decodef(&xa->req_setup_mb, "w", &opcode) != 0)
1634da6c28aaSamw 		goto trans_err_not_supported;
1635da6c28aaSamw 
1636da6c28aaSamw 	/*
1637da6c28aaSamw 	 * Save this for /proc to read later.
1638da6c28aaSamw 	 */
1639da6c28aaSamw 	xa->smb_func = opcode;
1640da6c28aaSamw 
1641da6c28aaSamw 	/* for now, only respond to the */
1642da6c28aaSamw 	switch (opcode) {
16432c2961f8Sjose borrego 	case TRANS2_OPEN2:
16442c2961f8Sjose borrego 		rc = smb_com_trans2_open2(sr, xa);
16452c2961f8Sjose borrego 		break;
16462c2961f8Sjose borrego 
1647da6c28aaSamw 	case TRANS2_CREATE_DIRECTORY:
1648da6c28aaSamw 		rc = smb_com_trans2_create_directory(sr, xa);
1649da6c28aaSamw 		break;
1650da6c28aaSamw 
1651da6c28aaSamw 	case TRANS2_FIND_FIRST2:
1652da6c28aaSamw 		/*
1653da6c28aaSamw 		 * Should have enough room to send the response
1654da6c28aaSamw 		 * data back to client.
1655da6c28aaSamw 		 */
1656da6c28aaSamw 		if (n_data == 0) {
1657dc20a302Sas200622 			smbsr_error(sr, NT_STATUS_INFO_LENGTH_MISMATCH,
1658da6c28aaSamw 			    ERRDOS, ERROR_BAD_LENGTH);
1659faa1795aSjb150015 			return (SDRC_ERROR);
1660da6c28aaSamw 		}
1661da6c28aaSamw 		rc = smb_com_trans2_find_first2(sr, xa);
1662da6c28aaSamw 		break;
1663da6c28aaSamw 
1664da6c28aaSamw 	case TRANS2_FIND_NEXT2:
1665da6c28aaSamw 		/*
1666da6c28aaSamw 		 * Should have enough room to send the response
1667da6c28aaSamw 		 * data back to client.
1668da6c28aaSamw 		 */
1669da6c28aaSamw 		if (n_data == 0) {
1670dc20a302Sas200622 			smbsr_error(sr, NT_STATUS_INFO_LENGTH_MISMATCH,
1671da6c28aaSamw 			    ERRDOS, ERROR_BAD_LENGTH);
1672faa1795aSjb150015 			return (SDRC_ERROR);
1673da6c28aaSamw 		}
1674da6c28aaSamw 		rc = smb_com_trans2_find_next2(sr, xa);
1675da6c28aaSamw 		break;
1676da6c28aaSamw 
1677da6c28aaSamw 	case TRANS2_QUERY_FS_INFORMATION:
1678da6c28aaSamw 		/*
1679da6c28aaSamw 		 * Should have enough room to send the response
1680da6c28aaSamw 		 * data back to client.
1681da6c28aaSamw 		 */
1682da6c28aaSamw 		if (n_data == 0) {
1683dc20a302Sas200622 			smbsr_error(sr, NT_STATUS_INFO_LENGTH_MISMATCH,
1684da6c28aaSamw 			    ERRDOS, ERROR_BAD_LENGTH);
1685faa1795aSjb150015 			return (SDRC_ERROR);
1686da6c28aaSamw 		}
1687da6c28aaSamw 		rc = smb_com_trans2_query_fs_information(sr, xa);
1688da6c28aaSamw 		break;
1689da6c28aaSamw 
16909fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States 	case TRANS2_SET_FS_INFORMATION:
16919fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States 		rc = smb_com_trans2_set_fs_information(sr, xa);
16929fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States 		break;
16939fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States 
1694da6c28aaSamw 	case TRANS2_QUERY_PATH_INFORMATION:
1695da6c28aaSamw 		/*
1696da6c28aaSamw 		 * Should have enough room to send the response
1697da6c28aaSamw 		 * data back to client.
1698da6c28aaSamw 		 */
1699da6c28aaSamw 		if (n_data == 0) {
1700dc20a302Sas200622 			smbsr_error(sr, NT_STATUS_INFO_LENGTH_MISMATCH,
1701da6c28aaSamw 			    ERRDOS, ERROR_BAD_LENGTH);
1702faa1795aSjb150015 			return (SDRC_ERROR);
1703da6c28aaSamw 		}
1704da6c28aaSamw 		rc = smb_com_trans2_query_path_information(sr, xa);
1705da6c28aaSamw 		break;
1706da6c28aaSamw 
1707da6c28aaSamw 	case TRANS2_QUERY_FILE_INFORMATION:
1708da6c28aaSamw 		/*
1709da6c28aaSamw 		 * Should have enough room to send the response
1710da6c28aaSamw 		 * data back to client.
1711da6c28aaSamw 		 */
1712da6c28aaSamw 		if (n_data == 0) {
1713dc20a302Sas200622 			smbsr_error(sr, NT_STATUS_INFO_LENGTH_MISMATCH,
1714da6c28aaSamw 			    ERRDOS, ERROR_BAD_LENGTH);
1715faa1795aSjb150015 			return (SDRC_ERROR);
1716da6c28aaSamw 		}
1717da6c28aaSamw 		rc = smb_com_trans2_query_file_information(sr, xa);
1718da6c28aaSamw 		break;
1719da6c28aaSamw 
1720da6c28aaSamw 	case TRANS2_SET_PATH_INFORMATION:
1721da6c28aaSamw 		rc = smb_com_trans2_set_path_information(sr, xa);
1722da6c28aaSamw 		break;
1723da6c28aaSamw 
1724da6c28aaSamw 	case TRANS2_SET_FILE_INFORMATION:
1725da6c28aaSamw 		rc = smb_com_trans2_set_file_information(sr, xa);
1726da6c28aaSamw 		break;
17279fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States 
17289fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States 	case TRANS2_GET_DFS_REFERRAL:
17299fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States 		rc = smb_com_trans2_get_dfs_referral(sr, xa);
17309fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States 		break;
17319fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States 
1732da6c28aaSamw 	default:
17332c2961f8Sjose borrego 		(void) smb_mbc_encodef(&xa->rep_param_mb, "w", 0);
1734da6c28aaSamw 		goto trans_err_not_supported;
1735da6c28aaSamw 	}
1736da6c28aaSamw 
1737da6c28aaSamw 	switch (rc) {
1738faa1795aSjb150015 	case SDRC_SUCCESS:
1739da6c28aaSamw 		break;
1740da6c28aaSamw 
1741da6c28aaSamw 	case SDRC_DROP_VC:
1742da6c28aaSamw 	case SDRC_NO_REPLY:
1743faa1795aSjb150015 	case SDRC_ERROR:
1744da6c28aaSamw 		return (rc);
1745da6c28aaSamw 
1746faa1795aSjb150015 	case SDRC_NOT_IMPLEMENTED:
1747da6c28aaSamw 		goto trans_err_not_supported;
1748da6c28aaSamw 
1749da6c28aaSamw 	default:
1750da6c28aaSamw 		break;
1751da6c28aaSamw 	}
1752da6c28aaSamw 
1753da6c28aaSamw 	n_setup = MBC_LENGTH(&xa->rep_setup_mb);
1754da6c28aaSamw 	n_param = MBC_LENGTH(&xa->rep_param_mb);
1755da6c28aaSamw 	n_data  = MBC_LENGTH(&xa->rep_data_mb);
1756da6c28aaSamw 
1757da6c28aaSamw 	if (xa->smb_msrcnt < n_setup ||
1758da6c28aaSamw 	    xa->smb_mprcnt < n_param ||
1759da6c28aaSamw 	    xa->smb_mdrcnt < n_data) {
1760da6c28aaSamw 		goto trans_err_too_small;
1761da6c28aaSamw 	}
1762da6c28aaSamw 
1763da6c28aaSamw 	/* neato, blast it over there */
1764da6c28aaSamw 
1765da6c28aaSamw 	n_setup = (n_setup + 1) / 2;		/* Conver to setup words */
1766da6c28aaSamw 	param_pad = 1;				/* must be one */
1767da6c28aaSamw 	param_off = param_pad + 32 + 21 + (n_setup << 1) + 2;
1768da6c28aaSamw 
1769da6c28aaSamw 	/*
1770da6c28aaSamw 	 * Including the nt_unknown_secret value persuades netmon to
1771da6c28aaSamw 	 * display the correct data format for QueryPathInfo and
1772da6c28aaSamw 	 * QueryFileInfo.
1773da6c28aaSamw 	 */
1774da6c28aaSamw 	if (opcode == TRANS2_QUERY_FILE_INFORMATION ||
1775da6c28aaSamw 	    opcode == TRANS2_QUERY_PATH_INFORMATION) {
1776da6c28aaSamw 		data_pad = sizeof (uint16_t);
1777da6c28aaSamw 		data_off = param_off + n_param + data_pad;
1778da6c28aaSamw 		fmt = "bww2.wwwwwwb.Cw#.CwC";
1779da6c28aaSamw 		nt_unknown_secret = 0x0100;
1780da6c28aaSamw 	}
1781da6c28aaSamw 	else
1782da6c28aaSamw 	{
1783da6c28aaSamw 		data_pad = (param_off + n_param) & 1; /* Pad to short */
1784da6c28aaSamw 		/* Param off from hdr start */
1785da6c28aaSamw 		data_off = param_off + n_param + data_pad;
1786da6c28aaSamw 		fmt = "bww2.wwwwwwb.Cw#.C#.C";
1787da6c28aaSamw 		nt_unknown_secret = data_pad;
1788da6c28aaSamw 	}
1789da6c28aaSamw 
1790da6c28aaSamw 	total_bytes = param_pad + n_param + data_pad + n_data;
1791da6c28aaSamw 
17927b59d02dSjb150015 	rc = smbsr_encode_result(sr, 10+n_setup, total_bytes,
1793da6c28aaSamw 	    fmt,
1794da6c28aaSamw 	    10 + n_setup,		/* wct */
1795da6c28aaSamw 	    n_param,			/* Total Parameter Bytes */
1796da6c28aaSamw 	    n_data /* + data_pad */,	/* Total Data Bytes */
1797da6c28aaSamw 	    n_param,			/* Total Parameter Bytes this buffer */
1798da6c28aaSamw 	    param_off,			/* Param offset from header start */
1799da6c28aaSamw 	    0,				/* Param displacement */
1800da6c28aaSamw 	    n_data /* + data_pad */,	/* Total Data Bytes this buffer */
1801da6c28aaSamw 	    data_off,			/* Data offset from header start */
1802da6c28aaSamw 	    0,				/* Data displacement */
1803da6c28aaSamw 	    n_setup,			/* suwcnt */
1804da6c28aaSamw 	    &xa->rep_setup_mb,		/* setup[] */
1805da6c28aaSamw 	    total_bytes,		/* Total data bytes */
1806da6c28aaSamw 	    param_pad,
1807da6c28aaSamw 	    &xa->rep_param_mb,
1808da6c28aaSamw 	    nt_unknown_secret,
1809da6c28aaSamw 	    &xa->rep_data_mb);
1810faa1795aSjb150015 	return ((rc == 0) ? SDRC_SUCCESS : SDRC_ERROR);
1811da6c28aaSamw 
1812da6c28aaSamw trans_err_too_small:
1813da6c28aaSamw 	rc = NERR_BufTooSmall;
1814da6c28aaSamw 	goto trans_err;
1815da6c28aaSamw 
1816da6c28aaSamw trans_err_not_supported:
1817da6c28aaSamw 	rc = ERROR_NOT_SUPPORTED;
1818da6c28aaSamw 	goto trans_err;
1819da6c28aaSamw 
1820da6c28aaSamw trans_err:
1821da6c28aaSamw 	pos = MBC_LENGTH(&sr->reply) + 23;
18227b59d02dSjb150015 	rc = smbsr_encode_result(sr, 10, 4, "bww2.wwwwwwb.www",
1823da6c28aaSamw 	    10,		/* wct */
1824da6c28aaSamw 	    4, 0,	/* tpscnt tdscnt */
1825da6c28aaSamw 	    4, pos, 0,	/* pscnt psoff psdisp */
1826da6c28aaSamw 	    0, 0, 0,	/* dscnt dsoff dsdisp */
1827da6c28aaSamw 	    0,		/* suwcnt */
1828da6c28aaSamw 	    4,		/* bcc */
1829da6c28aaSamw 	    rc,
1830da6c28aaSamw 	    0);		/* converter word? */
1831faa1795aSjb150015 	return ((rc == 0) ? SDRC_SUCCESS : SDRC_ERROR);
1832da6c28aaSamw }
1833da6c28aaSamw 
18347f3ef643SGordon Ross static uint32_t smb_xa_max_setup_count = 200;
18357f3ef643SGordon Ross static uint32_t smb_xa_max_param_count = 32 * 1024;
18367f3ef643SGordon Ross static uint32_t smb_xa_max_data_count  = 64 * 1024;
18377f3ef643SGordon Ross 
1838da6c28aaSamw smb_xa_t *
1839da6c28aaSamw smb_xa_create(
1840da6c28aaSamw     smb_session_t	*session,
1841da6c28aaSamw     smb_request_t	*sr,
1842da6c28aaSamw     uint32_t		total_parameter_count,
1843da6c28aaSamw     uint32_t		total_data_count,
1844da6c28aaSamw     uint32_t		max_parameter_count,
1845da6c28aaSamw     uint32_t		max_data_count,
1846da6c28aaSamw     uint32_t		max_setup_count,
1847da6c28aaSamw     uint32_t		setup_word_count)
1848da6c28aaSamw {
1849da6c28aaSamw 	smb_xa_t	*xa, *nxa;
1850da6c28aaSamw 	smb_llist_t	*xlist;
1851da6c28aaSamw 
18527f3ef643SGordon Ross 	/*
18537f3ef643SGordon Ross 	 * Sanity check what the client says it will send.
18547f3ef643SGordon Ross 	 * Caller handles NULL return as ERRnoroom.
18557f3ef643SGordon Ross 	 */
18567f3ef643SGordon Ross 	if (setup_word_count > smb_xa_max_setup_count)
18577f3ef643SGordon Ross 		return (NULL);
18587f3ef643SGordon Ross 	if (total_parameter_count > smb_xa_max_param_count)
18597f3ef643SGordon Ross 		return (NULL);
18607f3ef643SGordon Ross 	if (total_data_count > smb_xa_max_data_count)
18617f3ef643SGordon Ross 		return (NULL);
18627f3ef643SGordon Ross 
18637f3ef643SGordon Ross 	/*
18647f3ef643SGordon Ross 	 * Limit what the client asks us to allocate for
18657f3ef643SGordon Ross 	 * returned setup, params, data.
18667f3ef643SGordon Ross 	 */
18677f3ef643SGordon Ross 	if (max_setup_count > smb_xa_max_setup_count)
18687f3ef643SGordon Ross 		max_setup_count = smb_xa_max_setup_count;
18697f3ef643SGordon Ross 	if (max_parameter_count > smb_xa_max_param_count)
18707f3ef643SGordon Ross 		max_parameter_count = smb_xa_max_param_count;
18717f3ef643SGordon Ross 	if (max_data_count > smb_xa_max_data_count)
18727f3ef643SGordon Ross 		max_data_count = smb_xa_max_data_count;
18737f3ef643SGordon Ross 
1874bbf6f00cSJordan Brown 	xa = kmem_zalloc(sizeof (smb_xa_t), KM_SLEEP);
1875da6c28aaSamw 	xa->xa_refcnt = 1;
1876da6c28aaSamw 	xa->smb_com = sr->smb_com;
1877da6c28aaSamw 	xa->smb_flg = sr->smb_flg;
1878da6c28aaSamw 	xa->smb_flg2 = sr->smb_flg2;
1879da6c28aaSamw 	xa->smb_tid = sr->smb_tid;
1880da6c28aaSamw 	xa->smb_pid = sr->smb_pid;
1881da6c28aaSamw 	xa->smb_uid = sr->smb_uid;
1882da6c28aaSamw 	xa->xa_smb_mid = sr->smb_mid;
18837f3ef643SGordon Ross 	xa->xa_smb_fid = 0xFFFF;
1884da6c28aaSamw 	xa->reply_seqnum = sr->reply_seqnum;
1885da6c28aaSamw 	xa->smb_tpscnt = total_parameter_count;
1886da6c28aaSamw 	xa->smb_tdscnt = total_data_count;
1887da6c28aaSamw 	xa->smb_mprcnt = max_parameter_count;
1888da6c28aaSamw 	xa->smb_mdrcnt = max_data_count;
1889da6c28aaSamw 	xa->smb_msrcnt = max_setup_count;
1890da6c28aaSamw 	xa->smb_suwcnt = setup_word_count;
1891da6c28aaSamw 	xa->xa_session = session;
1892da6c28aaSamw 	xa->xa_magic = SMB_XA_MAGIC;
1893da6c28aaSamw 
18947f3ef643SGordon Ross 	/* request parts */
18957f3ef643SGordon Ross 	xa->req_setup_mb.max_bytes = setup_word_count * 2;
18967f3ef643SGordon Ross 	xa->req_param_mb.max_bytes = total_parameter_count;
18977f3ef643SGordon Ross 	xa->req_data_mb.max_bytes  = total_data_count;
18987f3ef643SGordon Ross 
18997f3ef643SGordon Ross 	/* reply parts */
19007f3ef643SGordon Ross 	xa->rep_setup_mb.max_bytes = max_setup_count * 2;
19017f3ef643SGordon Ross 	xa->rep_param_mb.max_bytes = max_parameter_count;
19027f3ef643SGordon Ross 	xa->rep_data_mb.max_bytes =  max_data_count;
19037f3ef643SGordon Ross 
1904da6c28aaSamw 	/*
1905da6c28aaSamw 	 * The new xa structure is checked against the current list to see
1906da6c28aaSamw 	 * if it exists already.
1907da6c28aaSamw 	 */
1908da6c28aaSamw 	xlist = &session->s_xa_list;
1909da6c28aaSamw 	smb_llist_enter(xlist, RW_WRITER);
1910da6c28aaSamw 	nxa = smb_llist_head(xlist);
1911da6c28aaSamw 	while (nxa) {
1912da6c28aaSamw 		ASSERT(nxa->xa_magic == SMB_XA_MAGIC);
1913da6c28aaSamw 		if (nxa->xa_smb_mid == xa->xa_smb_mid &&
1914da6c28aaSamw 		    nxa->smb_pid == xa->smb_pid &&
1915da6c28aaSamw 		    !SMB_XA_CLOSED(nxa) &&
1916da6c28aaSamw 		    !(nxa->xa_flags & SMB_XA_FLAG_COMPLETE)) {
1917da6c28aaSamw 			smb_llist_exit(xlist);
1918bbf6f00cSJordan Brown 			kmem_free(xa, sizeof (smb_xa_t));
1919da6c28aaSamw 			return (NULL);
1920da6c28aaSamw 		}
1921da6c28aaSamw 		nxa = smb_llist_next(xlist, nxa);
1922da6c28aaSamw 	}
1923da6c28aaSamw 	smb_llist_insert_tail(xlist, xa);
1924da6c28aaSamw 	smb_llist_exit(xlist);
1925da6c28aaSamw 	return (xa);
1926da6c28aaSamw }
1927da6c28aaSamw 
1928da6c28aaSamw void
1929da6c28aaSamw smb_xa_delete(smb_xa_t *xa)
1930da6c28aaSamw {
1931da6c28aaSamw 	ASSERT(xa->xa_refcnt == 0);
1932da6c28aaSamw 	ASSERT(SMB_XA_CLOSED(xa));
1933da6c28aaSamw 
1934bbf6f00cSJordan Brown 	if (xa->xa_pipe_name)
19359fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States 		smb_mem_free(xa->xa_pipe_name);
1936da6c28aaSamw 
19377f3ef643SGordon Ross 	/* request parts */
19387f3ef643SGordon Ross 	if (xa->req_setup_mb.chain != NULL)
19397f3ef643SGordon Ross 		m_freem(xa->req_setup_mb.chain);
19407f3ef643SGordon Ross 	if (xa->req_param_mb.chain != NULL)
19417f3ef643SGordon Ross 		m_freem(xa->req_param_mb.chain);
19427f3ef643SGordon Ross 	if (xa->req_data_mb.chain != NULL)
19437f3ef643SGordon Ross 		m_freem(xa->req_data_mb.chain);
19447f3ef643SGordon Ross 
19457f3ef643SGordon Ross 	/* reply parts */
1946da6c28aaSamw 	if (xa->rep_setup_mb.chain != NULL)
1947da6c28aaSamw 		m_freem(xa->rep_setup_mb.chain);
1948da6c28aaSamw 	if (xa->rep_param_mb.chain != NULL)
1949da6c28aaSamw 		m_freem(xa->rep_param_mb.chain);
1950da6c28aaSamw 	if (xa->rep_data_mb.chain != NULL)
1951da6c28aaSamw 		m_freem(xa->rep_data_mb.chain);
1952da6c28aaSamw 
1953da6c28aaSamw 	xa->xa_magic = (uint32_t)~SMB_XA_MAGIC;
1954bbf6f00cSJordan Brown 	kmem_free(xa, sizeof (smb_xa_t));
1955da6c28aaSamw }
1956da6c28aaSamw 
1957da6c28aaSamw smb_xa_t *
1958da6c28aaSamw smb_xa_hold(smb_xa_t *xa)
1959da6c28aaSamw {
1960da6c28aaSamw 	mutex_enter(&xa->xa_mutex);
1961da6c28aaSamw 	xa->xa_refcnt++;
1962da6c28aaSamw 	ASSERT(xa->xa_refcnt);
1963da6c28aaSamw 	mutex_exit(&xa->xa_mutex);
1964da6c28aaSamw 	return (xa);
1965da6c28aaSamw }
1966da6c28aaSamw 
1967da6c28aaSamw void
1968da6c28aaSamw smb_xa_rele(smb_session_t *session, smb_xa_t *xa)
1969da6c28aaSamw {
1970da6c28aaSamw 	mutex_enter(&xa->xa_mutex);
1971da6c28aaSamw 	ASSERT(xa->xa_refcnt);
1972da6c28aaSamw 	xa->xa_refcnt--;
1973da6c28aaSamw 	if (SMB_XA_CLOSED(xa) && (xa->xa_refcnt == 0)) {
1974da6c28aaSamw 		mutex_exit(&xa->xa_mutex);
1975da6c28aaSamw 		smb_llist_enter(&session->s_xa_list, RW_WRITER);
1976da6c28aaSamw 		smb_llist_remove(&session->s_xa_list, xa);
1977da6c28aaSamw 		smb_llist_exit(&session->s_xa_list);
1978da6c28aaSamw 		smb_xa_delete(xa);
1979da6c28aaSamw 		return;
1980da6c28aaSamw 	}
1981da6c28aaSamw 	mutex_exit(&xa->xa_mutex);
1982da6c28aaSamw }
1983da6c28aaSamw 
1984da6c28aaSamw int
1985da6c28aaSamw smb_xa_open(smb_xa_t *xa)
1986da6c28aaSamw {
1987da6c28aaSamw 	int rc;
1988da6c28aaSamw 
1989da6c28aaSamw 	mutex_enter(&xa->xa_mutex);
1990da6c28aaSamw 
1991da6c28aaSamw 	ASSERT((xa->xa_flags & SMB_XA_FLAG_OPEN) == 0);
1992da6c28aaSamw 
1993da6c28aaSamw 	if ((xa->xa_flags & SMB_XA_FLAG_CLOSE) == 0) {
1994da6c28aaSamw 		xa->xa_flags |= SMB_XA_FLAG_OPEN;
1995da6c28aaSamw 		rc = 0;
1996da6c28aaSamw 	} else {
1997da6c28aaSamw 		rc = ERROR_INVALID_HANDLE;
1998da6c28aaSamw 	}
1999da6c28aaSamw 
2000da6c28aaSamw 	mutex_exit(&xa->xa_mutex);
2001da6c28aaSamw 
2002da6c28aaSamw 	return (rc);
2003da6c28aaSamw }
2004da6c28aaSamw 
2005da6c28aaSamw void
2006da6c28aaSamw smb_xa_close(smb_xa_t *xa)
2007da6c28aaSamw {
2008da6c28aaSamw 	mutex_enter(&xa->xa_mutex);
2009da6c28aaSamw 	xa->xa_flags |= SMB_XA_FLAG_CLOSE;
2010da6c28aaSamw 	xa->xa_flags &= ~SMB_XA_FLAG_OPEN;
2011da6c28aaSamw 
2012da6c28aaSamw 	if (xa->xa_refcnt == 0) {
2013da6c28aaSamw 		mutex_exit(&xa->xa_mutex);
2014da6c28aaSamw 		smb_llist_enter(&xa->xa_session->s_xa_list, RW_WRITER);
2015da6c28aaSamw 		smb_llist_remove(&xa->xa_session->s_xa_list, xa);
2016da6c28aaSamw 		smb_llist_exit(&xa->xa_session->s_xa_list);
2017da6c28aaSamw 		smb_xa_delete(xa);
2018da6c28aaSamw 		return;
2019da6c28aaSamw 	}
2020da6c28aaSamw 
2021da6c28aaSamw 	mutex_exit(&xa->xa_mutex);
2022da6c28aaSamw }
2023da6c28aaSamw 
2024da6c28aaSamw int
2025da6c28aaSamw smb_xa_complete(smb_xa_t *xa)
2026da6c28aaSamw {
2027da6c28aaSamw 	int rc;
2028da6c28aaSamw 
2029da6c28aaSamw 	mutex_enter(&xa->xa_mutex);
2030da6c28aaSamw 	if (xa->xa_flags & (SMB_XA_FLAG_COMPLETE | SMB_XA_FLAG_CLOSE)) {
20317f3ef643SGordon Ross 		rc = 0; /* error ("not complete") */
2032da6c28aaSamw 	} else {
20337f3ef643SGordon Ross 		rc = 1; /* Yes, "complete" */
2034da6c28aaSamw 		xa->xa_flags |= SMB_XA_FLAG_COMPLETE;
20357f3ef643SGordon Ross 
20367f3ef643SGordon Ross 		/*
20377f3ef643SGordon Ross 		 * During trans & trans-secondary processing,
20387f3ef643SGordon Ross 		 * we copied the request data into these.
20397f3ef643SGordon Ross 		 * Now we want to parse them, so we need to
20407f3ef643SGordon Ross 		 * move the "finger" back to the beginning.
20417f3ef643SGordon Ross 		 */
20427f3ef643SGordon Ross 		xa->req_setup_mb.chain_offset = 0;
20437f3ef643SGordon Ross 		xa->req_param_mb.chain_offset = 0;
20447f3ef643SGordon Ross 		xa->req_data_mb.chain_offset  = 0;
2045da6c28aaSamw 	}
20467f3ef643SGordon Ross 
2047da6c28aaSamw 	mutex_exit(&xa->xa_mutex);
2048da6c28aaSamw 	return (rc);
2049da6c28aaSamw }
2050da6c28aaSamw 
2051da6c28aaSamw smb_xa_t *
2052da6c28aaSamw smb_xa_find(
2053da6c28aaSamw     smb_session_t	*session,
2054da6c28aaSamw     uint16_t		pid,
2055da6c28aaSamw     uint16_t		mid)
2056da6c28aaSamw {
2057da6c28aaSamw 	smb_xa_t	*xa;
2058da6c28aaSamw 	smb_llist_t	*xlist;
2059da6c28aaSamw 
2060da6c28aaSamw 	xlist = &session->s_xa_list;
2061da6c28aaSamw 	smb_llist_enter(xlist, RW_READER);
2062da6c28aaSamw 	xa = smb_llist_head(xlist);
2063da6c28aaSamw 	while (xa) {
2064da6c28aaSamw 		mutex_enter(&xa->xa_mutex);
2065da6c28aaSamw 		if (xa->xa_smb_mid == mid &&
2066da6c28aaSamw 		    xa->smb_pid == pid &&
2067da6c28aaSamw 		    !SMB_XA_CLOSED(xa) &&
2068da6c28aaSamw 		    !(xa->xa_flags & SMB_XA_FLAG_COMPLETE)) {
2069da6c28aaSamw 			xa->xa_refcnt++;
2070da6c28aaSamw 			ASSERT(xa->xa_refcnt);
2071da6c28aaSamw 			mutex_exit(&xa->xa_mutex);
2072da6c28aaSamw 			break;
2073da6c28aaSamw 		}
2074da6c28aaSamw 		mutex_exit(&xa->xa_mutex);
2075da6c28aaSamw 		xa = smb_llist_next(xlist, xa);
2076da6c28aaSamw 	}
2077da6c28aaSamw 	smb_llist_exit(xlist);
2078da6c28aaSamw 	return (xa);
2079da6c28aaSamw }
2080