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.
24adee6784SGordon Ross * Copyright 2018 Nexenta Systems, Inc. All rights reserved.
25*97264293SGordon Ross * Copyright 2022 RackTop Systems, Inc.
26da6c28aaSamw */
27da6c28aaSamw
28bbf6f00cSJordan Brown #include <smbsrv/smb_kproto.h>
29da6c28aaSamw #include <smbsrv/smb_fsops.h>
303db3f65cSamw #include <smbsrv/smb_share.h>
31bbf6f00cSJordan Brown #include <smbsrv/string.h>
32da6c28aaSamw #include <smbsrv/nmpipes.h>
33da6c28aaSamw #include <smbsrv/mailslot.h>
34adee6784SGordon Ross #include <smb/winioctl.h>
35da6c28aaSamw
36da6c28aaSamw /*
37da6c28aaSamw * count of bytes in server response packet
38da6c28aaSamw * except parameters and data. Note that setup
39da6c28aaSamw * word count is zero.
40da6c28aaSamw */
41da6c28aaSamw #define RESP_HEADER_LEN 24
42da6c28aaSamw
43da6c28aaSamw /*
44b1352070SAlan Wright * We started by using common functions for transaction/transaction2
45da6c28aaSamw * and transaction_secondary/transaction2_secondary because they
46da6c28aaSamw * are respectively so similar. However, it turned out to be a bad
47da6c28aaSamw * idea because of quirky differences. Be sure if you modify one
48da6c28aaSamw * of these four functions to check and see if the modification should
49da6c28aaSamw * be applied to its peer.
50da6c28aaSamw */
51da6c28aaSamw
529fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States static int smb_trans_ready(smb_xa_t *);
539fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States static smb_sdrc_t smb_trans_dispatch(smb_request_t *, smb_xa_t *);
549fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States static smb_sdrc_t smb_trans2_dispatch(smb_request_t *, smb_xa_t *);
55da6c28aaSamw
567b59d02dSjb150015 smb_sdrc_t
smb_pre_transaction(smb_request_t * sr)57faa1795aSjb150015 smb_pre_transaction(smb_request_t *sr)
58faa1795aSjb150015 {
5993bc28dbSGordon Ross DTRACE_SMB_START(op__Transaction, smb_request_t *, sr);
60faa1795aSjb150015 return (SDRC_SUCCESS);
61faa1795aSjb150015 }
62faa1795aSjb150015
63faa1795aSjb150015 void
smb_post_transaction(smb_request_t * sr)64faa1795aSjb150015 smb_post_transaction(smb_request_t *sr)
65faa1795aSjb150015 {
6693bc28dbSGordon Ross DTRACE_SMB_DONE(op__Transaction, smb_request_t *, sr);
67faa1795aSjb150015 }
68faa1795aSjb150015
69faa1795aSjb150015 smb_sdrc_t
smb_com_transaction(smb_request_t * sr)70faa1795aSjb150015 smb_com_transaction(smb_request_t *sr)
71da6c28aaSamw {
72da6c28aaSamw int rc;
73da6c28aaSamw unsigned char msrcnt, suwcnt;
74da6c28aaSamw uint16_t tpscnt, tdscnt, mprcnt, mdrcnt, flags;
75da6c28aaSamw uint16_t pscnt, psoff, dscnt, dsoff;
76da6c28aaSamw uint32_t timeo;
77da6c28aaSamw struct smb_xa *xa;
78da6c28aaSamw char *stn;
79da6c28aaSamw int ready;
80da6c28aaSamw
81a90cf9f2SGordon Ross if (!STYPE_ISIPC(sr->tid_tree->t_res_type)) {
82a90cf9f2SGordon Ross smbsr_error(sr, 0, ERRDOS, ERRnoaccess);
83a90cf9f2SGordon Ross return (SDRC_ERROR);
84a90cf9f2SGordon Ross }
85a90cf9f2SGordon Ross
86da6c28aaSamw rc = smbsr_decode_vwv(sr, SMB_TRANSHDR_ED_FMT,
87da6c28aaSamw &tpscnt, &tdscnt, &mprcnt, &mdrcnt, &msrcnt, &flags,
88da6c28aaSamw &timeo, &pscnt, &psoff, &dscnt, &dsoff, &suwcnt);
89da6c28aaSamw
907b59d02dSjb150015 if (rc != 0)
91faa1795aSjb150015 return (SDRC_ERROR);
92da6c28aaSamw
93da6c28aaSamw xa = smb_xa_create(sr->session, sr, tpscnt, tdscnt, mprcnt, mdrcnt,
94da6c28aaSamw msrcnt, suwcnt);
95da6c28aaSamw if (xa == NULL) {
96dc20a302Sas200622 smbsr_error(sr, 0, ERRSRV, ERRnoroom);
97faa1795aSjb150015 return (SDRC_ERROR);
98da6c28aaSamw }
99da6c28aaSamw
100da6c28aaSamw /* Should be some alignment stuff here in SMB? */
101da6c28aaSamw if (sr->smb_flg2 & SMB_FLAGS2_UNICODE) {
102da6c28aaSamw rc = smbsr_decode_data(sr, "%.U", sr, &stn);
103da6c28aaSamw } else {
104da6c28aaSamw rc = smbsr_decode_data(sr, "%s", sr, &stn);
105da6c28aaSamw }
106da6c28aaSamw if (rc != 0) {
107da6c28aaSamw smb_xa_rele(sr->session, xa);
108faa1795aSjb150015 return (SDRC_ERROR);
109da6c28aaSamw }
110da6c28aaSamw
1119fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States xa->xa_pipe_name = smb_mem_strdup(stn);
112da6c28aaSamw xa->smb_flags = flags;
113da6c28aaSamw xa->smb_timeout = timeo;
114da6c28aaSamw xa->req_disp_param = pscnt;
115da6c28aaSamw xa->req_disp_data = dscnt;
116da6c28aaSamw
1177f3ef643SGordon Ross if (smb_mbc_copy(&xa->req_setup_mb, &sr->smb_vwv,
118da6c28aaSamw sr->smb_vwv.chain_offset, suwcnt * 2)) {
119da6c28aaSamw smb_xa_rele(sr->session, xa);
120dc20a302Sas200622 smbsr_error(sr, 0, ERRDOS, ERRbadformat);
121faa1795aSjb150015 return (SDRC_ERROR);
122da6c28aaSamw }
1237f3ef643SGordon Ross if (smb_mbc_copy(&xa->req_param_mb, &sr->command, psoff, pscnt)) {
124da6c28aaSamw smb_xa_rele(sr->session, xa);
125dc20a302Sas200622 smbsr_error(sr, 0, ERRDOS, ERRbadformat);
126faa1795aSjb150015 return (SDRC_ERROR);
127da6c28aaSamw }
1287f3ef643SGordon Ross if (smb_mbc_copy(&xa->req_data_mb, &sr->command, dsoff, dscnt)) {
129da6c28aaSamw smb_xa_rele(sr->session, xa);
130dc20a302Sas200622 smbsr_error(sr, 0, ERRDOS, ERRbadformat);
131faa1795aSjb150015 return (SDRC_ERROR);
132da6c28aaSamw }
133da6c28aaSamw
134da6c28aaSamw ready = smb_trans_ready(xa);
135da6c28aaSamw
136da6c28aaSamw if (smb_xa_open(xa)) {
137da6c28aaSamw smb_xa_rele(sr->session, xa);
138ccc71be5SGordon Ross smbsr_error(sr, 0, ERRSRV, ERRsrverror);
139faa1795aSjb150015 return (SDRC_ERROR);
140da6c28aaSamw }
141da6c28aaSamw sr->r_xa = xa;
142da6c28aaSamw
143da6c28aaSamw if (!ready) {
1447b59d02dSjb150015 rc = smbsr_encode_empty_result(sr);
145faa1795aSjb150015 return ((rc == 0) ? SDRC_SUCCESS : SDRC_ERROR);
146da6c28aaSamw }
147da6c28aaSamw
148da6c28aaSamw if (!smb_xa_complete(xa)) {
149da6c28aaSamw smb_xa_close(xa);
150dc20a302Sas200622 smbsr_error(sr, 0, ERRDOS, ERRbadformat);
151faa1795aSjb150015 return (SDRC_ERROR);
152da6c28aaSamw }
153da6c28aaSamw
154da6c28aaSamw return (smb_trans_dispatch(sr, xa));
155da6c28aaSamw }
156da6c28aaSamw
1577b59d02dSjb150015 smb_sdrc_t
smb_pre_transaction_secondary(smb_request_t * sr)158faa1795aSjb150015 smb_pre_transaction_secondary(smb_request_t *sr)
159faa1795aSjb150015 {
16093bc28dbSGordon Ross DTRACE_SMB_START(op__TransactionSecondary, smb_request_t *, sr);
161faa1795aSjb150015 return (SDRC_SUCCESS);
162faa1795aSjb150015 }
163faa1795aSjb150015
164faa1795aSjb150015 void
smb_post_transaction_secondary(smb_request_t * sr)165faa1795aSjb150015 smb_post_transaction_secondary(smb_request_t *sr)
166faa1795aSjb150015 {
16793bc28dbSGordon Ross DTRACE_SMB_DONE(op__TransactionSecondary, smb_request_t *, sr);
168faa1795aSjb150015 }
169faa1795aSjb150015
170faa1795aSjb150015 smb_sdrc_t
smb_com_transaction_secondary(smb_request_t * sr)171faa1795aSjb150015 smb_com_transaction_secondary(smb_request_t *sr)
172da6c28aaSamw {
173da6c28aaSamw uint16_t tpscnt, tdscnt, pscnt, psdisp;
174da6c28aaSamw uint16_t dscnt, dsoff, dsdisp, psoff;
175da6c28aaSamw smb_xa_t *xa;
176da6c28aaSamw int rc;
177da6c28aaSamw
178da6c28aaSamw if ((xa = smbsr_lookup_xa(sr)) == 0) {
179dc20a302Sas200622 smbsr_error(sr, 0, ERRSRV, ERRsrverror);
180faa1795aSjb150015 return (SDRC_ERROR);
181da6c28aaSamw }
182da6c28aaSamw
183da6c28aaSamw if (sr->session->signing.flags & SMB_SIGNING_ENABLED) {
184da6c28aaSamw if (smb_sign_check_secondary(sr, xa->reply_seqnum) != 0) {
185dc20a302Sas200622 smbsr_error(sr, NT_STATUS_ACCESS_DENIED,
186da6c28aaSamw ERRDOS, ERRnoaccess);
187faa1795aSjb150015 return (SDRC_ERROR);
188da6c28aaSamw }
189da6c28aaSamw }
190da6c28aaSamw
191da6c28aaSamw if (xa->smb_com != SMB_COM_TRANSACTION) {
192da6c28aaSamw return (SDRC_DROP_VC);
193da6c28aaSamw }
194da6c28aaSamw
195da6c28aaSamw rc = smbsr_decode_vwv(sr, SMB_TRANSSHDR_ED_FMT, &tpscnt, &tdscnt,
196da6c28aaSamw &pscnt, &psoff, &psdisp, &dscnt, &dsoff, &dsdisp);
197da6c28aaSamw
1987b59d02dSjb150015 if (rc != 0)
199faa1795aSjb150015 return (SDRC_ERROR);
200da6c28aaSamw
201da6c28aaSamw mutex_enter(&xa->xa_mutex);
2027f3ef643SGordon Ross if (xa->smb_tpscnt > tpscnt)
2037f3ef643SGordon Ross xa->smb_tpscnt = tpscnt;
2047f3ef643SGordon Ross if (xa->smb_tdscnt > tdscnt)
2057f3ef643SGordon Ross xa->smb_tdscnt = tdscnt;
206da6c28aaSamw xa->req_disp_param = psdisp + pscnt;
207da6c28aaSamw xa->req_disp_data = dsdisp + dscnt;
208da6c28aaSamw
2097f3ef643SGordon Ross /*
2107f3ef643SGordon Ross * The words psdisp, dsdisp, tell us what displacement
2117f3ef643SGordon Ross * into the entire trans parameter and data buffers
2127f3ef643SGordon Ross * where we should put the params & data that are
2137f3ef643SGordon Ross * delivered by this request. [MS-CIFS] says all the
2147f3ef643SGordon Ross * parameters and data SHOULD be sent sequentially, so
2157f3ef643SGordon Ross * so we can normally reassemble by simply appending.
2167f3ef643SGordon Ross * However, the components MAY come out of order, so
2177f3ef643SGordon Ross * check and set the current offset. This is rare,
2187f3ef643SGordon Ross * and we might like to know when this happens, so
2197f3ef643SGordon Ross * fire some static dtrace probes when it does.
2207f3ef643SGordon Ross */
2217f3ef643SGordon Ross if (xa->req_param_mb.chain_offset != psdisp) {
2227f3ef643SGordon Ross DTRACE_PROBE2(trans_param_disp,
2237f3ef643SGordon Ross smb_xa_t *, xa, uint16_t, psdisp);
2247f3ef643SGordon Ross xa->req_param_mb.chain_offset = psdisp;
2257f3ef643SGordon Ross }
2267f3ef643SGordon Ross if (xa->req_data_mb.chain_offset != dsdisp) {
2277f3ef643SGordon Ross DTRACE_PROBE2(trans_data_disp,
2287f3ef643SGordon Ross smb_xa_t *, xa, uint16_t, dsdisp);
2297f3ef643SGordon Ross xa->req_data_mb.chain_offset = dsdisp;
2307f3ef643SGordon Ross }
2317f3ef643SGordon Ross
2327f3ef643SGordon Ross if (smb_mbc_copy(&xa->req_param_mb, &sr->command, psoff, pscnt)) {
233da6c28aaSamw mutex_exit(&xa->xa_mutex);
234da6c28aaSamw smb_xa_close(xa);
235dc20a302Sas200622 smbsr_error(sr, 0, ERRDOS, ERRbadformat);
236faa1795aSjb150015 return (SDRC_ERROR);
237da6c28aaSamw }
2387f3ef643SGordon Ross if (smb_mbc_copy(&xa->req_data_mb, &sr->command, dsoff, dscnt)) {
239da6c28aaSamw mutex_exit(&xa->xa_mutex);
240da6c28aaSamw smb_xa_close(xa);
241dc20a302Sas200622 smbsr_error(sr, 0, ERRDOS, ERRbadformat);
242faa1795aSjb150015 return (SDRC_ERROR);
243da6c28aaSamw }
244da6c28aaSamw mutex_exit(&xa->xa_mutex);
245da6c28aaSamw
246da6c28aaSamw if (!smb_trans_ready(xa))
247da6c28aaSamw return (SDRC_NO_REPLY);
248da6c28aaSamw
249da6c28aaSamw if (!smb_xa_complete(xa))
250da6c28aaSamw return (SDRC_NO_REPLY);
251da6c28aaSamw
252da6c28aaSamw return (smb_trans_dispatch(sr, xa));
253da6c28aaSamw }
254da6c28aaSamw
2557b59d02dSjb150015 smb_sdrc_t
smb_pre_ioctl(smb_request_t * sr)256faa1795aSjb150015 smb_pre_ioctl(smb_request_t *sr)
257faa1795aSjb150015 {
25893bc28dbSGordon Ross DTRACE_SMB_START(op__Ioctl, smb_request_t *, sr);
259faa1795aSjb150015 return (SDRC_SUCCESS);
260faa1795aSjb150015 }
261faa1795aSjb150015
262faa1795aSjb150015 void
smb_post_ioctl(smb_request_t * sr)263faa1795aSjb150015 smb_post_ioctl(smb_request_t *sr)
264faa1795aSjb150015 {
26593bc28dbSGordon Ross DTRACE_SMB_DONE(op__Ioctl, smb_request_t *, sr);
266faa1795aSjb150015 }
267faa1795aSjb150015
268faa1795aSjb150015 smb_sdrc_t
smb_com_ioctl(smb_request_t * sr)269faa1795aSjb150015 smb_com_ioctl(smb_request_t *sr)
270da6c28aaSamw {
271da6c28aaSamw uint16_t fid, category, function, tpscnt, tdscnt, mprcnt;
272da6c28aaSamw uint16_t mdrcnt, pscnt, pdoff, dscnt, dsoff;
273da6c28aaSamw uint32_t timeout;
274da6c28aaSamw int rc;
275da6c28aaSamw
276da6c28aaSamw rc = smbsr_decode_vwv(sr, "wwwwwwwl2.wwww", &fid, &category, &function,
277da6c28aaSamw &tpscnt, &tdscnt, &mprcnt, &mdrcnt, &timeout, &pscnt,
278da6c28aaSamw &pdoff, &dscnt, &dsoff);
279da6c28aaSamw
2807b59d02dSjb150015 if (rc != 0)
281faa1795aSjb150015 return (SDRC_ERROR);
282da6c28aaSamw
283faa1795aSjb150015 return (SDRC_NOT_IMPLEMENTED);
284da6c28aaSamw }
285da6c28aaSamw
286faa1795aSjb150015 smb_sdrc_t
smb_pre_transaction2(smb_request_t * sr)287faa1795aSjb150015 smb_pre_transaction2(smb_request_t *sr)
288da6c28aaSamw {
28993bc28dbSGordon Ross DTRACE_SMB_START(op__Transaction2, smb_request_t *, sr);
290faa1795aSjb150015 return (SDRC_SUCCESS);
291faa1795aSjb150015 }
292faa1795aSjb150015
293faa1795aSjb150015 void
smb_post_transaction2(smb_request_t * sr)294faa1795aSjb150015 smb_post_transaction2(smb_request_t *sr)
295faa1795aSjb150015 {
29693bc28dbSGordon Ross DTRACE_SMB_DONE(op__Transaction2, smb_request_t *, sr);
297da6c28aaSamw }
298da6c28aaSamw
2997b59d02dSjb150015 smb_sdrc_t
smb_com_transaction2(struct smb_request * sr)300da6c28aaSamw smb_com_transaction2(struct smb_request *sr)
301da6c28aaSamw {
302da6c28aaSamw unsigned char msrcnt, suwcnt;
303da6c28aaSamw uint16_t tpscnt, tdscnt, mprcnt, mdrcnt, flags;
304da6c28aaSamw uint16_t pscnt, psoff, dscnt, dsoff;
305da6c28aaSamw uint32_t timeo;
306da6c28aaSamw smb_xa_t *xa;
307da6c28aaSamw int ready;
308da6c28aaSamw int rc;
309da6c28aaSamw
310da6c28aaSamw rc = smbsr_decode_vwv(sr, SMB_TRANSHDR_ED_FMT, &tpscnt, &tdscnt,
311da6c28aaSamw &mprcnt, &mdrcnt, &msrcnt, &flags, &timeo, &pscnt, &psoff, &dscnt,
312da6c28aaSamw &dsoff, &suwcnt);
313da6c28aaSamw
3147b59d02dSjb150015 if (rc != 0)
315faa1795aSjb150015 return (SDRC_ERROR);
316da6c28aaSamw
317da6c28aaSamw xa = smb_xa_create(sr->session, sr, tpscnt, tdscnt, mprcnt, mdrcnt,
318da6c28aaSamw msrcnt, suwcnt);
319da6c28aaSamw if (xa == 0) {
320dc20a302Sas200622 smbsr_error(sr, 0, ERRSRV, ERRnoroom);
321faa1795aSjb150015 return (SDRC_ERROR);
322da6c28aaSamw }
323da6c28aaSamw
324da6c28aaSamw xa->smb_flags = flags;
325da6c28aaSamw xa->smb_timeout = timeo;
326da6c28aaSamw xa->req_disp_param = pscnt;
327da6c28aaSamw xa->req_disp_data = dscnt;
328da6c28aaSamw
3297f3ef643SGordon Ross if (smb_mbc_copy(&xa->req_setup_mb, &sr->smb_vwv,
330da6c28aaSamw sr->smb_vwv.chain_offset, suwcnt*2)) {
331da6c28aaSamw smb_xa_rele(sr->session, xa);
332dc20a302Sas200622 smbsr_error(sr, 0, ERRDOS, ERRbadformat);
333faa1795aSjb150015 return (SDRC_ERROR);
334da6c28aaSamw }
3357f3ef643SGordon Ross if (smb_mbc_copy(&xa->req_param_mb, &sr->command, psoff, pscnt)) {
336da6c28aaSamw smb_xa_rele(sr->session, xa);
337dc20a302Sas200622 smbsr_error(sr, 0, ERRDOS, ERRbadformat);
338faa1795aSjb150015 return (SDRC_ERROR);
339da6c28aaSamw }
3407f3ef643SGordon Ross if (smb_mbc_copy(&xa->req_data_mb, &sr->command, dsoff, dscnt)) {
341da6c28aaSamw smb_xa_rele(sr->session, xa);
342dc20a302Sas200622 smbsr_error(sr, 0, ERRDOS, ERRbadformat);
343faa1795aSjb150015 return (SDRC_ERROR);
344da6c28aaSamw }
345da6c28aaSamw
346da6c28aaSamw ready = smb_trans_ready(xa);
347da6c28aaSamw
348da6c28aaSamw if (smb_xa_open(xa)) {
349da6c28aaSamw smb_xa_rele(sr->session, xa);
350ccc71be5SGordon Ross smbsr_error(sr, 0, ERRSRV, ERRsrverror);
351faa1795aSjb150015 return (SDRC_ERROR);
352da6c28aaSamw }
353da6c28aaSamw sr->r_xa = xa;
354da6c28aaSamw
355da6c28aaSamw if (!ready) {
3567b59d02dSjb150015 rc = smbsr_encode_empty_result(sr);
357faa1795aSjb150015 return ((rc == 0) ? SDRC_SUCCESS : SDRC_ERROR);
358da6c28aaSamw }
359da6c28aaSamw
360da6c28aaSamw if (!smb_xa_complete(xa)) {
361da6c28aaSamw smb_xa_close(xa);
362dc20a302Sas200622 smbsr_error(sr, 0, ERRDOS, ERRbadformat);
363faa1795aSjb150015 return (SDRC_ERROR);
364da6c28aaSamw }
365da6c28aaSamw
366da6c28aaSamw return (smb_trans2_dispatch(sr, xa));
367da6c28aaSamw }
368da6c28aaSamw
3697b59d02dSjb150015 smb_sdrc_t
smb_pre_transaction2_secondary(smb_request_t * sr)370faa1795aSjb150015 smb_pre_transaction2_secondary(smb_request_t *sr)
371faa1795aSjb150015 {
37293bc28dbSGordon Ross DTRACE_SMB_START(op__Transaction2Secondary, smb_request_t *, sr);
373faa1795aSjb150015 return (SDRC_SUCCESS);
374faa1795aSjb150015 }
375faa1795aSjb150015
376faa1795aSjb150015 void
smb_post_transaction2_secondary(smb_request_t * sr)377faa1795aSjb150015 smb_post_transaction2_secondary(smb_request_t *sr)
378faa1795aSjb150015 {
37993bc28dbSGordon Ross DTRACE_SMB_DONE(op__Transaction2Secondary, smb_request_t *, sr);
380faa1795aSjb150015 }
381faa1795aSjb150015
382faa1795aSjb150015 smb_sdrc_t
smb_com_transaction2_secondary(smb_request_t * sr)383faa1795aSjb150015 smb_com_transaction2_secondary(smb_request_t *sr)
384da6c28aaSamw {
385da6c28aaSamw uint16_t tpscnt, tdscnt, fid;
386da6c28aaSamw uint16_t pscnt, psoff, psdisp, dscnt, dsoff, dsdisp;
387da6c28aaSamw smb_xa_t *xa;
388da6c28aaSamw int rc;
389da6c28aaSamw
390da6c28aaSamw if ((xa = smbsr_lookup_xa(sr)) == 0) {
391dc20a302Sas200622 smbsr_error(sr, 0, ERRSRV, ERRsrverror);
392faa1795aSjb150015 return (SDRC_ERROR);
393da6c28aaSamw }
394da6c28aaSamw
395da6c28aaSamw if (sr->session->signing.flags & SMB_SIGNING_ENABLED) {
396da6c28aaSamw if (smb_sign_check_secondary(sr, xa->reply_seqnum) != 0) {
397dc20a302Sas200622 smbsr_error(sr, NT_STATUS_ACCESS_DENIED,
398da6c28aaSamw ERRDOS, ERRnoaccess);
399faa1795aSjb150015 return (SDRC_ERROR);
400da6c28aaSamw }
401da6c28aaSamw }
402da6c28aaSamw
403da6c28aaSamw if (xa->smb_com != SMB_COM_TRANSACTION2) {
404da6c28aaSamw return (SDRC_DROP_VC);
405da6c28aaSamw }
406da6c28aaSamw
407da6c28aaSamw rc = smbsr_decode_vwv(sr, SMB_TRANS2SHDR_ED_FMT, &tpscnt, &tdscnt,
408da6c28aaSamw &pscnt, &psoff, &psdisp, &dscnt, &dsoff, &dsdisp, &fid);
409da6c28aaSamw
4107b59d02dSjb150015 if (rc != 0)
411faa1795aSjb150015 return (SDRC_ERROR);
412da6c28aaSamw
413da6c28aaSamw mutex_enter(&xa->xa_mutex);
4147f3ef643SGordon Ross if (xa->smb_tpscnt > tpscnt)
4157f3ef643SGordon Ross xa->smb_tpscnt = tpscnt;
4167f3ef643SGordon Ross if (xa->smb_tdscnt > tdscnt)
4177f3ef643SGordon Ross xa->smb_tdscnt = tdscnt;
4187f3ef643SGordon Ross if (fid != 0xFFFF)
4197f3ef643SGordon Ross xa->xa_smb_fid = fid;
420da6c28aaSamw xa->req_disp_param = psdisp + pscnt;
421da6c28aaSamw xa->req_disp_data = dsdisp + dscnt;
422da6c28aaSamw
4237f3ef643SGordon Ross /*
4247f3ef643SGordon Ross * See comment in smb_com_transaction_secondary
4257f3ef643SGordon Ross */
4267f3ef643SGordon Ross if (xa->req_param_mb.chain_offset != psdisp) {
4277f3ef643SGordon Ross DTRACE_PROBE2(trans_param_disp,
4287f3ef643SGordon Ross smb_xa_t *, xa, uint16_t, psdisp);
4297f3ef643SGordon Ross xa->req_param_mb.chain_offset = psdisp;
4307f3ef643SGordon Ross }
4317f3ef643SGordon Ross if (xa->req_data_mb.chain_offset != dsdisp) {
4327f3ef643SGordon Ross DTRACE_PROBE2(trans_data_disp,
4337f3ef643SGordon Ross smb_xa_t *, xa, uint16_t, dsdisp);
4347f3ef643SGordon Ross xa->req_data_mb.chain_offset = dsdisp;
4357f3ef643SGordon Ross }
4367f3ef643SGordon Ross
4377f3ef643SGordon Ross if (smb_mbc_copy(&xa->req_param_mb, &sr->command, psoff, pscnt)) {
438da6c28aaSamw mutex_exit(&xa->xa_mutex);
439da6c28aaSamw smb_xa_close(xa);
440dc20a302Sas200622 smbsr_error(sr, 0, ERRDOS, ERRbadformat);
441faa1795aSjb150015 return (SDRC_ERROR);
442da6c28aaSamw }
4437f3ef643SGordon Ross if (smb_mbc_copy(&xa->req_data_mb, &sr->command, dsoff, dscnt)) {
444da6c28aaSamw mutex_exit(&xa->xa_mutex);
445da6c28aaSamw smb_xa_close(xa);
446dc20a302Sas200622 smbsr_error(sr, 0, ERRDOS, ERRbadformat);
447faa1795aSjb150015 return (SDRC_ERROR);
448da6c28aaSamw }
449da6c28aaSamw mutex_exit(&xa->xa_mutex);
450da6c28aaSamw
451da6c28aaSamw if (!smb_trans_ready(xa))
452da6c28aaSamw return (SDRC_NO_REPLY);
453da6c28aaSamw
454da6c28aaSamw if (!smb_xa_complete(xa))
455da6c28aaSamw return (SDRC_NO_REPLY);
456da6c28aaSamw
457da6c28aaSamw return (smb_trans2_dispatch(sr, xa));
458da6c28aaSamw }
459da6c28aaSamw
4607b59d02dSjb150015 static smb_sdrc_t
smb_nt_trans_dispatch(struct smb_request * sr,struct smb_xa * xa)461da6c28aaSamw smb_nt_trans_dispatch(struct smb_request *sr, struct smb_xa *xa)
462da6c28aaSamw {
463da6c28aaSamw int rc;
464da6c28aaSamw int total_bytes, n_setup, n_param, n_data;
465da6c28aaSamw int param_off, param_pad, data_off, data_pad;
466da6c28aaSamw
467da6c28aaSamw switch (xa->smb_func) {
468da6c28aaSamw case NT_TRANSACT_CREATE:
469faa1795aSjb150015 if ((rc = smb_pre_nt_transact_create(sr, xa)) == 0)
470da6c28aaSamw rc = smb_nt_transact_create(sr, xa);
471faa1795aSjb150015 smb_post_nt_transact_create(sr, xa);
472da6c28aaSamw break;
473da6c28aaSamw case NT_TRANSACT_NOTIFY_CHANGE:
474da6c28aaSamw rc = smb_nt_transact_notify_change(sr, xa);
475da6c28aaSamw break;
476da6c28aaSamw case NT_TRANSACT_QUERY_SECURITY_DESC:
477da6c28aaSamw rc = smb_nt_transact_query_security_info(sr, xa);
478da6c28aaSamw break;
479da6c28aaSamw case NT_TRANSACT_SET_SECURITY_DESC:
480da6c28aaSamw rc = smb_nt_transact_set_security_info(sr, xa);
481da6c28aaSamw break;
482da6c28aaSamw case NT_TRANSACT_IOCTL:
483da6c28aaSamw rc = smb_nt_transact_ioctl(sr, xa);
484da6c28aaSamw break;
485da6c28aaSamw case NT_TRANSACT_QUERY_QUOTA:
4869fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States rc = smb_nt_transact_query_quota(sr, xa);
487b1352070SAlan Wright break;
488da6c28aaSamw case NT_TRANSACT_SET_QUOTA:
4899fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States rc = smb_nt_transact_set_quota(sr, xa);
4909fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States break;
491bbf6f00cSJordan Brown case NT_TRANSACT_RENAME:
492bbf6f00cSJordan Brown rc = smb_nt_transact_rename(sr, xa);
493bbf6f00cSJordan Brown break;
494bbf6f00cSJordan Brown
495da6c28aaSamw default:
496dc20a302Sas200622 smbsr_error(sr, 0, ERRSRV, ERRsmbcmd);
497faa1795aSjb150015 return (SDRC_ERROR);
498da6c28aaSamw }
499da6c28aaSamw
500da6c28aaSamw switch (rc) {
501faa1795aSjb150015 case SDRC_SUCCESS:
502da6c28aaSamw break;
503da6c28aaSamw
504da6c28aaSamw case SDRC_DROP_VC:
505da6c28aaSamw case SDRC_NO_REPLY:
506faa1795aSjb150015 case SDRC_ERROR:
50759229f98Sjose borrego case SDRC_SR_KEPT:
508da6c28aaSamw return (rc);
509da6c28aaSamw
510faa1795aSjb150015 case SDRC_NOT_IMPLEMENTED:
511dc20a302Sas200622 smbsr_error(sr, 0, ERRSRV, ERRsmbcmd);
512faa1795aSjb150015 return (SDRC_ERROR);
513da6c28aaSamw
514da6c28aaSamw default:
515da6c28aaSamw break;
516da6c28aaSamw }
517da6c28aaSamw
518da6c28aaSamw n_setup = MBC_LENGTH(&xa->rep_setup_mb);
519da6c28aaSamw n_param = MBC_LENGTH(&xa->rep_param_mb);
520da6c28aaSamw n_data = MBC_LENGTH(&xa->rep_data_mb);
521da6c28aaSamw
522da6c28aaSamw if (xa->smb_msrcnt < n_setup ||
523da6c28aaSamw xa->smb_mprcnt < n_param ||
524da6c28aaSamw xa->smb_mdrcnt < n_data) {
525dc20a302Sas200622 smbsr_error(sr, 0, ERRSRV, ERRsmbcmd);
526faa1795aSjb150015 return (SDRC_ERROR);
527da6c28aaSamw }
528da6c28aaSamw
529da6c28aaSamw /* neato, blast it over there */
530da6c28aaSamw
531da6c28aaSamw n_setup = (n_setup + 1) / 2; /* Conver to setup words */
532da6c28aaSamw param_pad = 1; /* must be one */
533da6c28aaSamw param_off = param_pad + 32 + 37 + (n_setup << 1) + 2;
534da6c28aaSamw data_pad = (4 - ((param_off + n_param) & 3)) % 4; /* Pad to 4 byte */
535da6c28aaSamw data_off = param_off + n_param + data_pad; /* Param off from hdr */
536da6c28aaSamw total_bytes = param_pad + n_param + data_pad + n_data;
537da6c28aaSamw
5387b59d02dSjb150015 rc = smbsr_encode_result(sr, 18+n_setup, total_bytes,
539da6c28aaSamw "b3.llllllllbCw#.C#.C",
540da6c28aaSamw 18 + n_setup, /* wct */
541da6c28aaSamw n_param, /* Total Parameter Bytes */
542da6c28aaSamw n_data, /* Total Data Bytes */
543da6c28aaSamw n_param, /* Total Parameter Bytes this buffer */
544da6c28aaSamw param_off, /* Param offset from header start */
545da6c28aaSamw 0, /* Param displacement */
546da6c28aaSamw n_data, /* Total Data Bytes this buffer */
547da6c28aaSamw data_off, /* Data offset from header start */
548da6c28aaSamw 0, /* Data displacement */
549da6c28aaSamw n_setup, /* suwcnt */
550da6c28aaSamw &xa->rep_setup_mb, /* setup[] */
551da6c28aaSamw total_bytes, /* Total data bytes */
552da6c28aaSamw param_pad,
553da6c28aaSamw &xa->rep_param_mb,
554da6c28aaSamw data_pad,
555da6c28aaSamw &xa->rep_data_mb);
556faa1795aSjb150015 return ((rc == 0) ? SDRC_SUCCESS : SDRC_ERROR);
557da6c28aaSamw }
558da6c28aaSamw
559faa1795aSjb150015 smb_sdrc_t
smb_pre_nt_transact(smb_request_t * sr)560faa1795aSjb150015 smb_pre_nt_transact(smb_request_t *sr)
561faa1795aSjb150015 {
56293bc28dbSGordon Ross DTRACE_SMB_START(op__NtTransact, smb_request_t *, sr);
563faa1795aSjb150015 return (SDRC_SUCCESS);
564faa1795aSjb150015 }
565faa1795aSjb150015
566faa1795aSjb150015 void
smb_post_nt_transact(smb_request_t * sr)567faa1795aSjb150015 smb_post_nt_transact(smb_request_t *sr)
568faa1795aSjb150015 {
56993bc28dbSGordon Ross DTRACE_SMB_DONE(op__NtTransact, smb_request_t *, sr);
570faa1795aSjb150015 }
571da6c28aaSamw
5727b59d02dSjb150015 smb_sdrc_t
smb_com_nt_transact(struct smb_request * sr)573da6c28aaSamw smb_com_nt_transact(struct smb_request *sr)
574da6c28aaSamw {
575da6c28aaSamw uint16_t Function;
576da6c28aaSamw unsigned char MaxSetupCount, SetupCount;
577da6c28aaSamw uint32_t TotalParameterCount, TotalDataCount;
578da6c28aaSamw uint32_t MaxParameterCount, MaxDataCount, pscnt;
579da6c28aaSamw uint32_t psoff, dscnt, dsoff;
580da6c28aaSamw smb_xa_t *xa;
581da6c28aaSamw int ready;
582da6c28aaSamw int rc;
583da6c28aaSamw
584da6c28aaSamw rc = smbsr_decode_vwv(sr, SMB_NT_TRANSHDR_ED_FMT, &MaxSetupCount,
585da6c28aaSamw &TotalParameterCount, &TotalDataCount, &MaxParameterCount,
586da6c28aaSamw &MaxDataCount, &pscnt, &psoff, &dscnt,
587da6c28aaSamw &dsoff, &SetupCount, &Function);
588da6c28aaSamw
5897b59d02dSjb150015 if (rc != 0)
590faa1795aSjb150015 return (SDRC_ERROR);
591da6c28aaSamw
592da6c28aaSamw xa = smb_xa_create(sr->session, sr, TotalParameterCount, TotalDataCount,
593da6c28aaSamw MaxParameterCount, MaxDataCount, MaxSetupCount, SetupCount);
594da6c28aaSamw if (xa == 0) {
595dc20a302Sas200622 smbsr_error(sr, 0, ERRSRV, ERRnoroom);
596faa1795aSjb150015 return (SDRC_ERROR);
597da6c28aaSamw }
598da6c28aaSamw
599da6c28aaSamw xa->smb_flags = 0;
600da6c28aaSamw xa->smb_timeout = 0;
601da6c28aaSamw xa->smb_func = Function;
602da6c28aaSamw xa->req_disp_param = pscnt;
603da6c28aaSamw xa->req_disp_data = dscnt;
604da6c28aaSamw
6057f3ef643SGordon Ross if (smb_mbc_copy(&xa->req_setup_mb, &sr->smb_vwv,
606da6c28aaSamw sr->smb_vwv.chain_offset, SetupCount * 2)) {
607da6c28aaSamw smb_xa_rele(sr->session, xa);
608dc20a302Sas200622 smbsr_error(sr, 0, ERRDOS, ERRbadformat);
609faa1795aSjb150015 return (SDRC_ERROR);
610da6c28aaSamw }
6117f3ef643SGordon Ross if (smb_mbc_copy(&xa->req_param_mb, &sr->command, psoff, pscnt)) {
612da6c28aaSamw smb_xa_rele(sr->session, xa);
613dc20a302Sas200622 smbsr_error(sr, 0, ERRDOS, ERRbadformat);
614faa1795aSjb150015 return (SDRC_ERROR);
615da6c28aaSamw }
6167f3ef643SGordon Ross if (smb_mbc_copy(&xa->req_data_mb, &sr->command, dsoff, dscnt)) {
617da6c28aaSamw smb_xa_rele(sr->session, xa);
618dc20a302Sas200622 smbsr_error(sr, 0, ERRDOS, ERRbadformat);
619faa1795aSjb150015 return (SDRC_ERROR);
620da6c28aaSamw }
621da6c28aaSamw
622da6c28aaSamw ready = smb_trans_ready(xa);
623da6c28aaSamw
624da6c28aaSamw if (smb_xa_open(xa)) {
625da6c28aaSamw smb_xa_rele(sr->session, xa);
626ccc71be5SGordon Ross smbsr_error(sr, 0, ERRSRV, ERRsrverror);
627faa1795aSjb150015 return (SDRC_ERROR);
628da6c28aaSamw }
629da6c28aaSamw sr->r_xa = xa;
630da6c28aaSamw
631da6c28aaSamw if (!ready) {
6327b59d02dSjb150015 rc = smbsr_encode_empty_result(sr);
633faa1795aSjb150015 return ((rc == 0) ? SDRC_SUCCESS : SDRC_ERROR);
634da6c28aaSamw }
635da6c28aaSamw
636da6c28aaSamw if (!smb_xa_complete(xa)) {
637da6c28aaSamw smb_xa_close(xa);
638dc20a302Sas200622 smbsr_error(sr, 0, ERRDOS, ERRbadformat);
639faa1795aSjb150015 return (SDRC_ERROR);
640da6c28aaSamw }
641da6c28aaSamw
642da6c28aaSamw return (smb_nt_trans_dispatch(sr, xa));
643da6c28aaSamw }
644da6c28aaSamw
645faa1795aSjb150015 smb_sdrc_t
smb_pre_nt_transact_secondary(smb_request_t * sr)646faa1795aSjb150015 smb_pre_nt_transact_secondary(smb_request_t *sr)
647faa1795aSjb150015 {
64893bc28dbSGordon Ross DTRACE_SMB_START(op__NtTransactSecondary, smb_request_t *, sr);
649faa1795aSjb150015 return (SDRC_SUCCESS);
650faa1795aSjb150015 }
651faa1795aSjb150015
652faa1795aSjb150015 void
smb_post_nt_transact_secondary(smb_request_t * sr)653faa1795aSjb150015 smb_post_nt_transact_secondary(smb_request_t *sr)
654faa1795aSjb150015 {
65593bc28dbSGordon Ross DTRACE_SMB_DONE(op__NtTransactSecondary, smb_request_t *, sr);
656faa1795aSjb150015 }
657da6c28aaSamw
6587b59d02dSjb150015 smb_sdrc_t
smb_com_nt_transact_secondary(struct smb_request * sr)659da6c28aaSamw smb_com_nt_transact_secondary(struct smb_request *sr)
660da6c28aaSamw {
661da6c28aaSamw uint16_t tpscnt, tdscnt, fid;
662da6c28aaSamw uint16_t pscnt, psoff, psdisp, dscnt, dsoff, dsdisp;
663da6c28aaSamw smb_xa_t *xa;
664da6c28aaSamw int rc;
665da6c28aaSamw
666da6c28aaSamw if ((xa = smbsr_lookup_xa(sr)) == 0) {
667dc20a302Sas200622 smbsr_error(sr, 0, ERRSRV, ERRsrverror);
668faa1795aSjb150015 return (SDRC_ERROR);
669da6c28aaSamw }
670da6c28aaSamw
671da6c28aaSamw if (sr->session->signing.flags & SMB_SIGNING_ENABLED) {
672da6c28aaSamw if (smb_sign_check_secondary(sr, xa->reply_seqnum) != 0) {
673dc20a302Sas200622 smbsr_error(sr, NT_STATUS_ACCESS_DENIED,
674da6c28aaSamw ERRDOS, ERRnoaccess);
675faa1795aSjb150015 return (SDRC_ERROR);
676da6c28aaSamw }
677da6c28aaSamw }
678da6c28aaSamw
679da6c28aaSamw if (xa->smb_com != SMB_COM_TRANSACTION2) {
680da6c28aaSamw return (SDRC_DROP_VC);
681da6c28aaSamw }
682da6c28aaSamw
683da6c28aaSamw rc = smbsr_decode_vwv(sr, SMB_TRANS2SHDR_ED_FMT, &tpscnt, &tdscnt,
684da6c28aaSamw &pscnt, &psoff, &psdisp, &dscnt, &dsoff, &dsdisp, &fid);
685da6c28aaSamw
6867b59d02dSjb150015 if (rc != 0)
687faa1795aSjb150015 return (SDRC_ERROR);
688da6c28aaSamw
689da6c28aaSamw mutex_enter(&xa->xa_mutex);
6907f3ef643SGordon Ross if (xa->smb_tpscnt > tpscnt)
6917f3ef643SGordon Ross xa->smb_tpscnt = tpscnt;
6927f3ef643SGordon Ross if (xa->smb_tdscnt > tdscnt)
6937f3ef643SGordon Ross xa->smb_tdscnt = tdscnt;
6947f3ef643SGordon Ross if (fid != 0xFFFF)
6957f3ef643SGordon Ross xa->xa_smb_fid = fid;
696da6c28aaSamw xa->req_disp_param = psdisp + pscnt;
697da6c28aaSamw xa->req_disp_data = dsdisp + dscnt;
698da6c28aaSamw
6997f3ef643SGordon Ross /*
7007f3ef643SGordon Ross * See comment in smb_com_transaction_secondary
7017f3ef643SGordon Ross */
7027f3ef643SGordon Ross if (xa->req_param_mb.chain_offset != psdisp) {
7037f3ef643SGordon Ross DTRACE_PROBE2(trans_param_disp,
7047f3ef643SGordon Ross smb_xa_t *, xa, uint16_t, psdisp);
7057f3ef643SGordon Ross xa->req_param_mb.chain_offset = psdisp;
7067f3ef643SGordon Ross }
7077f3ef643SGordon Ross if (xa->req_data_mb.chain_offset != dsdisp) {
7087f3ef643SGordon Ross DTRACE_PROBE2(trans_data_disp,
7097f3ef643SGordon Ross smb_xa_t *, xa, uint16_t, dsdisp);
7107f3ef643SGordon Ross xa->req_data_mb.chain_offset = dsdisp;
7117f3ef643SGordon Ross }
7127f3ef643SGordon Ross
7137f3ef643SGordon Ross if (smb_mbc_copy(&xa->req_param_mb, &sr->command, psoff, pscnt)) {
714da6c28aaSamw mutex_exit(&xa->xa_mutex);
715da6c28aaSamw smb_xa_close(xa);
716dc20a302Sas200622 smbsr_error(sr, 0, ERRDOS, ERRbadformat);
717faa1795aSjb150015 return (SDRC_ERROR);
718da6c28aaSamw }
7197f3ef643SGordon Ross if (smb_mbc_copy(&xa->req_data_mb, &sr->command, dsoff, dscnt)) {
720da6c28aaSamw mutex_exit(&xa->xa_mutex);
721da6c28aaSamw smb_xa_close(xa);
722dc20a302Sas200622 smbsr_error(sr, 0, ERRDOS, ERRbadformat);
723faa1795aSjb150015 return (SDRC_ERROR);
724da6c28aaSamw }
725da6c28aaSamw mutex_exit(&xa->xa_mutex);
726da6c28aaSamw
727da6c28aaSamw if (!smb_trans_ready(xa))
728da6c28aaSamw return (SDRC_NO_REPLY);
729da6c28aaSamw
730da6c28aaSamw if (!smb_xa_complete(xa))
731da6c28aaSamw return (SDRC_NO_REPLY);
732da6c28aaSamw
733da6c28aaSamw return (smb_nt_trans_dispatch(sr, xa));
734da6c28aaSamw }
735da6c28aaSamw
7367b59d02dSjb150015 static int
smb_trans_ready(smb_xa_t * xa)7379fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States smb_trans_ready(smb_xa_t *xa)
738da6c28aaSamw {
739da6c28aaSamw int rc;
740da6c28aaSamw
741da6c28aaSamw mutex_enter(&xa->xa_mutex);
742da6c28aaSamw rc = xa->req_disp_data >= xa->smb_tdscnt &&
743da6c28aaSamw xa->req_disp_param >= xa->smb_tpscnt;
744da6c28aaSamw mutex_exit(&xa->xa_mutex);
745da6c28aaSamw
746da6c28aaSamw return (rc);
747da6c28aaSamw }
748da6c28aaSamw
7493ad684d6Sjb150015 static void
smb_encode_SHARE_INFO_1(struct mbuf_chain * output,struct mbuf_chain * text,char * oem_name,uint16_t type,char * comment)7503ad684d6Sjb150015 smb_encode_SHARE_INFO_1(struct mbuf_chain *output, struct mbuf_chain *text,
7513ad684d6Sjb150015 char *oem_name, uint16_t type, char *comment)
752da6c28aaSamw {
7533db3f65cSamw (void) smb_mbc_encodef(output, "13c.wl", oem_name,
7543ad684d6Sjb150015 type, MBC_LENGTH(text));
755da6c28aaSamw
7563db3f65cSamw (void) smb_mbc_encodef(text, "s", comment ? comment : "");
7576537f381Sas200622 }
758da6c28aaSamw
7593ad684d6Sjb150015 static void
smb_encode_SHARE_INFO_2(struct mbuf_chain * output,struct mbuf_chain * text,smb_request_t * sr,char * oem_name,uint16_t type,char * comment,uint16_t access,char * path,char * password)7603ad684d6Sjb150015 smb_encode_SHARE_INFO_2(struct mbuf_chain *output, struct mbuf_chain *text,
7613ad684d6Sjb150015 smb_request_t *sr, char *oem_name, uint16_t type,
7623ad684d6Sjb150015 char *comment, uint16_t access, char *path, char *password)
763da6c28aaSamw {
764da6c28aaSamw unsigned char pword[9];
765da6c28aaSamw
766da6c28aaSamw bzero(pword, sizeof (pword));
767da6c28aaSamw (void) strncpy((char *)pword, password, sizeof (pword));
7683ad684d6Sjb150015 smb_encode_SHARE_INFO_1(output, text, oem_name, type, comment);
7693db3f65cSamw (void) smb_mbc_encodef(output, "wwwl9c.",
770da6c28aaSamw access,
771faa1795aSjb150015 sr->sr_cfg->skc_maxconnections,
7728622ec45SGordon Ross smb_server_get_session_count(sr->sr_server),
773da6c28aaSamw MBC_LENGTH(text),
7743ad684d6Sjb150015 pword);
7753db3f65cSamw (void) smb_mbc_encodef(text, "s", path);
776da6c28aaSamw }
777da6c28aaSamw
778*97264293SGordon Ross int smb_trans_share_enum = 0;
779*97264293SGordon Ross
780*97264293SGordon Ross /*
781*97264293SGordon Ross * This is a legacy interface, no longer supported.
782*97264293SGordon Ross * Clients now use MS-RPC for share enumeration.
783*97264293SGordon Ross * Does not implement access-based enumeration (ABE)
784*97264293SGordon Ross * so do not enable if you care about share list ABE.
785*97264293SGordon Ross */
786da6c28aaSamw int
smb_trans_net_share_enum(struct smb_request * sr,struct smb_xa * xa)787da6c28aaSamw smb_trans_net_share_enum(struct smb_request *sr, struct smb_xa *xa)
788da6c28aaSamw {
789a90cf9f2SGordon Ross uint16_t pid_hi, pid_lo;
790a90cf9f2SGordon Ross
791da6c28aaSamw /*
792da6c28aaSamw * Number of data bytes that will
793da6c28aaSamw * be sent in the current response
794da6c28aaSamw */
795da6c28aaSamw uint16_t data_scnt;
796da6c28aaSamw
797da6c28aaSamw /*
798da6c28aaSamw * Total number of data bytes that
799da6c28aaSamw * are sent till now. This is only
800da6c28aaSamw * used for calculating current data
801da6c28aaSamw * displacement
802da6c28aaSamw */
803da6c28aaSamw uint16_t tot_data_scnt;
804da6c28aaSamw
805da6c28aaSamw /*
806da6c28aaSamw * Number of parameter bytes should
807da6c28aaSamw * be sent for the current response.
808da6c28aaSamw * It is 8 for the 1st response and
809da6c28aaSamw * 0 for others
810da6c28aaSamw */
811da6c28aaSamw uint16_t param_scnt;
812da6c28aaSamw
813da6c28aaSamw /* number of setup and parameter bytes */
814da6c28aaSamw uint16_t n_setup, n_param;
815da6c28aaSamw
816da6c28aaSamw /* data and parameter displacement */
817da6c28aaSamw uint16_t data_disp, param_disp;
818da6c28aaSamw
819da6c28aaSamw /* parameter and data offset and pad */
820da6c28aaSamw int param_off, param_pad, data_off, data_pad;
821da6c28aaSamw
822da6c28aaSamw /*
823da6c28aaSamw * total bytes of parameters and data
824da6c28aaSamw * in the packet, plus the pad bytes.
825da6c28aaSamw */
826da6c28aaSamw int tot_packet_bytes;
827da6c28aaSamw
8283ad684d6Sjb150015 boolean_t first_resp;
829da6c28aaSamw
8303ad684d6Sjb150015 char fmt[16];
8313ad684d6Sjb150015 struct mbuf_chain reply;
8323ad684d6Sjb150015
8333ad684d6Sjb150015 uint16_t level;
8343ad684d6Sjb150015 uint16_t pkt_bufsize;
8353ad684d6Sjb150015 smb_enumshare_info_t esi;
8363ad684d6Sjb150015 char *sent_buf;
8373ad684d6Sjb150015
8383ad684d6Sjb150015 ASSERT(sr->uid_user);
839da6c28aaSamw
840*97264293SGordon Ross if (smb_trans_share_enum == 0)
841*97264293SGordon Ross return (SDRC_NOT_IMPLEMENTED);
842*97264293SGordon Ross
8433db3f65cSamw if (smb_mbc_decodef(&xa->req_param_mb, "ww", &level,
8443ad684d6Sjb150015 &esi.es_bufsize) != 0)
845faa1795aSjb150015 return (SDRC_NOT_IMPLEMENTED);
846da6c28aaSamw
847da6c28aaSamw if (level != 1) {
8483ad684d6Sjb150015 /*
8493ad684d6Sjb150015 * Only level 1 is valid for NetShareEnum
8503ad684d6Sjb150015 * None of the error codes in the spec are meaningful
8513ad684d6Sjb150015 * here. This error code is returned by Windows.
8523ad684d6Sjb150015 */
8533db3f65cSamw (void) smb_mbc_encodef(&xa->rep_param_mb, "wwww",
8543ad684d6Sjb150015 ERROR_INVALID_LEVEL, 0, 0, 0);
855faa1795aSjb150015 return (SDRC_SUCCESS);
856da6c28aaSamw }
857da6c28aaSamw
858148c5f43SAlan Wright esi.es_buf = smb_srm_zalloc(sr, esi.es_bufsize);
859c5866007SKeyur Desai esi.es_posix_uid = crgetuid(sr->uid_user->u_cred);
8608622ec45SGordon Ross smb_kshare_enum(sr->sr_server, &esi);
861da6c28aaSamw
8623ad684d6Sjb150015 /* client buffer size is not big enough to hold any shares */
8633ad684d6Sjb150015 if (esi.es_nsent == 0) {
8643db3f65cSamw (void) smb_mbc_encodef(&xa->rep_param_mb, "wwww",
8653ad684d6Sjb150015 ERROR_MORE_DATA, 0, esi.es_nsent, esi.es_ntotal);
866faa1795aSjb150015 return (SDRC_SUCCESS);
867da6c28aaSamw }
868da6c28aaSamw
869da6c28aaSamw /*
8707f3ef643SGordon Ross * Initialize the reply mbuf chain. Note that we re-initialize
8717f3ef643SGordon Ross * this on each pass through the loop below.
8727f3ef643SGordon Ross */
8737f3ef643SGordon Ross MBC_SETUP(&reply, smb_maxbufsize);
8747f3ef643SGordon Ross
8757f3ef643SGordon Ross /*
876da6c28aaSamw * The rep_setup_mb is already initialized in smb_trans_dispatch().
877da6c28aaSamw * Calling MBC_INIT() will initialized the structure and so the
878da6c28aaSamw * pointer to the mbuf chains will be lost. Therefore, we need
879da6c28aaSamw * to free the resources before calling MBC_INIT() again.
880da6c28aaSamw */
8813ad684d6Sjb150015 n_setup = 0; /* Setup count for NetShareEnum SMB is 0 */
8827f3ef643SGordon Ross MBC_FLUSH(&xa->rep_setup_mb);
883da6c28aaSamw
8843ad684d6Sjb150015 n_param = 8;
8853ad684d6Sjb150015 pkt_bufsize = sr->session->smb_msg_size -
8863ad684d6Sjb150015 (SMB_HEADER_ED_LEN + RESP_HEADER_LEN + n_param);
887da6c28aaSamw
8883ad684d6Sjb150015 tot_data_scnt = 0;
8893ad684d6Sjb150015 sent_buf = esi.es_buf;
8903ad684d6Sjb150015 first_resp = B_TRUE;
8913ad684d6Sjb150015
8923ad684d6Sjb150015 while (tot_data_scnt < esi.es_datasize) {
8933ad684d6Sjb150015 data_scnt = esi.es_datasize - tot_data_scnt;
8943ad684d6Sjb150015 if (data_scnt > pkt_bufsize)
8953ad684d6Sjb150015 data_scnt = pkt_bufsize;
8967f3ef643SGordon Ross MBC_FLUSH(&xa->rep_data_mb);
8973ad684d6Sjb150015
8983ad684d6Sjb150015 (void) sprintf(fmt, "%dc", data_scnt);
8993db3f65cSamw (void) smb_mbc_encodef(&xa->rep_data_mb, fmt, sent_buf);
9003ad684d6Sjb150015
9013ad684d6Sjb150015 sent_buf += data_scnt;
902da6c28aaSamw tot_data_scnt += data_scnt;
903da6c28aaSamw
904da6c28aaSamw /* Only the 1st response packet contains parameters */
905da6c28aaSamw param_scnt = (first_resp) ? n_param : 0;
906da6c28aaSamw param_pad = 1; /* always one */
907da6c28aaSamw param_off = SMB_HEADER_ED_LEN + RESP_HEADER_LEN;
908da6c28aaSamw param_disp = (first_resp) ? 0 : n_param;
909da6c28aaSamw
9107f3ef643SGordon Ross MBC_FLUSH(&xa->rep_param_mb);
9113ad684d6Sjb150015
912da6c28aaSamw if (first_resp) {
9133ad684d6Sjb150015 first_resp = B_FALSE;
9143db3f65cSamw (void) smb_mbc_encodef(&xa->rep_param_mb, "wwww",
9153ad684d6Sjb150015 (esi.es_ntotal > esi.es_nsent)
9163ad684d6Sjb150015 ? ERROR_MORE_DATA : 0,
9173ad684d6Sjb150015 0, esi.es_nsent, esi.es_ntotal);
918da6c28aaSamw }
919da6c28aaSamw
920da6c28aaSamw data_pad = (param_off + n_param) & 1; /* Pad to short */
921da6c28aaSamw
922da6c28aaSamw /* data off from hdr start */
923da6c28aaSamw data_off = param_off + param_scnt + data_pad;
924da6c28aaSamw data_disp = tot_data_scnt - data_scnt;
925da6c28aaSamw tot_packet_bytes = param_pad + param_scnt + data_pad +
926da6c28aaSamw data_scnt;
927da6c28aaSamw
928a90cf9f2SGordon Ross pid_hi = sr->smb_pid >> 16;
929a90cf9f2SGordon Ross pid_lo = (uint16_t)sr->smb_pid;
930a90cf9f2SGordon Ross
9317f3ef643SGordon Ross MBC_FLUSH(&reply);
9323db3f65cSamw (void) smb_mbc_encodef(&reply, SMB_HEADER_ED_FMT,
933da6c28aaSamw sr->first_smb_com,
934da6c28aaSamw sr->smb_rcls,
935da6c28aaSamw sr->smb_reh,
936da6c28aaSamw sr->smb_err,
937da6c28aaSamw sr->smb_flg | SMB_FLAGS_REPLY,
938da6c28aaSamw sr->smb_flg2,
939a90cf9f2SGordon Ross pid_hi,
940da6c28aaSamw sr->smb_sig,
941da6c28aaSamw sr->smb_tid,
942a90cf9f2SGordon Ross pid_lo,
943da6c28aaSamw sr->smb_uid,
944da6c28aaSamw sr->smb_mid);
945da6c28aaSamw
9463db3f65cSamw (void) smb_mbc_encodef(&reply,
947da6c28aaSamw "bww2.wwwwwwb.Cw#.C#.C",
948da6c28aaSamw 10 + n_setup, /* wct */
949da6c28aaSamw n_param, /* Total Parameter Bytes */
9503ad684d6Sjb150015 esi.es_datasize, /* Total Data Bytes */
951da6c28aaSamw param_scnt, /* Total Parameter Bytes this buffer */
952da6c28aaSamw param_off, /* Param offset from header start */
953da6c28aaSamw param_disp, /* Param displacement */
954da6c28aaSamw data_scnt, /* Total Data Bytes this buffer */
955da6c28aaSamw data_off, /* Data offset from header start */
956da6c28aaSamw data_disp, /* Data displacement */
957da6c28aaSamw n_setup, /* suwcnt */
958da6c28aaSamw &xa->rep_setup_mb, /* setup[] */
959da6c28aaSamw tot_packet_bytes, /* Total data bytes */
960da6c28aaSamw param_pad,
961da6c28aaSamw &xa->rep_param_mb,
962da6c28aaSamw data_pad,
963da6c28aaSamw &xa->rep_data_mb);
964da6c28aaSamw
965da6c28aaSamw if (sr->session->signing.flags & SMB_SIGNING_ENABLED)
966b89a8333Snatalie li - Sun Microsystems - Irvine United States smb_sign_reply(sr, &reply);
967da6c28aaSamw
968da6c28aaSamw (void) smb_session_send(sr->session, 0, &reply);
9697f3ef643SGordon Ross
970da6c28aaSamw }
971da6c28aaSamw
9727f3ef643SGordon Ross m_freem(reply.chain);
9737f3ef643SGordon Ross
974da6c28aaSamw return (SDRC_NO_REPLY);
975da6c28aaSamw }
976da6c28aaSamw
977*97264293SGordon Ross int smb_trans_share_getinfo = 0;
978*97264293SGordon Ross
979*97264293SGordon Ross /*
980*97264293SGordon Ross * This is a legacy interface, no longer supported.
981*97264293SGordon Ross * Clients now use MS-RPC to get share information.
982*97264293SGordon Ross * Does not implement access-based enumeration (ABE)
983*97264293SGordon Ross * so do not enable if you care about share list ABE.
984*97264293SGordon Ross */
985da6c28aaSamw int
smb_trans_net_share_getinfo(smb_request_t * sr,struct smb_xa * xa)9863ad684d6Sjb150015 smb_trans_net_share_getinfo(smb_request_t *sr, struct smb_xa *xa)
987da6c28aaSamw {
9883ad684d6Sjb150015 uint16_t level, max_bytes, access;
989da6c28aaSamw struct mbuf_chain str_mb;
990da6c28aaSamw char *share;
991da6c28aaSamw char *password;
992148c5f43SAlan Wright smb_kshare_t *si;
993da6c28aaSamw
994*97264293SGordon Ross if (smb_trans_share_getinfo == 0)
995*97264293SGordon Ross return (SDRC_NOT_IMPLEMENTED);
996*97264293SGordon Ross
9973db3f65cSamw if (smb_mbc_decodef(&xa->req_param_mb, "%sww", sr,
9983ad684d6Sjb150015 &share, &level, &max_bytes) != 0)
999faa1795aSjb150015 return (SDRC_NOT_IMPLEMENTED);
1000da6c28aaSamw
10018622ec45SGordon Ross si = smb_kshare_lookup(sr->sr_server, share);
1002148c5f43SAlan Wright if ((si == NULL) || (si->shr_oemname == NULL)) {
10033db3f65cSamw (void) smb_mbc_encodef(&xa->rep_param_mb, "www",
1004da6c28aaSamw NERR_NetNameNotFound, 0, 0);
1005148c5f43SAlan Wright if (si)
10068622ec45SGordon Ross smb_kshare_release(sr->sr_server, si);
1007faa1795aSjb150015 return (SDRC_SUCCESS);
1008da6c28aaSamw }
1009da6c28aaSamw
10103ad684d6Sjb150015 access = SHARE_ACCESS_ALL;
1011da6c28aaSamw password = "";
1012da6c28aaSamw
1013da6c28aaSamw MBC_INIT(&str_mb, max_bytes);
1014da6c28aaSamw
1015da6c28aaSamw switch (level) {
1016da6c28aaSamw case 0 :
1017148c5f43SAlan Wright (void) smb_mbc_encodef(&xa->rep_data_mb, "13c",
1018148c5f43SAlan Wright si->shr_oemname);
1019da6c28aaSamw break;
1020da6c28aaSamw
1021da6c28aaSamw case 1 :
10223ad684d6Sjb150015 smb_encode_SHARE_INFO_1(&xa->rep_data_mb, &str_mb,
1023148c5f43SAlan Wright si->shr_oemname, si->shr_type, si->shr_cmnt);
1024da6c28aaSamw break;
1025da6c28aaSamw
1026da6c28aaSamw case 2 :
10273ad684d6Sjb150015 smb_encode_SHARE_INFO_2(&xa->rep_data_mb, &str_mb, sr,
1028148c5f43SAlan Wright si->shr_oemname, si->shr_type, si->shr_cmnt, access,
1029148c5f43SAlan Wright si->shr_path, password);
10303ad684d6Sjb150015 break;
10313ad684d6Sjb150015
1032da6c28aaSamw default:
10338622ec45SGordon Ross smb_kshare_release(sr->sr_server, si);
10343db3f65cSamw (void) smb_mbc_encodef(&xa->rep_param_mb, "www",
10353ad684d6Sjb150015 ERROR_INVALID_LEVEL, 0, 0);
1036da6c28aaSamw m_freem(str_mb.chain);
1037faa1795aSjb150015 return (SDRC_NOT_IMPLEMENTED);
1038da6c28aaSamw }
1039da6c28aaSamw
10408622ec45SGordon Ross smb_kshare_release(sr->sr_server, si);
10413db3f65cSamw (void) smb_mbc_encodef(&xa->rep_param_mb, "www", NERR_Success,
1042da6c28aaSamw -MBC_LENGTH(&xa->rep_data_mb),
1043da6c28aaSamw MBC_LENGTH(&xa->rep_data_mb) + MBC_LENGTH(&str_mb));
10443db3f65cSamw (void) smb_mbc_encodef(&xa->rep_data_mb, "C", &str_mb);
1045da6c28aaSamw m_freem(str_mb.chain);
1046faa1795aSjb150015 return (SDRC_SUCCESS);
1047da6c28aaSamw }
1048da6c28aaSamw
1049da6c28aaSamw int
smb_trans_net_workstation_getinfo(struct smb_request * sr,struct smb_xa * xa)10503ad684d6Sjb150015 smb_trans_net_workstation_getinfo(struct smb_request *sr, struct smb_xa *xa)
1051da6c28aaSamw {
10523ad684d6Sjb150015 uint16_t level, max_bytes;
1053da6c28aaSamw struct mbuf_chain str_mb;
1054da6c28aaSamw char *domain;
1055da6c28aaSamw char *hostname;
1056da6c28aaSamw
10573db3f65cSamw if ((smb_mbc_decodef(&xa->req_param_mb, "ww",
10583ad684d6Sjb150015 &level, &max_bytes) != 0) ||
1059da6c28aaSamw (level != 10)) {
10603db3f65cSamw (void) smb_mbc_encodef(&xa->rep_param_mb, "wwww",
1061da6c28aaSamw NERR_BadTransactConfig, 0, 0, 0);
1062faa1795aSjb150015 return (SDRC_SUCCESS);
1063da6c28aaSamw }
1064da6c28aaSamw
1065b89a8333Snatalie li - Sun Microsystems - Irvine United States domain = sr->sr_cfg->skc_nbdomain;
1066faa1795aSjb150015 hostname = sr->sr_cfg->skc_hostname;
1067da6c28aaSamw
1068da6c28aaSamw MBC_INIT(&str_mb, max_bytes);
1069da6c28aaSamw
10703db3f65cSamw (void) smb_mbc_encodef(&str_mb, "."); /* Prevent NULL pointers */
1071da6c28aaSamw
10723db3f65cSamw (void) smb_mbc_encodef(&xa->rep_data_mb, "l", MBC_LENGTH(&str_mb));
10733db3f65cSamw (void) smb_mbc_encodef(&str_mb, "s", hostname);
10743db3f65cSamw (void) smb_mbc_encodef(&xa->rep_data_mb, "l", MBC_LENGTH(&str_mb));
10753db3f65cSamw (void) smb_mbc_encodef(&str_mb, "s", "nobody");
10763db3f65cSamw (void) smb_mbc_encodef(&xa->rep_data_mb, "l", MBC_LENGTH(&str_mb));
10773db3f65cSamw (void) smb_mbc_encodef(&str_mb, "s", domain);
10783db3f65cSamw (void) smb_mbc_encodef(&xa->rep_data_mb, "bbl",
1079fd9ee8b5Sjoyce mcintosh (uint8_t)sr->sr_cfg->skc_version.sv_major,
1080fd9ee8b5Sjoyce mcintosh (uint8_t)sr->sr_cfg->skc_version.sv_minor,
10819fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States MBC_LENGTH(&str_mb));
10823db3f65cSamw (void) smb_mbc_encodef(&str_mb, "s", domain);
10833db3f65cSamw (void) smb_mbc_encodef(&xa->rep_data_mb, "l", MBC_LENGTH(&str_mb));
10843db3f65cSamw (void) smb_mbc_encodef(&str_mb, "s", domain);
1085da6c28aaSamw
10863db3f65cSamw (void) smb_mbc_encodef(&xa->rep_param_mb, "www", 0,
1087da6c28aaSamw -MBC_LENGTH(&xa->rep_data_mb),
1088da6c28aaSamw MBC_LENGTH(&xa->rep_data_mb) + MBC_LENGTH(&str_mb));
10893db3f65cSamw (void) smb_mbc_encodef(&xa->rep_data_mb, "C", &str_mb);
1090da6c28aaSamw m_freem(str_mb.chain);
1091faa1795aSjb150015 return (SDRC_SUCCESS);
1092da6c28aaSamw }
1093da6c28aaSamw
1094da6c28aaSamw int
smb_trans_net_user_getinfo(struct smb_request * sr,struct smb_xa * xa)10953ad684d6Sjb150015 smb_trans_net_user_getinfo(struct smb_request *sr, struct smb_xa *xa)
1096da6c28aaSamw {
10973ad684d6Sjb150015 uint16_t level, max_bytes;
1098da6c28aaSamw unsigned char *user;
1099da6c28aaSamw int rc;
1100da6c28aaSamw
11013db3f65cSamw rc = smb_mbc_decodef(&xa->req_param_mb, "%sww", sr,
1102da6c28aaSamw &user,
1103da6c28aaSamw &level,
1104da6c28aaSamw &max_bytes);
1105da6c28aaSamw
1106da6c28aaSamw if (rc != 0)
1107faa1795aSjb150015 return (SDRC_NOT_IMPLEMENTED);
1108da6c28aaSamw
11093db3f65cSamw (void) smb_mbc_encodef(&xa->rep_param_mb, "www",
1110da6c28aaSamw NERR_UserNotFound, 0, 0);
1111faa1795aSjb150015 return (SDRC_SUCCESS);
1112da6c28aaSamw }
1113da6c28aaSamw
11147b59d02dSjb150015 smb_sdrc_t
smb_trans_net_server_getinfo(struct smb_request * sr,struct smb_xa * xa)11153ad684d6Sjb150015 smb_trans_net_server_getinfo(struct smb_request *sr, struct smb_xa *xa)
1116da6c28aaSamw {
11173ad684d6Sjb150015 uint16_t level, buf_size;
11183ad684d6Sjb150015 uint16_t avail_data, max_data;
1119da6c28aaSamw char server_name[16];
1120da6c28aaSamw struct mbuf_chain str_mb;
1121da6c28aaSamw
11223db3f65cSamw if (smb_mbc_decodef(&xa->req_param_mb, "ww", &level, &buf_size) != 0)
1123faa1795aSjb150015 return (SDRC_ERROR);
1124da6c28aaSamw
11253ad684d6Sjb150015 max_data = MBC_MAXBYTES(&xa->rep_data_mb);
1126da6c28aaSamw
1127da6c28aaSamw MBC_INIT(&str_mb, buf_size);
1128da6c28aaSamw
1129da6c28aaSamw bzero(server_name, sizeof (server_name));
11303ad684d6Sjb150015 (void) strncpy(server_name, sr->sr_cfg->skc_hostname,
11313ad684d6Sjb150015 sizeof (server_name));
1132da6c28aaSamw
11333ad684d6Sjb150015 /* valid levels are 0 and 1 */
1134da6c28aaSamw switch (level) {
1135da6c28aaSamw case 0:
11363db3f65cSamw (void) smb_mbc_encodef(&xa->rep_data_mb, "16c", server_name);
1137da6c28aaSamw break;
11383ad684d6Sjb150015
1139da6c28aaSamw case 1:
11403db3f65cSamw (void) smb_mbc_encodef(&str_mb, "s",
11413ad684d6Sjb150015 sr->sr_cfg->skc_system_comment);
11423db3f65cSamw (void) smb_mbc_encodef(&xa->rep_data_mb, "16cbbll", server_name,
1143fd9ee8b5Sjoyce mcintosh (uint8_t)sr->sr_cfg->skc_version.sv_major,
1144fd9ee8b5Sjoyce mcintosh (uint8_t)sr->sr_cfg->skc_version.sv_minor,
11453ad684d6Sjb150015 MY_SERVER_TYPE, max_data - MBC_LENGTH(&str_mb));
1146da6c28aaSamw break;
11473ad684d6Sjb150015
1148da6c28aaSamw default:
11493db3f65cSamw (void) smb_mbc_encodef(&xa->rep_param_mb, "www",
11503ad684d6Sjb150015 ERROR_INVALID_LEVEL, 0, 0);
1151da6c28aaSamw m_freem(str_mb.chain);
11523ad684d6Sjb150015 return (SDRC_SUCCESS);
1153da6c28aaSamw }
1154da6c28aaSamw
11553ad684d6Sjb150015 avail_data = MBC_LENGTH(&xa->rep_data_mb) + MBC_LENGTH(&str_mb);
11563db3f65cSamw (void) smb_mbc_encodef(&xa->rep_param_mb, "www",
11573ad684d6Sjb150015 NERR_Success, max_data - avail_data, avail_data);
11583db3f65cSamw (void) smb_mbc_encodef(&xa->rep_data_mb, "C", &str_mb);
1159da6c28aaSamw m_freem(str_mb.chain);
1160faa1795aSjb150015 return (SDRC_SUCCESS);
1161da6c28aaSamw }
1162da6c28aaSamw
1163da6c28aaSamw /*
1164da6c28aaSamw * 6.4 The NetServerEnum2 RAP Service
1165da6c28aaSamw *
1166da6c28aaSamw * The NetServerEnum2 RAP service lists all computers of the specified type
1167da6c28aaSamw * or types that are visible in the specified domains. It may also
1168da6c28aaSamw * enumerate domains.
1169da6c28aaSamw *
1170da6c28aaSamw * The following definition uses the notation and terminology defined in
1171da6c28aaSamw * the CIFS Remote Administration Protocol specification, which is required
1172da6c28aaSamw * in order to make it well-defined. The definition is:
1173da6c28aaSamw *
1174da6c28aaSamw * uint16_t NetServerEnum2 (
1175da6c28aaSamw * uint16_t sLevel,
1176da6c28aaSamw * RCVBUF pbBuffer,
1177da6c28aaSamw * RCVBUFLEN cbBuffer,
1178da6c28aaSamw * ENTCOUNT pcEntriesRead,
1179da6c28aaSamw * uint16_t *pcTotalAvail,
1180da6c28aaSamw * uint32_t fServerType,
1181da6c28aaSamw * char *pszDomain,
1182da6c28aaSamw * );
1183da6c28aaSamw *
1184da6c28aaSamw * where:
1185da6c28aaSamw *
1186da6c28aaSamw * sLevel specifies the level of detail (0 or 1) requested.
1187da6c28aaSamw *
1188da6c28aaSamw * pbBuffer points to the buffer to receive the returned data. If the
1189da6c28aaSamw * function is successful, the buffer contains a sequence of
1190da6c28aaSamw * server_info_x structures, where x is 0 or 1, depending on the
1191da6c28aaSamw * level of detail requested.
1192da6c28aaSamw *
1193da6c28aaSamw * cbBuffer specifies the size, in bytes, of the buffer pointed to by
1194da6c28aaSamw * the pbBuffer parameter.
1195da6c28aaSamw *
1196da6c28aaSamw * pcEntriesRead points to a 16 bit variable that receives a count of
1197da6c28aaSamw * the number of servers enumerated in the buffer. This count is
1198da6c28aaSamw * valid only if NetServerEnum2 returns the NERR_Success or
1199da6c28aaSamw * ERROR_MORE_DATA values.
1200da6c28aaSamw *
1201da6c28aaSamw * pcTotal Avail points to a 16 bit variable that receives a count of
1202da6c28aaSamw * the total number of available entries. This count is valid only if
1203da6c28aaSamw * NetServerEnum2 returns the NERR_Success or ERROR_MORE_DATA values.
1204da6c28aaSamw *
1205da6c28aaSamw * fServerType specifies the type or types of computers to enumerate.
1206da6c28aaSamw * Computers that match at least one of the specified types are
1207da6c28aaSamw * returned in the buffer. Possible values are defined in the request
1208da6c28aaSamw * parameters section.
1209da6c28aaSamw *
1210da6c28aaSamw * pszDomain points to a null-terminated string that contains the
1211da6c28aaSamw * name of the workgroup in which to enumerate computers of the
1212da6c28aaSamw * specified type or types. If the pszDomain parameter is a null
1213da6c28aaSamw * string or a null pointer, servers are enumerated for the current
1214da6c28aaSamw * domain of the computer.
1215da6c28aaSamw *
1216da6c28aaSamw * 6.4.1 Transaction Request Parameters section
1217da6c28aaSamw *
1218da6c28aaSamw * The Transaction request parameters section in this instance contains:
1219da6c28aaSamw * . The 16 bit function number for NetServerEnum2 which is 104.
1220da6c28aaSamw * . The parameter descriptor string which is "WrLehDz".
1221da6c28aaSamw * . The data descriptor string for the (returned) data which is "B16" for
1222da6c28aaSamw * level detail 0 or "B16BBDz" for level detail 1.
1223da6c28aaSamw * . The actual parameters as described by the parameter descriptor
1224da6c28aaSamw * string.
1225da6c28aaSamw *
1226da6c28aaSamw * The parameters are:
1227da6c28aaSamw * . A 16 bit integer with a value of 0 or 1 (corresponding to the "W" in
1228da6c28aaSamw * the parameter descriptor string. This represents the level of detail
1229da6c28aaSamw * the server is expected to return
1230da6c28aaSamw * . A 16 bit integer that contains the size of the receive buffer.
1231da6c28aaSamw * . A 32 bit integer that represents the type of servers the function
1232da6c28aaSamw * should enumerate. The possible values may be any of the following or
1233da6c28aaSamw * a combination of the following:
1234da6c28aaSamw *
1235da6c28aaSamw * SV_TYPE_WORKSTATION 0x00000001 All workstations
1236da6c28aaSamw * SV_TYPE_SERVER 0x00000002 All servers
1237da6c28aaSamw * SV_TYPE_SQLSERVER 0x00000004 Any server running with SQL
1238da6c28aaSamw * server
1239da6c28aaSamw * SV_TYPE_DOMAIN_CTRL 0x00000008 Primary domain controller
1240da6c28aaSamw * SV_TYPE_DOMAIN_BAKCTRL 0x00000010 Backup domain controller
1241da6c28aaSamw * SV_TYPE_TIME_SOURCE 0x00000020 Server running the timesource
1242da6c28aaSamw * service
1243da6c28aaSamw * SV_TYPE_AFP 0x00000040 Apple File Protocol servers
1244da6c28aaSamw * SV_TYPE_NOVELL 0x00000080 Novell servers
1245da6c28aaSamw * SV_TYPE_DOMAIN_MEMBER 0x00000100 Domain Member
1246da6c28aaSamw * SV_TYPE_PRINTQ_SERVER 0x00000200 Server sharing print queue
1247da6c28aaSamw * SV_TYPE_DIALIN_SERVER 0x00000400 Server running dialin service.
1248da6c28aaSamw * SV_TYPE_XENIX_SERVER 0x00000800 Xenix server
1249da6c28aaSamw * SV_TYPE_NT 0x00001000 NT server
1250da6c28aaSamw * SV_TYPE_WFW 0x00002000 Server running Windows for
1251da6c28aaSamw * Workgroups
1252da6c28aaSamw * SV_TYPE_SERVER_NT 0x00008000 Windows NT non DC server
1253da6c28aaSamw * SV_TYPE_POTENTIAL_BROWSER 0x00010000 Server that can run the browser
1254da6c28aaSamw * service
1255da6c28aaSamw * SV_TYPE_BACKUP_BROWSER 0x00020000 Backup browser server
1256da6c28aaSamw * SV_TYPE_MASTER_BROWSER 0x00040000 Master browser server
1257da6c28aaSamw * SV_TYPE_DOMAIN_MASTER 0x00080000 Domain Master Browser server
1258da6c28aaSamw * SV_TYPE_LOCAL_LIST_ONLY 0x40000000 Enumerate only entries marked
1259da6c28aaSamw * "local"
1260da6c28aaSamw * SV_TYPE_DOMAIN_ENUM 0x80000000 Enumerate Domains. The pszDomain
1261da6c28aaSamw * parameter must be NULL.
1262da6c28aaSamw *
1263da6c28aaSamw * . A null terminated ASCII string representing the pszDomain parameter
1264da6c28aaSamw * described above
1265da6c28aaSamw *
1266da6c28aaSamw * 6.4.2 Transaction Request Data section
1267da6c28aaSamw *
1268da6c28aaSamw * There is no data or auxiliary data to send as part of the request.
1269da6c28aaSamw *
1270da6c28aaSamw * 6.4.3 Transaction Response Parameters section
1271da6c28aaSamw *
1272da6c28aaSamw * The transaction response parameters section consists of:
1273da6c28aaSamw * . A 16 bit word indicating the return status. The possible values are:
1274da6c28aaSamw *
1275da6c28aaSamw * Code Value Description
1276da6c28aaSamw * NERR_Success 0 No errors encountered
1277da6c28aaSamw * ERROR_MORE_DATA 234 Additional data is available
1278da6c28aaSamw * NERR_ServerNotStarted 2114 The RAP service on the remote computer
1279da6c28aaSamw * is not running
1280da6c28aaSamw * NERR_BadTransactConfig 2141 The server is not configured for
1281da6c28aaSamw * transactions, IPC$ is not shared
1282da6c28aaSamw *
1283da6c28aaSamw * . A 16 bit "converter" word.
1284da6c28aaSamw * . A 16 bit number representing the number of entries returned.
1285da6c28aaSamw * . A 16 bit number representing the total number of available entries.
1286da6c28aaSamw * If the supplied buffer is large enough, this will equal the number of
1287da6c28aaSamw * entries returned.
1288da6c28aaSamw *
1289da6c28aaSamw * 6.4.4 Transaction Response Data section
1290da6c28aaSamw *
1291da6c28aaSamw * The return data section consists of a number of SERVER_INFO_1 structures.
1292da6c28aaSamw * The number of such structures present is determined by the third entry
1293da6c28aaSamw * (described above) in the return parameters section.
1294da6c28aaSamw *
1295da6c28aaSamw * At level detail 0, the Transaction response data section contains a
1296da6c28aaSamw * number of SERVER_INFO_0 data structure. The number of such structures is
1297da6c28aaSamw * equal to the 16 bit number returned by the server in the third parameter
1298da6c28aaSamw * in the Transaction response parameter section. The SERVER_INFO_0 data
1299da6c28aaSamw * structure is defined as:
1300da6c28aaSamw *
1301da6c28aaSamw * struct SERVER_INFO_0 {
1302da6c28aaSamw * char sv0_name[16];
1303da6c28aaSamw * };
1304da6c28aaSamw *
1305da6c28aaSamw * where:
1306da6c28aaSamw *
1307da6c28aaSamw * sv0_name is a null-terminated string that specifies the name of a
1308da6c28aaSamw * computer or domain .
1309da6c28aaSamw *
1310da6c28aaSamw * At level detail 1, the Transaction response data section contains a
1311da6c28aaSamw * number of SERVER_INFO_1 data structure. The number of such structures is
1312da6c28aaSamw * equal to the 16 bit number returned by the server in the third parameter
1313da6c28aaSamw * in the Transaction response parameter section. The SERVER_INFO_1 data
1314da6c28aaSamw * structure is defined as:
1315da6c28aaSamw *
1316da6c28aaSamw * struct SERVER_INFO_1 {
1317da6c28aaSamw * char sv1_name[16];
1318da6c28aaSamw * char sv1_version_major;
1319da6c28aaSamw * char sv1_version_minor;
1320da6c28aaSamw * uint32_t sv1_type;
1321da6c28aaSamw * char *sv1_comment_or_master_browser;
1322da6c28aaSamw * };
1323da6c28aaSamw *
1324da6c28aaSamw * sv1_name contains a null-terminated string that specifies the name
1325da6c28aaSamw * of a computer, or a domain name if SV_TYPE_DOMAIN_ENUM is set in
1326da6c28aaSamw * sv1_type.
1327da6c28aaSamw *
1328da6c28aaSamw * sv1_version_major whatever was specified in the HostAnnouncement
1329da6c28aaSamw * or DomainAnnouncement frame with which the entry was registered.
1330da6c28aaSamw *
1331da6c28aaSamw * sv1_version_minor whatever was specified in the HostAnnouncement
1332da6c28aaSamw * or DomainAnnouncement frame with which the entry was registered.
1333da6c28aaSamw *
1334da6c28aaSamw * sv1_type specifies the type of software the computer is running.
1335da6c28aaSamw * The member can be one or a combination of the values defined above
1336da6c28aaSamw * in the Transaction request parameters section for fServerType.
1337da6c28aaSamw *
1338da6c28aaSamw *
1339da6c28aaSamw * sv1_comment_or_master_browser points to a null-terminated string. If
1340da6c28aaSamw * the sv1_type indicates that the entry is for a domain, this
1341da6c28aaSamw * specifies the name of server running the domain master browser;
1342da6c28aaSamw * otherwise, it specifies a comment describing the server. The comment
1343da6c28aaSamw * can be a null string or the pointer may be a null pointer.
1344da6c28aaSamw *
1345da6c28aaSamw * In case there are multiple SERVER_INFO_1 data structures to
1346da6c28aaSamw * return, the server may put all these fixed length structures in
1347da6c28aaSamw * the return buffer, leave some space and then put all the variable
1348da6c28aaSamw * length data (the actual value of the sv1_comment strings) at the
1349da6c28aaSamw * end of the buffer.
1350da6c28aaSamw *
1351da6c28aaSamw * There is no auxiliary data to receive.
1352da6c28aaSamw */
1353da6c28aaSamw
1354da6c28aaSamw int
smb_trans_net_server_enum2(struct smb_request * sr,struct smb_xa * xa)1355da6c28aaSamw smb_trans_net_server_enum2(struct smb_request *sr, struct smb_xa *xa)
1356da6c28aaSamw {
1357da6c28aaSamw uint16_t opcode, level, max_bytes;
1358da6c28aaSamw uint32_t server_type;
1359da6c28aaSamw unsigned char *domain;
1360da6c28aaSamw struct mbuf_chain str_mb;
1361da6c28aaSamw char *hostname, *s;
1362da6c28aaSamw smb_kmod_cfg_t *si;
1363da6c28aaSamw
13643db3f65cSamw if (smb_mbc_decodef(&xa->req_param_mb,
13653db3f65cSamw "%wsswwls", sr, &opcode, &s, &s,
1366da6c28aaSamw &level, &max_bytes, &server_type, &domain) != 0)
1367faa1795aSjb150015 return (SDRC_NOT_IMPLEMENTED);
1368da6c28aaSamw
1369faa1795aSjb150015 si = sr->sr_cfg;
1370da6c28aaSamw
1371bbf6f00cSJordan Brown if (smb_strcasecmp(si->skc_nbdomain, (char *)domain, 0) != 0) {
13723db3f65cSamw (void) smb_mbc_encodef(&xa->rep_param_mb, "wwww", 0, 0, 0, 0);
1373faa1795aSjb150015 return (SDRC_SUCCESS);
1374da6c28aaSamw }
1375da6c28aaSamw
1376da6c28aaSamw if ((server_type & MY_SERVER_TYPE) == 0) {
13773db3f65cSamw (void) smb_mbc_encodef(&xa->rep_param_mb, "wwww", 0, 0, 0, 0);
1378faa1795aSjb150015 return (SDRC_SUCCESS);
1379da6c28aaSamw }
1380da6c28aaSamw
1381da6c28aaSamw MBC_INIT(&str_mb, max_bytes);
1382da6c28aaSamw
1383da6c28aaSamw hostname = si->skc_hostname;
1384da6c28aaSamw
13853db3f65cSamw (void) smb_mbc_encodef(&xa->rep_data_mb, "16c", hostname);
1386da6c28aaSamw if (level == 1) {
13873db3f65cSamw (void) smb_mbc_encodef(&xa->rep_data_mb, "bbll",
1388fd9ee8b5Sjoyce mcintosh (uint8_t)sr->sr_cfg->skc_version.sv_major,
1389fd9ee8b5Sjoyce mcintosh (uint8_t)sr->sr_cfg->skc_version.sv_minor,
1390da6c28aaSamw MY_SERVER_TYPE, MBC_LENGTH(&str_mb));
13913db3f65cSamw (void) smb_mbc_encodef(&str_mb, "s", si->skc_system_comment);
1392da6c28aaSamw }
1393da6c28aaSamw
13943db3f65cSamw (void) smb_mbc_encodef(&xa->rep_param_mb, "wwww", 0,
1395da6c28aaSamw -MBC_LENGTH(&xa->rep_data_mb), 1, 1);
13963db3f65cSamw (void) smb_mbc_encodef(&xa->rep_data_mb, "m", str_mb.chain);
1397faa1795aSjb150015 return (SDRC_SUCCESS);
1398da6c28aaSamw }
1399da6c28aaSamw
1400bbf6f00cSJordan Brown static boolean_t
is_supported_mailslot(const char * mailslot)1401bbf6f00cSJordan Brown is_supported_mailslot(const char *mailslot)
1402da6c28aaSamw {
1403bbf6f00cSJordan Brown static char *mailslots[] = {
1404bbf6f00cSJordan Brown PIPE_LANMAN,
1405bbf6f00cSJordan Brown MAILSLOT_LANMAN,
1406bbf6f00cSJordan Brown MAILSLOT_BROWSE,
1407bbf6f00cSJordan Brown MAILSLOT_MSBROWSE
1408bbf6f00cSJordan Brown };
1409da6c28aaSamw
1410bbf6f00cSJordan Brown int i;
1411bbf6f00cSJordan Brown
1412bbf6f00cSJordan Brown for (i = 0; i < sizeof (mailslots)/sizeof (mailslots[0]); ++i)
1413bbf6f00cSJordan Brown if (smb_strcasecmp(mailslot, mailslots[i], 0) == 0)
1414bbf6f00cSJordan Brown return (B_TRUE);
1415bbf6f00cSJordan Brown
1416bbf6f00cSJordan Brown return (B_FALSE);
1417bbf6f00cSJordan Brown }
1418bbf6f00cSJordan Brown
1419bbf6f00cSJordan Brown /*
142068b2bbf2SGordon Ross * smb_trans_nmpipe
142168b2bbf2SGordon Ross *
142268b2bbf2SGordon Ross * This is used for RPC bind and request transactions.
142368b2bbf2SGordon Ross *
142468b2bbf2SGordon Ross * If the data available from the pipe is larger than the maximum
142568b2bbf2SGordon Ross * data size requested by the client, return as much as requested.
142668b2bbf2SGordon Ross * The residual data remains in the pipe until the client comes back
142768b2bbf2SGordon Ross * with a read request or closes the pipe.
142868b2bbf2SGordon Ross *
142968b2bbf2SGordon Ross * When we read less than what's available, we MUST return the
143068b2bbf2SGordon Ross * status NT_STATUS_BUFFER_OVERFLOW (or ERRDOS/ERROR_MORE_DATA)
1431bbf6f00cSJordan Brown */
143268b2bbf2SGordon Ross static smb_sdrc_t
smb_trans_nmpipe(smb_request_t * sr,smb_xa_t * xa)143368b2bbf2SGordon Ross smb_trans_nmpipe(smb_request_t *sr, smb_xa_t *xa)
1434bbf6f00cSJordan Brown {
1435a90cf9f2SGordon Ross smb_fsctl_t fsctl;
1436a90cf9f2SGordon Ross uint32_t status;
1437bbf6f00cSJordan Brown
143868b2bbf2SGordon Ross smbsr_lookup_file(sr);
143968b2bbf2SGordon Ross if (sr->fid_ofile == NULL) {
144068b2bbf2SGordon Ross smbsr_error(sr, NT_STATUS_INVALID_HANDLE,
144168b2bbf2SGordon Ross ERRDOS, ERRbadfid);
144268b2bbf2SGordon Ross return (SDRC_ERROR);
144368b2bbf2SGordon Ross }
144468b2bbf2SGordon Ross
1445bce01b59SGordon Ross /*
1446a90cf9f2SGordon Ross * A little confusing perhaps, but the fsctl "input" is what we
1447a90cf9f2SGordon Ross * write to the pipe (from the transaction "send" data), and the
1448a90cf9f2SGordon Ross * fsctl "output" is what we read from the pipe (and becomes the
1449a90cf9f2SGordon Ross * transaction receive data).
1450bce01b59SGordon Ross */
1451a90cf9f2SGordon Ross fsctl.CtlCode = FSCTL_PIPE_TRANSCEIVE;
1452a90cf9f2SGordon Ross fsctl.InputCount = xa->smb_tdscnt; /* write count */
1453a90cf9f2SGordon Ross fsctl.OutputCount = 0; /* minimum to read from the pipe */
1454a90cf9f2SGordon Ross fsctl.MaxOutputResp = xa->smb_mdrcnt; /* max to read */
1455a90cf9f2SGordon Ross fsctl.in_mbc = &xa->req_data_mb; /* write from here */
1456a90cf9f2SGordon Ross fsctl.out_mbc = &xa->rep_data_mb; /* read into here */
1457a90cf9f2SGordon Ross
145855f0a249SGordon Ross status = smb_opipe_transceive(sr, &fsctl);
1459a90cf9f2SGordon Ross if (status) {
1460a90cf9f2SGordon Ross smbsr_status(sr, status, 0, 0);
1461a90cf9f2SGordon Ross if (NT_SC_SEVERITY(status) == NT_STATUS_SEVERITY_ERROR)
1462a90cf9f2SGordon Ross return (SDRC_ERROR);
1463a90cf9f2SGordon Ross /* Warnings like NT_STATUS_BUFFER_OVERFLOW are OK */
1464bce01b59SGordon Ross }
1465bce01b59SGordon Ross
146668b2bbf2SGordon Ross return (SDRC_SUCCESS);
1467da6c28aaSamw }
1468da6c28aaSamw
14697b59d02dSjb150015 static smb_sdrc_t
smb_trans_dispatch(smb_request_t * sr,smb_xa_t * xa)14709fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States smb_trans_dispatch(smb_request_t *sr, smb_xa_t *xa)
1471da6c28aaSamw {
1472da6c28aaSamw int rc, pos;
1473da6c28aaSamw int total_bytes, n_setup, n_param, n_data;
1474da6c28aaSamw int param_off, param_pad, data_off, data_pad;
1475da6c28aaSamw uint16_t opcode;
1476da6c28aaSamw uint16_t devstate;
1477da6c28aaSamw char *req_fmt;
1478da6c28aaSamw char *rep_fmt;
1479da6c28aaSamw
1480a90cf9f2SGordon Ross if (xa->smb_suwcnt > 0) {
14813db3f65cSamw rc = smb_mbc_decodef(&xa->req_setup_mb, "ww", &opcode,
1482da6c28aaSamw &sr->smb_fid);
1483da6c28aaSamw if (rc != 0)
1484da6c28aaSamw goto trans_err_not_supported;
1485da6c28aaSamw switch (opcode) {
1486da6c28aaSamw case TRANS_SET_NMPIPE_STATE:
14873db3f65cSamw if ((rc = smb_mbc_decodef(&xa->req_param_mb, "w",
1488da6c28aaSamw &devstate)) != 0)
1489da6c28aaSamw goto trans_err_not_supported;
1490da6c28aaSamw
1491faa1795aSjb150015 rc = SDRC_SUCCESS;
1492da6c28aaSamw break;
1493da6c28aaSamw
1494da6c28aaSamw case TRANS_TRANSACT_NMPIPE:
149568b2bbf2SGordon Ross rc = smb_trans_nmpipe(sr, xa);
1496da6c28aaSamw break;
1497da6c28aaSamw
1498da6c28aaSamw case TRANS_WAIT_NMPIPE:
149968b2bbf2SGordon Ross delay(SEC_TO_TICK(1));
1500faa1795aSjb150015 rc = SDRC_SUCCESS;
1501da6c28aaSamw break;
1502da6c28aaSamw
1503da6c28aaSamw default:
1504da6c28aaSamw goto trans_err_not_supported;
1505da6c28aaSamw }
1506da6c28aaSamw } else {
1507bbf6f00cSJordan Brown if (!is_supported_mailslot(xa->xa_pipe_name))
1508da6c28aaSamw goto trans_err_not_supported;
1509da6c28aaSamw
15103db3f65cSamw if ((rc = smb_mbc_decodef(&xa->req_param_mb, "%wss", sr,
1511da6c28aaSamw &opcode, &req_fmt, &rep_fmt)) != 0)
1512da6c28aaSamw goto trans_err_not_supported;
1513da6c28aaSamw
1514da6c28aaSamw switch (opcode) {
1515da6c28aaSamw case API_WshareEnum:
1516da6c28aaSamw rc = smb_trans_net_share_enum(sr, xa);
1517da6c28aaSamw break;
1518da6c28aaSamw
1519da6c28aaSamw case API_WshareGetInfo:
15203ad684d6Sjb150015 rc = smb_trans_net_share_getinfo(sr, xa);
1521da6c28aaSamw break;
1522da6c28aaSamw
1523da6c28aaSamw case API_WserverGetInfo:
15243ad684d6Sjb150015 rc = smb_trans_net_server_getinfo(sr, xa);
1525da6c28aaSamw break;
1526da6c28aaSamw
1527da6c28aaSamw case API_WUserGetInfo:
15283ad684d6Sjb150015 rc = smb_trans_net_user_getinfo(sr, xa);
1529da6c28aaSamw break;
1530da6c28aaSamw
1531da6c28aaSamw case API_WWkstaGetInfo:
15323ad684d6Sjb150015 rc = smb_trans_net_workstation_getinfo(sr, xa);
1533da6c28aaSamw break;
1534da6c28aaSamw
1535da6c28aaSamw case API_NetServerEnum2:
1536da6c28aaSamw rc = smb_trans_net_server_enum2(sr, xa);
1537da6c28aaSamw break;
1538da6c28aaSamw
1539da6c28aaSamw default:
1540da6c28aaSamw goto trans_err_not_supported;
1541da6c28aaSamw }
1542da6c28aaSamw }
1543da6c28aaSamw
1544da6c28aaSamw switch (rc) {
1545faa1795aSjb150015 case SDRC_SUCCESS:
1546da6c28aaSamw break;
1547da6c28aaSamw
1548da6c28aaSamw case SDRC_DROP_VC:
1549da6c28aaSamw case SDRC_NO_REPLY:
1550faa1795aSjb150015 case SDRC_ERROR:
1551da6c28aaSamw return (rc);
1552da6c28aaSamw
1553faa1795aSjb150015 case SDRC_NOT_IMPLEMENTED:
1554da6c28aaSamw goto trans_err_not_supported;
1555da6c28aaSamw
1556da6c28aaSamw default:
1557da6c28aaSamw break;
1558da6c28aaSamw }
1559da6c28aaSamw
1560da6c28aaSamw n_setup = MBC_LENGTH(&xa->rep_setup_mb);
1561da6c28aaSamw n_param = MBC_LENGTH(&xa->rep_param_mb);
1562da6c28aaSamw n_data = MBC_LENGTH(&xa->rep_data_mb);
1563da6c28aaSamw
1564da6c28aaSamw if (xa->smb_msrcnt < n_setup ||
1565da6c28aaSamw xa->smb_mprcnt < n_param ||
1566da6c28aaSamw xa->smb_mdrcnt < n_data) {
1567da6c28aaSamw goto trans_err_too_small;
1568da6c28aaSamw }
1569da6c28aaSamw
1570da6c28aaSamw /* neato, blast it over there */
1571da6c28aaSamw
1572da6c28aaSamw n_setup = (n_setup + 1) / 2; /* Convert to setup words */
1573da6c28aaSamw param_pad = 1; /* always one */
1574da6c28aaSamw param_off = param_pad + 32 + 21 + (n_setup << 1) + 2;
1575da6c28aaSamw data_pad = (param_off + n_param) & 1; /* Pad to short */
1576da6c28aaSamw /* Param off from hdr start */
1577da6c28aaSamw data_off = param_off + n_param + data_pad;
1578da6c28aaSamw total_bytes = param_pad + n_param + data_pad + n_data;
1579da6c28aaSamw
15807b59d02dSjb150015 rc = smbsr_encode_result(sr, 10+n_setup, total_bytes,
1581da6c28aaSamw "bww2.wwwwwwb.Cw#.C#.C",
1582da6c28aaSamw 10 + n_setup, /* wct */
1583da6c28aaSamw n_param, /* Total Parameter Bytes */
1584da6c28aaSamw n_data, /* Total Data Bytes */
1585da6c28aaSamw n_param, /* Total Parameter Bytes this buffer */
1586da6c28aaSamw param_off, /* Param offset from header start */
1587da6c28aaSamw 0, /* Param displacement */
1588da6c28aaSamw n_data, /* Total Data Bytes this buffer */
1589da6c28aaSamw data_off, /* Data offset from header start */
1590da6c28aaSamw 0, /* Data displacement */
1591da6c28aaSamw n_setup, /* suwcnt */
1592da6c28aaSamw &xa->rep_setup_mb, /* setup[] */
1593da6c28aaSamw total_bytes, /* Total data bytes */
1594da6c28aaSamw param_pad,
1595da6c28aaSamw &xa->rep_param_mb,
1596da6c28aaSamw data_pad,
1597da6c28aaSamw &xa->rep_data_mb);
1598faa1795aSjb150015 return ((rc == 0) ? SDRC_SUCCESS : SDRC_ERROR);
1599da6c28aaSamw
1600da6c28aaSamw trans_err_too_small:
1601da6c28aaSamw rc = NERR_BufTooSmall;
1602da6c28aaSamw goto trans_err;
1603da6c28aaSamw
1604da6c28aaSamw trans_err_not_supported:
1605da6c28aaSamw rc = ERROR_NOT_SUPPORTED;
1606da6c28aaSamw goto trans_err;
1607da6c28aaSamw
1608da6c28aaSamw trans_err:
1609da6c28aaSamw pos = MBC_LENGTH(&sr->reply) + 23;
16107b59d02dSjb150015 rc = smbsr_encode_result(sr, 10, 4, "bww2.wwwwwwb.www",
1611da6c28aaSamw 10, /* wct */
1612da6c28aaSamw 4, 0, /* tpscnt tdscnt */
1613da6c28aaSamw 4, pos, 0, /* pscnt psoff psdisp */
1614da6c28aaSamw 0, 0, 0, /* dscnt dsoff dsdisp */
1615da6c28aaSamw 0, /* suwcnt */
1616da6c28aaSamw 4, /* bcc */
1617da6c28aaSamw rc,
1618da6c28aaSamw 0); /* converter word? */
1619faa1795aSjb150015 return ((rc == 0) ? SDRC_SUCCESS : SDRC_ERROR);
1620da6c28aaSamw }
1621da6c28aaSamw
16227b59d02dSjb150015 static smb_sdrc_t
smb_trans2_dispatch(smb_request_t * sr,smb_xa_t * xa)16239fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States smb_trans2_dispatch(smb_request_t *sr, smb_xa_t *xa)
1624da6c28aaSamw {
1625da6c28aaSamw int rc, pos;
1626da6c28aaSamw int total_bytes, n_setup, n_param, n_data;
1627b819cea2SGordon Ross int param_off, param_pad, data_off;
1628b819cea2SGordon Ross uint16_t data_pad;
1629da6c28aaSamw uint16_t opcode;
1630da6c28aaSamw uint16_t nt_unknown_secret = 0x0100;
1631da6c28aaSamw char *fmt;
1632da6c28aaSamw
16337f3ef643SGordon Ross n_data = xa->smb_mdrcnt;
1634da6c28aaSamw
16353db3f65cSamw if (smb_mbc_decodef(&xa->req_setup_mb, "w", &opcode) != 0)
1636da6c28aaSamw goto trans_err_not_supported;
1637da6c28aaSamw
1638da6c28aaSamw /*
1639da6c28aaSamw * Save this for /proc to read later.
1640da6c28aaSamw */
1641da6c28aaSamw xa->smb_func = opcode;
1642da6c28aaSamw
1643da6c28aaSamw /* for now, only respond to the */
1644da6c28aaSamw switch (opcode) {
16452c2961f8Sjose borrego case TRANS2_OPEN2:
16462c2961f8Sjose borrego rc = smb_com_trans2_open2(sr, xa);
16472c2961f8Sjose borrego break;
16482c2961f8Sjose borrego
1649da6c28aaSamw case TRANS2_CREATE_DIRECTORY:
1650da6c28aaSamw rc = smb_com_trans2_create_directory(sr, xa);
1651da6c28aaSamw break;
1652da6c28aaSamw
1653da6c28aaSamw case TRANS2_FIND_FIRST2:
1654da6c28aaSamw /*
1655da6c28aaSamw * Should have enough room to send the response
1656da6c28aaSamw * data back to client.
1657da6c28aaSamw */
1658da6c28aaSamw if (n_data == 0) {
1659dc20a302Sas200622 smbsr_error(sr, NT_STATUS_INFO_LENGTH_MISMATCH,
1660da6c28aaSamw ERRDOS, ERROR_BAD_LENGTH);
1661faa1795aSjb150015 return (SDRC_ERROR);
1662da6c28aaSamw }
1663da6c28aaSamw rc = smb_com_trans2_find_first2(sr, xa);
1664da6c28aaSamw break;
1665da6c28aaSamw
1666da6c28aaSamw case TRANS2_FIND_NEXT2:
1667da6c28aaSamw /*
1668da6c28aaSamw * Should have enough room to send the response
1669da6c28aaSamw * data back to client.
1670da6c28aaSamw */
1671da6c28aaSamw if (n_data == 0) {
1672dc20a302Sas200622 smbsr_error(sr, NT_STATUS_INFO_LENGTH_MISMATCH,
1673da6c28aaSamw ERRDOS, ERROR_BAD_LENGTH);
1674faa1795aSjb150015 return (SDRC_ERROR);
1675da6c28aaSamw }
1676da6c28aaSamw rc = smb_com_trans2_find_next2(sr, xa);
1677da6c28aaSamw break;
1678da6c28aaSamw
1679da6c28aaSamw case TRANS2_QUERY_FS_INFORMATION:
1680da6c28aaSamw /*
1681da6c28aaSamw * Should have enough room to send the response
1682da6c28aaSamw * data back to client.
1683da6c28aaSamw */
1684da6c28aaSamw if (n_data == 0) {
1685dc20a302Sas200622 smbsr_error(sr, NT_STATUS_INFO_LENGTH_MISMATCH,
1686da6c28aaSamw ERRDOS, ERROR_BAD_LENGTH);
1687faa1795aSjb150015 return (SDRC_ERROR);
1688da6c28aaSamw }
1689da6c28aaSamw rc = smb_com_trans2_query_fs_information(sr, xa);
1690da6c28aaSamw break;
1691da6c28aaSamw
16929fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States case TRANS2_SET_FS_INFORMATION:
16939fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States rc = smb_com_trans2_set_fs_information(sr, xa);
16949fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States break;
16959fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States
1696da6c28aaSamw case TRANS2_QUERY_PATH_INFORMATION:
1697da6c28aaSamw /*
1698da6c28aaSamw * Should have enough room to send the response
1699da6c28aaSamw * data back to client.
1700da6c28aaSamw */
1701da6c28aaSamw if (n_data == 0) {
1702dc20a302Sas200622 smbsr_error(sr, NT_STATUS_INFO_LENGTH_MISMATCH,
1703da6c28aaSamw ERRDOS, ERROR_BAD_LENGTH);
1704faa1795aSjb150015 return (SDRC_ERROR);
1705da6c28aaSamw }
1706da6c28aaSamw rc = smb_com_trans2_query_path_information(sr, xa);
1707da6c28aaSamw break;
1708da6c28aaSamw
1709da6c28aaSamw case TRANS2_QUERY_FILE_INFORMATION:
1710da6c28aaSamw /*
1711da6c28aaSamw * Should have enough room to send the response
1712da6c28aaSamw * data back to client.
1713da6c28aaSamw */
1714da6c28aaSamw if (n_data == 0) {
1715dc20a302Sas200622 smbsr_error(sr, NT_STATUS_INFO_LENGTH_MISMATCH,
1716da6c28aaSamw ERRDOS, ERROR_BAD_LENGTH);
1717faa1795aSjb150015 return (SDRC_ERROR);
1718da6c28aaSamw }
1719da6c28aaSamw rc = smb_com_trans2_query_file_information(sr, xa);
1720da6c28aaSamw break;
1721da6c28aaSamw
1722da6c28aaSamw case TRANS2_SET_PATH_INFORMATION:
1723da6c28aaSamw rc = smb_com_trans2_set_path_information(sr, xa);
1724da6c28aaSamw break;
1725da6c28aaSamw
1726da6c28aaSamw case TRANS2_SET_FILE_INFORMATION:
1727da6c28aaSamw rc = smb_com_trans2_set_file_information(sr, xa);
1728da6c28aaSamw break;
17299fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States
17309fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States case TRANS2_GET_DFS_REFERRAL:
17319fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States rc = smb_com_trans2_get_dfs_referral(sr, xa);
17329fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States break;
17339fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States
1734da6c28aaSamw default:
17352c2961f8Sjose borrego (void) smb_mbc_encodef(&xa->rep_param_mb, "w", 0);
1736da6c28aaSamw goto trans_err_not_supported;
1737da6c28aaSamw }
1738da6c28aaSamw
1739da6c28aaSamw switch (rc) {
1740faa1795aSjb150015 case SDRC_SUCCESS:
1741da6c28aaSamw break;
1742da6c28aaSamw
1743da6c28aaSamw case SDRC_DROP_VC:
1744da6c28aaSamw case SDRC_NO_REPLY:
1745faa1795aSjb150015 case SDRC_ERROR:
1746da6c28aaSamw return (rc);
1747da6c28aaSamw
1748faa1795aSjb150015 case SDRC_NOT_IMPLEMENTED:
1749da6c28aaSamw goto trans_err_not_supported;
1750da6c28aaSamw
1751da6c28aaSamw default:
1752da6c28aaSamw break;
1753da6c28aaSamw }
1754da6c28aaSamw
1755da6c28aaSamw n_setup = MBC_LENGTH(&xa->rep_setup_mb);
1756da6c28aaSamw n_param = MBC_LENGTH(&xa->rep_param_mb);
1757da6c28aaSamw n_data = MBC_LENGTH(&xa->rep_data_mb);
1758da6c28aaSamw
1759da6c28aaSamw if (xa->smb_msrcnt < n_setup ||
1760da6c28aaSamw xa->smb_mprcnt < n_param ||
1761da6c28aaSamw xa->smb_mdrcnt < n_data) {
1762da6c28aaSamw goto trans_err_too_small;
1763da6c28aaSamw }
1764da6c28aaSamw
1765da6c28aaSamw /* neato, blast it over there */
1766da6c28aaSamw
1767da6c28aaSamw n_setup = (n_setup + 1) / 2; /* Conver to setup words */
1768da6c28aaSamw param_pad = 1; /* must be one */
1769da6c28aaSamw param_off = param_pad + 32 + 21 + (n_setup << 1) + 2;
1770da6c28aaSamw
1771da6c28aaSamw /*
1772da6c28aaSamw * Including the nt_unknown_secret value persuades netmon to
1773da6c28aaSamw * display the correct data format for QueryPathInfo and
1774da6c28aaSamw * QueryFileInfo.
1775da6c28aaSamw */
1776da6c28aaSamw if (opcode == TRANS2_QUERY_FILE_INFORMATION ||
1777da6c28aaSamw opcode == TRANS2_QUERY_PATH_INFORMATION) {
1778da6c28aaSamw data_pad = sizeof (uint16_t);
1779da6c28aaSamw data_off = param_off + n_param + data_pad;
1780da6c28aaSamw fmt = "bww2.wwwwwwb.Cw#.CwC";
1781da6c28aaSamw nt_unknown_secret = 0x0100;
1782da6c28aaSamw }
1783da6c28aaSamw else
1784da6c28aaSamw {
1785da6c28aaSamw data_pad = (param_off + n_param) & 1; /* Pad to short */
1786da6c28aaSamw /* Param off from hdr start */
1787da6c28aaSamw data_off = param_off + n_param + data_pad;
1788da6c28aaSamw fmt = "bww2.wwwwwwb.Cw#.C#.C";
1789da6c28aaSamw nt_unknown_secret = data_pad;
1790da6c28aaSamw }
1791da6c28aaSamw
1792da6c28aaSamw total_bytes = param_pad + n_param + data_pad + n_data;
1793da6c28aaSamw
17947b59d02dSjb150015 rc = smbsr_encode_result(sr, 10+n_setup, total_bytes,
1795da6c28aaSamw fmt,
1796da6c28aaSamw 10 + n_setup, /* wct */
1797da6c28aaSamw n_param, /* Total Parameter Bytes */
1798da6c28aaSamw n_data /* + data_pad */, /* Total Data Bytes */
1799da6c28aaSamw n_param, /* Total Parameter Bytes this buffer */
1800da6c28aaSamw param_off, /* Param offset from header start */
1801da6c28aaSamw 0, /* Param displacement */
1802da6c28aaSamw n_data /* + data_pad */, /* Total Data Bytes this buffer */
1803da6c28aaSamw data_off, /* Data offset from header start */
1804da6c28aaSamw 0, /* Data displacement */
1805da6c28aaSamw n_setup, /* suwcnt */
1806da6c28aaSamw &xa->rep_setup_mb, /* setup[] */
1807da6c28aaSamw total_bytes, /* Total data bytes */
1808da6c28aaSamw param_pad,
1809da6c28aaSamw &xa->rep_param_mb,
1810da6c28aaSamw nt_unknown_secret,
1811da6c28aaSamw &xa->rep_data_mb);
1812faa1795aSjb150015 return ((rc == 0) ? SDRC_SUCCESS : SDRC_ERROR);
1813da6c28aaSamw
1814da6c28aaSamw trans_err_too_small:
1815da6c28aaSamw rc = NERR_BufTooSmall;
1816da6c28aaSamw goto trans_err;
1817da6c28aaSamw
1818da6c28aaSamw trans_err_not_supported:
1819da6c28aaSamw rc = ERROR_NOT_SUPPORTED;
1820da6c28aaSamw goto trans_err;
1821da6c28aaSamw
1822da6c28aaSamw trans_err:
1823da6c28aaSamw pos = MBC_LENGTH(&sr->reply) + 23;
18247b59d02dSjb150015 rc = smbsr_encode_result(sr, 10, 4, "bww2.wwwwwwb.www",
1825da6c28aaSamw 10, /* wct */
1826da6c28aaSamw 4, 0, /* tpscnt tdscnt */
1827da6c28aaSamw 4, pos, 0, /* pscnt psoff psdisp */
1828da6c28aaSamw 0, 0, 0, /* dscnt dsoff dsdisp */
1829da6c28aaSamw 0, /* suwcnt */
1830da6c28aaSamw 4, /* bcc */
1831da6c28aaSamw rc,
1832da6c28aaSamw 0); /* converter word? */
1833faa1795aSjb150015 return ((rc == 0) ? SDRC_SUCCESS : SDRC_ERROR);
1834da6c28aaSamw }
1835da6c28aaSamw
18367f3ef643SGordon Ross static uint32_t smb_xa_max_setup_count = 200;
18377f3ef643SGordon Ross static uint32_t smb_xa_max_param_count = 32 * 1024;
18387f3ef643SGordon Ross static uint32_t smb_xa_max_data_count = 64 * 1024;
18397f3ef643SGordon Ross
1840da6c28aaSamw smb_xa_t *
smb_xa_create(smb_session_t * session,smb_request_t * sr,uint32_t total_parameter_count,uint32_t total_data_count,uint32_t max_parameter_count,uint32_t max_data_count,uint32_t max_setup_count,uint32_t setup_word_count)1841da6c28aaSamw smb_xa_create(
1842da6c28aaSamw smb_session_t *session,
1843da6c28aaSamw smb_request_t *sr,
1844da6c28aaSamw uint32_t total_parameter_count,
1845da6c28aaSamw uint32_t total_data_count,
1846da6c28aaSamw uint32_t max_parameter_count,
1847da6c28aaSamw uint32_t max_data_count,
1848da6c28aaSamw uint32_t max_setup_count,
1849da6c28aaSamw uint32_t setup_word_count)
1850da6c28aaSamw {
1851da6c28aaSamw smb_xa_t *xa, *nxa;
1852da6c28aaSamw smb_llist_t *xlist;
1853da6c28aaSamw
18547f3ef643SGordon Ross /*
18557f3ef643SGordon Ross * Sanity check what the client says it will send.
18567f3ef643SGordon Ross * Caller handles NULL return as ERRnoroom.
18577f3ef643SGordon Ross */
18587f3ef643SGordon Ross if (setup_word_count > smb_xa_max_setup_count)
18597f3ef643SGordon Ross return (NULL);
18607f3ef643SGordon Ross if (total_parameter_count > smb_xa_max_param_count)
18617f3ef643SGordon Ross return (NULL);
18627f3ef643SGordon Ross if (total_data_count > smb_xa_max_data_count)
18637f3ef643SGordon Ross return (NULL);
18647f3ef643SGordon Ross
18657f3ef643SGordon Ross /*
18667f3ef643SGordon Ross * Limit what the client asks us to allocate for
18677f3ef643SGordon Ross * returned setup, params, data.
18687f3ef643SGordon Ross */
18697f3ef643SGordon Ross if (max_setup_count > smb_xa_max_setup_count)
18707f3ef643SGordon Ross max_setup_count = smb_xa_max_setup_count;
18717f3ef643SGordon Ross if (max_parameter_count > smb_xa_max_param_count)
18727f3ef643SGordon Ross max_parameter_count = smb_xa_max_param_count;
18737f3ef643SGordon Ross if (max_data_count > smb_xa_max_data_count)
18747f3ef643SGordon Ross max_data_count = smb_xa_max_data_count;
18757f3ef643SGordon Ross
1876bbf6f00cSJordan Brown xa = kmem_zalloc(sizeof (smb_xa_t), KM_SLEEP);
1877da6c28aaSamw xa->xa_refcnt = 1;
1878da6c28aaSamw xa->smb_com = sr->smb_com;
1879da6c28aaSamw xa->smb_flg = sr->smb_flg;
1880da6c28aaSamw xa->smb_flg2 = sr->smb_flg2;
1881da6c28aaSamw xa->smb_tid = sr->smb_tid;
1882da6c28aaSamw xa->smb_pid = sr->smb_pid;
1883da6c28aaSamw xa->smb_uid = sr->smb_uid;
1884da6c28aaSamw xa->xa_smb_mid = sr->smb_mid;
18857f3ef643SGordon Ross xa->xa_smb_fid = 0xFFFF;
1886da6c28aaSamw xa->reply_seqnum = sr->reply_seqnum;
1887da6c28aaSamw xa->smb_tpscnt = total_parameter_count;
1888da6c28aaSamw xa->smb_tdscnt = total_data_count;
1889da6c28aaSamw xa->smb_mprcnt = max_parameter_count;
1890da6c28aaSamw xa->smb_mdrcnt = max_data_count;
1891da6c28aaSamw xa->smb_msrcnt = max_setup_count;
1892da6c28aaSamw xa->smb_suwcnt = setup_word_count;
1893da6c28aaSamw xa->xa_session = session;
1894da6c28aaSamw xa->xa_magic = SMB_XA_MAGIC;
1895da6c28aaSamw
18967f3ef643SGordon Ross /* request parts */
18977f3ef643SGordon Ross xa->req_setup_mb.max_bytes = setup_word_count * 2;
18987f3ef643SGordon Ross xa->req_param_mb.max_bytes = total_parameter_count;
18997f3ef643SGordon Ross xa->req_data_mb.max_bytes = total_data_count;
19007f3ef643SGordon Ross
19017f3ef643SGordon Ross /* reply parts */
19027f3ef643SGordon Ross xa->rep_setup_mb.max_bytes = max_setup_count * 2;
19037f3ef643SGordon Ross xa->rep_param_mb.max_bytes = max_parameter_count;
19047f3ef643SGordon Ross xa->rep_data_mb.max_bytes = max_data_count;
19057f3ef643SGordon Ross
1906da6c28aaSamw /*
1907da6c28aaSamw * The new xa structure is checked against the current list to see
1908da6c28aaSamw * if it exists already.
1909da6c28aaSamw */
1910da6c28aaSamw xlist = &session->s_xa_list;
1911da6c28aaSamw smb_llist_enter(xlist, RW_WRITER);
1912da6c28aaSamw nxa = smb_llist_head(xlist);
1913da6c28aaSamw while (nxa) {
1914da6c28aaSamw ASSERT(nxa->xa_magic == SMB_XA_MAGIC);
1915da6c28aaSamw if (nxa->xa_smb_mid == xa->xa_smb_mid &&
1916da6c28aaSamw nxa->smb_pid == xa->smb_pid &&
1917da6c28aaSamw !SMB_XA_CLOSED(nxa) &&
1918da6c28aaSamw !(nxa->xa_flags & SMB_XA_FLAG_COMPLETE)) {
1919da6c28aaSamw smb_llist_exit(xlist);
1920bbf6f00cSJordan Brown kmem_free(xa, sizeof (smb_xa_t));
1921da6c28aaSamw return (NULL);
1922da6c28aaSamw }
1923da6c28aaSamw nxa = smb_llist_next(xlist, nxa);
1924da6c28aaSamw }
1925da6c28aaSamw smb_llist_insert_tail(xlist, xa);
1926da6c28aaSamw smb_llist_exit(xlist);
1927da6c28aaSamw return (xa);
1928da6c28aaSamw }
1929da6c28aaSamw
1930da6c28aaSamw void
smb_xa_delete(smb_xa_t * xa)1931da6c28aaSamw smb_xa_delete(smb_xa_t *xa)
1932da6c28aaSamw {
1933da6c28aaSamw ASSERT(xa->xa_refcnt == 0);
1934da6c28aaSamw ASSERT(SMB_XA_CLOSED(xa));
1935da6c28aaSamw
1936bbf6f00cSJordan Brown if (xa->xa_pipe_name)
19379fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States smb_mem_free(xa->xa_pipe_name);
1938da6c28aaSamw
19397f3ef643SGordon Ross /* request parts */
19407f3ef643SGordon Ross if (xa->req_setup_mb.chain != NULL)
19417f3ef643SGordon Ross m_freem(xa->req_setup_mb.chain);
19427f3ef643SGordon Ross if (xa->req_param_mb.chain != NULL)
19437f3ef643SGordon Ross m_freem(xa->req_param_mb.chain);
19447f3ef643SGordon Ross if (xa->req_data_mb.chain != NULL)
19457f3ef643SGordon Ross m_freem(xa->req_data_mb.chain);
19467f3ef643SGordon Ross
19477f3ef643SGordon Ross /* reply parts */
1948da6c28aaSamw if (xa->rep_setup_mb.chain != NULL)
1949da6c28aaSamw m_freem(xa->rep_setup_mb.chain);
1950da6c28aaSamw if (xa->rep_param_mb.chain != NULL)
1951da6c28aaSamw m_freem(xa->rep_param_mb.chain);
1952da6c28aaSamw if (xa->rep_data_mb.chain != NULL)
1953da6c28aaSamw m_freem(xa->rep_data_mb.chain);
1954da6c28aaSamw
1955da6c28aaSamw xa->xa_magic = (uint32_t)~SMB_XA_MAGIC;
1956bbf6f00cSJordan Brown kmem_free(xa, sizeof (smb_xa_t));
1957da6c28aaSamw }
1958da6c28aaSamw
1959da6c28aaSamw smb_xa_t *
smb_xa_hold(smb_xa_t * xa)1960da6c28aaSamw smb_xa_hold(smb_xa_t *xa)
1961da6c28aaSamw {
1962da6c28aaSamw mutex_enter(&xa->xa_mutex);
1963da6c28aaSamw xa->xa_refcnt++;
1964da6c28aaSamw ASSERT(xa->xa_refcnt);
1965da6c28aaSamw mutex_exit(&xa->xa_mutex);
1966da6c28aaSamw return (xa);
1967da6c28aaSamw }
1968da6c28aaSamw
1969da6c28aaSamw void
smb_xa_rele(smb_session_t * session,smb_xa_t * xa)1970da6c28aaSamw smb_xa_rele(smb_session_t *session, smb_xa_t *xa)
1971da6c28aaSamw {
1972da6c28aaSamw mutex_enter(&xa->xa_mutex);
1973da6c28aaSamw ASSERT(xa->xa_refcnt);
1974da6c28aaSamw xa->xa_refcnt--;
1975da6c28aaSamw if (SMB_XA_CLOSED(xa) && (xa->xa_refcnt == 0)) {
1976da6c28aaSamw mutex_exit(&xa->xa_mutex);
1977da6c28aaSamw smb_llist_enter(&session->s_xa_list, RW_WRITER);
1978da6c28aaSamw smb_llist_remove(&session->s_xa_list, xa);
1979da6c28aaSamw smb_llist_exit(&session->s_xa_list);
1980da6c28aaSamw smb_xa_delete(xa);
1981da6c28aaSamw return;
1982da6c28aaSamw }
1983da6c28aaSamw mutex_exit(&xa->xa_mutex);
1984da6c28aaSamw }
1985da6c28aaSamw
1986da6c28aaSamw int
smb_xa_open(smb_xa_t * xa)1987da6c28aaSamw smb_xa_open(smb_xa_t *xa)
1988da6c28aaSamw {
1989da6c28aaSamw int rc;
1990da6c28aaSamw
1991da6c28aaSamw mutex_enter(&xa->xa_mutex);
1992da6c28aaSamw
1993da6c28aaSamw ASSERT((xa->xa_flags & SMB_XA_FLAG_OPEN) == 0);
1994da6c28aaSamw
1995da6c28aaSamw if ((xa->xa_flags & SMB_XA_FLAG_CLOSE) == 0) {
1996da6c28aaSamw xa->xa_flags |= SMB_XA_FLAG_OPEN;
1997da6c28aaSamw rc = 0;
1998da6c28aaSamw } else {
1999da6c28aaSamw rc = ERROR_INVALID_HANDLE;
2000da6c28aaSamw }
2001da6c28aaSamw
2002da6c28aaSamw mutex_exit(&xa->xa_mutex);
2003da6c28aaSamw
2004da6c28aaSamw return (rc);
2005da6c28aaSamw }
2006da6c28aaSamw
2007da6c28aaSamw void
smb_xa_close(smb_xa_t * xa)2008da6c28aaSamw smb_xa_close(smb_xa_t *xa)
2009da6c28aaSamw {
2010da6c28aaSamw mutex_enter(&xa->xa_mutex);
2011da6c28aaSamw xa->xa_flags |= SMB_XA_FLAG_CLOSE;
2012da6c28aaSamw xa->xa_flags &= ~SMB_XA_FLAG_OPEN;
2013da6c28aaSamw
2014da6c28aaSamw if (xa->xa_refcnt == 0) {
2015da6c28aaSamw mutex_exit(&xa->xa_mutex);
2016da6c28aaSamw smb_llist_enter(&xa->xa_session->s_xa_list, RW_WRITER);
2017da6c28aaSamw smb_llist_remove(&xa->xa_session->s_xa_list, xa);
2018da6c28aaSamw smb_llist_exit(&xa->xa_session->s_xa_list);
2019da6c28aaSamw smb_xa_delete(xa);
2020da6c28aaSamw return;
2021da6c28aaSamw }
2022da6c28aaSamw
2023da6c28aaSamw mutex_exit(&xa->xa_mutex);
2024da6c28aaSamw }
2025da6c28aaSamw
2026da6c28aaSamw int
smb_xa_complete(smb_xa_t * xa)2027da6c28aaSamw smb_xa_complete(smb_xa_t *xa)
2028da6c28aaSamw {
2029da6c28aaSamw int rc;
2030da6c28aaSamw
2031da6c28aaSamw mutex_enter(&xa->xa_mutex);
2032da6c28aaSamw if (xa->xa_flags & (SMB_XA_FLAG_COMPLETE | SMB_XA_FLAG_CLOSE)) {
20337f3ef643SGordon Ross rc = 0; /* error ("not complete") */
2034da6c28aaSamw } else {
20357f3ef643SGordon Ross rc = 1; /* Yes, "complete" */
2036da6c28aaSamw xa->xa_flags |= SMB_XA_FLAG_COMPLETE;
20377f3ef643SGordon Ross
20387f3ef643SGordon Ross /*
20397f3ef643SGordon Ross * During trans & trans-secondary processing,
20407f3ef643SGordon Ross * we copied the request data into these.
20417f3ef643SGordon Ross * Now we want to parse them, so we need to
20427f3ef643SGordon Ross * move the "finger" back to the beginning.
20437f3ef643SGordon Ross */
20447f3ef643SGordon Ross xa->req_setup_mb.chain_offset = 0;
20457f3ef643SGordon Ross xa->req_param_mb.chain_offset = 0;
20467f3ef643SGordon Ross xa->req_data_mb.chain_offset = 0;
2047da6c28aaSamw }
20487f3ef643SGordon Ross
2049da6c28aaSamw mutex_exit(&xa->xa_mutex);
2050da6c28aaSamw return (rc);
2051da6c28aaSamw }
2052da6c28aaSamw
2053da6c28aaSamw smb_xa_t *
smb_xa_find(smb_session_t * session,uint32_t pid,uint16_t mid)2054da6c28aaSamw smb_xa_find(
2055da6c28aaSamw smb_session_t *session,
2056a90cf9f2SGordon Ross uint32_t pid,
2057da6c28aaSamw uint16_t mid)
2058da6c28aaSamw {
2059da6c28aaSamw smb_xa_t *xa;
2060da6c28aaSamw smb_llist_t *xlist;
2061da6c28aaSamw
2062da6c28aaSamw xlist = &session->s_xa_list;
2063da6c28aaSamw smb_llist_enter(xlist, RW_READER);
2064da6c28aaSamw xa = smb_llist_head(xlist);
2065da6c28aaSamw while (xa) {
2066da6c28aaSamw mutex_enter(&xa->xa_mutex);
2067da6c28aaSamw if (xa->xa_smb_mid == mid &&
2068da6c28aaSamw xa->smb_pid == pid &&
2069da6c28aaSamw !SMB_XA_CLOSED(xa) &&
2070da6c28aaSamw !(xa->xa_flags & SMB_XA_FLAG_COMPLETE)) {
2071da6c28aaSamw xa->xa_refcnt++;
2072da6c28aaSamw ASSERT(xa->xa_refcnt);
2073da6c28aaSamw mutex_exit(&xa->xa_mutex);
2074da6c28aaSamw break;
2075da6c28aaSamw }
2076da6c28aaSamw mutex_exit(&xa->xa_mutex);
2077da6c28aaSamw xa = smb_llist_next(xlist, xa);
2078da6c28aaSamw }
2079da6c28aaSamw smb_llist_exit(xlist);
2080da6c28aaSamw return (xa);
2081da6c28aaSamw }
2082