2 Unix SMB/CIFS implementation.
3 client transaction calls
4 Copyright (C) Andrew Tridgell 1994-1998
6 This program is free software; you can redistribute it and/or modify
7 it under the terms of the GNU General Public License as published by
8 the Free Software Foundation; either version 3 of the License, or
9 (at your option) any later version.
11 This program is distributed in the hope that it will be useful,
12 but WITHOUT ANY WARRANTY; without even the implied warranty of
13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 GNU General Public License for more details.
16 You should have received a copy of the GNU General Public License
17 along with this program. If not, see <http://www.gnu.org/licenses/>.
21 #include "libsmb/libsmb.h"
22 #include "../lib/util/tevent_ntstatus.h"
23 #include "async_smb.h"
24 #include "../libcli/smb/smbXcli_base.h"
26 struct cli_trans_state
{
27 struct cli_state
*cli
;
28 struct tevent_req
*req
;
29 struct cli_trans_state
**ptr
;
32 static int cli_trans_state_destructor(struct cli_trans_state
*state
)
34 talloc_set_destructor(state
->ptr
, NULL
);
35 talloc_free(state
->ptr
);
39 static int cli_trans_state_ptr_destructor(struct cli_trans_state
**ptr
)
41 struct cli_trans_state
*state
= *ptr
;
42 void *parent
= talloc_parent(state
);
44 talloc_set_destructor(state
, NULL
);
46 talloc_reparent(state
, parent
, state
->req
);
51 struct tevent_req
*cli_trans_send(
52 TALLOC_CTX
*mem_ctx
, struct tevent_context
*ev
,
53 struct cli_state
*cli
, uint8_t cmd
,
54 const char *pipe_name
, uint16_t fid
, uint16_t function
, int flags
,
55 uint16_t *setup
, uint8_t num_setup
, uint8_t max_setup
,
56 uint8_t *param
, uint32_t num_param
, uint32_t max_param
,
57 uint8_t *data
, uint32_t num_data
, uint32_t max_data
)
59 struct cli_trans_state
*state
;
60 uint8_t additional_flags
= 0;
61 uint8_t clear_flags
= 0;
62 uint16_t additional_flags2
= 0;
63 uint16_t clear_flags2
= 0;
65 state
= talloc_zero(mem_ctx
, struct cli_trans_state
);
70 state
->ptr
= talloc(state
, struct cli_trans_state
*);
71 if (state
->ptr
== NULL
) {
76 if (cli
->case_sensitive
) {
77 clear_flags
|= FLAG_CASELESS_PATHNAMES
;
79 /* Default setting, case insensitive. */
80 additional_flags
|= FLAG_CASELESS_PATHNAMES
;
83 if ((smb1cli_conn_capabilities(cli
->conn
) & CAP_DFS
) && cli
->dfsroot
) {
84 additional_flags2
|= FLAGS2_DFS_PATHNAMES
;
87 state
->req
= smb1cli_trans_send(state
, ev
,
89 additional_flags
, clear_flags
,
90 additional_flags2
, clear_flags2
,
92 cli
->smb1
.pid
, cli
->smb1
.tid
, cli
->smb1
.uid
,
93 pipe_name
, fid
, function
, flags
,
94 setup
, num_setup
, max_setup
,
95 param
, num_param
, max_param
,
96 data
, num_data
, max_data
);
97 if (state
->req
== NULL
) {
102 talloc_reparent(state
, state
->req
, state
->ptr
);
103 talloc_set_destructor(state
, cli_trans_state_destructor
);
104 talloc_set_destructor(state
->ptr
, cli_trans_state_ptr_destructor
);
109 NTSTATUS
cli_trans_recv(struct tevent_req
*req
, TALLOC_CTX
*mem_ctx
,
110 uint16_t *recv_flags2
,
111 uint16_t **setup
, uint8_t min_setup
,
113 uint8_t **param
, uint32_t min_param
,
115 uint8_t **data
, uint32_t min_data
,
119 void *parent
= talloc_parent(req
);
120 struct cli_trans_state
*state
=
121 talloc_get_type(parent
,
122 struct cli_trans_state
);
123 bool map_dos_errors
= true;
125 status
= smb1cli_trans_recv(req
, mem_ctx
, recv_flags2
,
126 setup
, min_setup
, num_setup
,
127 param
, min_param
, num_param
,
128 data
, min_data
, num_data
);
131 map_dos_errors
= state
->cli
->map_dos_errors
;
132 state
->cli
->raw_status
= status
;
133 talloc_free(state
->ptr
);
137 if (NT_STATUS_IS_DOS(status
) && map_dos_errors
) {
138 uint8_t eclass
= NT_STATUS_DOS_CLASS(status
);
139 uint16_t ecode
= NT_STATUS_DOS_CODE(status
);
141 * TODO: is it really a good idea to do a mapping here?
143 * The old cli_pull_error() also does it, so I do not change
146 status
= dos_to_ntstatus(eclass
, ecode
);
152 NTSTATUS
cli_trans(TALLOC_CTX
*mem_ctx
, struct cli_state
*cli
,
154 const char *pipe_name
, uint16_t fid
, uint16_t function
,
156 uint16_t *setup
, uint8_t num_setup
, uint8_t max_setup
,
157 uint8_t *param
, uint32_t num_param
, uint32_t max_param
,
158 uint8_t *data
, uint32_t num_data
, uint32_t max_data
,
159 uint16_t *recv_flags2
,
160 uint16_t **rsetup
, uint8_t min_rsetup
, uint8_t *num_rsetup
,
161 uint8_t **rparam
, uint32_t min_rparam
, uint32_t *num_rparam
,
162 uint8_t **rdata
, uint32_t min_rdata
, uint32_t *num_rdata
)
165 uint8_t additional_flags
= 0;
166 uint8_t clear_flags
= 0;
167 uint16_t additional_flags2
= 0;
168 uint16_t clear_flags2
= 0;
170 if (cli
->case_sensitive
) {
171 clear_flags
|= FLAG_CASELESS_PATHNAMES
;
173 /* Default setting, case insensitive. */
174 additional_flags
|= FLAG_CASELESS_PATHNAMES
;
177 if ((smb1cli_conn_capabilities(cli
->conn
) & CAP_DFS
) && cli
->dfsroot
) {
178 additional_flags2
|= FLAGS2_DFS_PATHNAMES
;
181 status
= smb1cli_trans(mem_ctx
,
182 cli
->conn
, trans_cmd
,
183 additional_flags
, clear_flags
,
184 additional_flags2
, clear_flags2
,
186 cli
->smb1
.pid
, cli
->smb1
.tid
, cli
->smb1
.uid
,
187 pipe_name
, fid
, function
, flags
,
188 setup
, num_setup
, max_setup
,
189 param
, num_param
, max_param
,
190 data
, num_data
, max_data
,
192 rsetup
, min_rsetup
, num_rsetup
,
193 rparam
, min_rparam
, num_rparam
,
194 rdata
, min_rdata
, num_rdata
);
196 cli
->raw_status
= status
;
198 if (NT_STATUS_IS_DOS(status
) && cli
->map_dos_errors
) {
199 uint8_t eclass
= NT_STATUS_DOS_CLASS(status
);
200 uint16_t ecode
= NT_STATUS_DOS_CODE(status
);
202 * TODO: is it really a good idea to do a mapping here?
204 * The old cli_pull_error() also does it, so I do not change
207 status
= dos_to_ntstatus(eclass
, ecode
);