2 Unix SMB/CIFS implementation.
4 Copyright (C) Volker Lendecke 2011
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/>.
22 #include "async_smb.h"
23 #include "../libcli/smb/smbXcli_base.h"
25 #include "libsmb/proto.h"
26 #include "lib/util/tevent_ntstatus.h"
28 struct smb2cli_tcon_state
{
29 struct cli_state
*cli
;
34 static void smb2cli_tcon_done(struct tevent_req
*subreq
);
36 struct tevent_req
*smb2cli_tcon_send(TALLOC_CTX
*mem_ctx
,
37 struct tevent_context
*ev
,
38 struct cli_state
*cli
,
41 struct tevent_req
*req
, *subreq
;
42 struct smb2cli_tcon_state
*state
;
44 char srv_ip
[INET6_ADDRSTRLEN
];
45 const char *tcon_share
;
49 req
= tevent_req_create(mem_ctx
, &state
, struct smb2cli_tcon_state
);
55 print_sockaddr(srv_ip
, sizeof(srv_ip
), smbXcli_conn_remote_sockaddr(cli
->conn
));
57 tcon_share
= talloc_asprintf(state
, "\\\\%s\\%s",
59 if (tevent_req_nomem(tcon_share
, req
)) {
60 return tevent_req_post(req
, ev
);
62 if (!convert_string_talloc(state
, CH_UNIX
, CH_UTF16
,
63 tcon_share
, strlen(tcon_share
),
66 return tevent_req_post(req
, ev
);
69 if (strlen(tcon_share
) == 0) {
76 SSVAL(fixed
, 4, SMB2_HDR_BODY
+ 8);
77 SSVAL(fixed
, 6, dyn_len
);
80 dyn
= state
->dyn_pad
;;
81 dyn_len
= sizeof(state
->dyn_pad
);
84 subreq
= smb2cli_req_send(state
, ev
, cli
->conn
, SMB2_OP_TCON
,
89 state
->fixed
, sizeof(state
->fixed
),
91 if (tevent_req_nomem(subreq
, req
)) {
92 return tevent_req_post(req
, ev
);
94 tevent_req_set_callback(subreq
, smb2cli_tcon_done
, req
);
98 static void smb2cli_tcon_done(struct tevent_req
*subreq
)
100 struct tevent_req
*req
= tevent_req_callback_data(
101 subreq
, struct tevent_req
);
102 struct smb2cli_tcon_state
*state
= tevent_req_data(
103 req
, struct smb2cli_tcon_state
);
104 struct cli_state
*cli
= state
->cli
;
110 uint32_t share_flags
;
111 uint32_t share_capabilities
;
112 uint32_t maximal_access
;
113 static const struct smb2cli_req_expected_response expected
[] = {
115 .status
= NT_STATUS_OK
,
120 status
= smb2cli_req_recv(subreq
, state
, &iov
,
121 expected
, ARRAY_SIZE(expected
));
123 if (!NT_STATUS_IS_OK(status
)) {
124 tevent_req_nterror(req
, status
);
128 tcon_id
= IVAL(iov
[0].iov_base
, SMB2_HDR_TID
);
130 body
= (uint8_t *)iov
[1].iov_base
;
131 share_type
= CVAL(body
, 0x02);
132 share_flags
= IVAL(body
, 0x04);
133 share_capabilities
= IVAL(body
, 0x08);
134 maximal_access
= IVAL(body
, 0x0C);
136 cli
->smb2
.tcon
= smbXcli_tcon_create(cli
);
137 if (tevent_req_nomem(cli
->smb2
.tcon
, req
)) {
141 smb2cli_tcon_set_values(cli
->smb2
.tcon
,
149 tevent_req_done(req
);
152 NTSTATUS
smb2cli_tcon_recv(struct tevent_req
*req
)
154 return tevent_req_simple_recv_ntstatus(req
);
157 NTSTATUS
smb2cli_tcon(struct cli_state
*cli
, const char *share
)
159 TALLOC_CTX
*frame
= talloc_stackframe();
160 struct tevent_context
*ev
;
161 struct tevent_req
*req
;
162 NTSTATUS status
= NT_STATUS_NO_MEMORY
;
164 if (smbXcli_conn_has_async_calls(cli
->conn
)) {
166 * Can't use sync call while an async call is in flight
168 status
= NT_STATUS_INVALID_PARAMETER
;
171 ev
= tevent_context_init(frame
);
175 req
= smb2cli_tcon_send(frame
, ev
, cli
, share
);
179 if (!tevent_req_poll_ntstatus(req
, ev
, &status
)) {
182 status
= smb2cli_tcon_recv(req
);
188 struct smb2cli_tdis_state
{
189 struct cli_state
*cli
;
193 static void smb2cli_tdis_done(struct tevent_req
*subreq
);
195 struct tevent_req
*smb2cli_tdis_send(TALLOC_CTX
*mem_ctx
,
196 struct tevent_context
*ev
,
197 struct cli_state
*cli
)
199 struct tevent_req
*req
, *subreq
;
200 struct smb2cli_tdis_state
*state
;
202 req
= tevent_req_create(mem_ctx
, &state
,
203 struct smb2cli_tdis_state
);
208 SSVAL(state
->fixed
, 0, 4);
210 subreq
= smb2cli_req_send(state
, ev
, cli
->conn
, SMB2_OP_TDIS
,
215 state
->fixed
, sizeof(state
->fixed
),
217 if (tevent_req_nomem(subreq
, req
)) {
218 return tevent_req_post(req
, ev
);
220 tevent_req_set_callback(subreq
, smb2cli_tdis_done
, req
);
224 static void smb2cli_tdis_done(struct tevent_req
*subreq
)
226 struct tevent_req
*req
=
227 tevent_req_callback_data(subreq
,
229 struct smb2cli_tdis_state
*state
=
231 struct smb2cli_tdis_state
);
233 static const struct smb2cli_req_expected_response expected
[] = {
235 .status
= NT_STATUS_OK
,
240 status
= smb2cli_req_recv(subreq
, NULL
, NULL
,
241 expected
, ARRAY_SIZE(expected
));
243 if (tevent_req_nterror(req
, status
)) {
246 TALLOC_FREE(state
->cli
->smb2
.tcon
);
247 tevent_req_done(req
);
250 NTSTATUS
smb2cli_tdis_recv(struct tevent_req
*req
)
252 return tevent_req_simple_recv_ntstatus(req
);
255 NTSTATUS
smb2cli_tdis(struct cli_state
*cli
)
257 TALLOC_CTX
*frame
= talloc_stackframe();
258 struct tevent_context
*ev
;
259 struct tevent_req
*req
;
260 NTSTATUS status
= NT_STATUS_NO_MEMORY
;
262 if (smbXcli_conn_has_async_calls(cli
->conn
)) {
264 * Can't use sync call while an async call is in flight
266 status
= NT_STATUS_INVALID_PARAMETER
;
269 ev
= tevent_context_init(frame
);
273 req
= smb2cli_tdis_send(frame
, ev
, cli
);
277 if (!tevent_req_poll_ntstatus(req
, ev
, &status
)) {
280 status
= smb2cli_tdis_recv(req
);