2 Unix SMB/CIFS implementation.
3 Connect to 445 and 139/nbsesssetup
4 Copyright (C) Volker Lendecke 2010
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 "../lib/async_req/async_sock.h"
22 #include "async_smb.h"
24 struct nb_connect_state
{
25 struct tevent_context
*ev
;
27 struct nmb_name called
;
28 struct nmb_name calling
;
31 static int nb_connect_state_destructor(struct nb_connect_state
*state
);
32 static void nb_connect_connected(struct tevent_req
*subreq
);
33 static void nb_connect_done(struct tevent_req
*subreq
);
35 static struct tevent_req
*nb_connect_send(TALLOC_CTX
*mem_ctx
,
36 struct tevent_context
*ev
,
37 const struct sockaddr_storage
*addr
,
38 const char *called_name
,
40 const char *calling_name
,
43 struct tevent_req
*req
, *subreq
;
44 struct nb_connect_state
*state
;
46 req
= tevent_req_create(mem_ctx
, &state
, struct nb_connect_state
);
51 make_nmb_name(&state
->called
, called_name
, called_type
);
52 make_nmb_name(&state
->calling
, calling_name
, calling_type
);
55 talloc_set_destructor(state
, nb_connect_state_destructor
);
57 subreq
= open_socket_out_send(state
, ev
, addr
, 139, 5000);
58 if (tevent_req_nomem(subreq
, req
)) {
59 return tevent_req_post(req
, ev
);
61 tevent_req_set_callback(subreq
, nb_connect_connected
, req
);
65 static int nb_connect_state_destructor(struct nb_connect_state
*state
)
67 if (state
->sock
!= -1) {
73 static void nb_connect_connected(struct tevent_req
*subreq
)
75 struct tevent_req
*req
= tevent_req_callback_data(
76 subreq
, struct tevent_req
);
77 struct nb_connect_state
*state
= tevent_req_data(
78 req
, struct nb_connect_state
);
81 status
= open_socket_out_recv(subreq
, &state
->sock
);
83 if (!NT_STATUS_IS_OK(status
)) {
84 tevent_req_nterror(req
, status
);
87 subreq
= cli_session_request_send(state
, state
->ev
, state
->sock
,
88 &state
->called
, &state
->calling
);
89 if (tevent_req_nomem(subreq
, req
)) {
92 tevent_req_set_callback(subreq
, nb_connect_done
, req
);
95 static void nb_connect_done(struct tevent_req
*subreq
)
97 struct tevent_req
*req
= tevent_req_callback_data(
98 subreq
, struct tevent_req
);
103 ret
= cli_session_request_recv(subreq
, &err
, &resp
);
106 tevent_req_nterror(req
, map_nt_error_from_unix(err
));
110 tevent_req_nterror(req
, NT_STATUS_RESOURCE_NAME_NOT_FOUND
);
113 tevent_req_done(req
);
116 static NTSTATUS
nb_connect_recv(struct tevent_req
*req
, int *sock
)
118 struct nb_connect_state
*state
= tevent_req_data(
119 req
, struct nb_connect_state
);
122 if (tevent_req_is_nterror(req
, &status
)) {
130 struct smbsock_connect_state
{
131 struct tevent_context
*ev
;
132 const struct sockaddr_storage
*addr
;
133 const char *called_name
;
134 const char *calling_name
;
135 struct tevent_req
*req_139
;
136 struct tevent_req
*req_445
;
141 static int smbsock_connect_state_destructor(
142 struct smbsock_connect_state
*state
);
143 static void smbsock_connect_connected(struct tevent_req
*subreq
);
144 static void smbsock_connect_do_139(struct tevent_req
*subreq
);
146 struct tevent_req
*smbsock_connect_send(TALLOC_CTX
*mem_ctx
,
147 struct tevent_context
*ev
,
148 const struct sockaddr_storage
*addr
,
149 const char *called_name
,
150 const char *calling_name
)
152 struct tevent_req
*req
, *subreq
;
153 struct smbsock_connect_state
*state
;
155 req
= tevent_req_create(mem_ctx
, &state
, struct smbsock_connect_state
);
163 (called_name
!= NULL
) ? called_name
: "*SMBSERVER";
164 state
->calling_name
=
165 (calling_name
!= NULL
) ? calling_name
: global_myname();
167 talloc_set_destructor(state
, smbsock_connect_state_destructor
);
169 state
->req_445
= open_socket_out_send(state
, ev
, addr
, 445, 5000);
170 if (tevent_req_nomem(state
->req_445
, req
)) {
171 return tevent_req_post(req
, ev
);
173 tevent_req_set_callback(state
->req_445
, smbsock_connect_connected
,
177 * After 5 msecs, fire the 139 request
179 subreq
= tevent_wakeup_send(state
, ev
, timeval_current_ofs(0, 5000));
180 if (tevent_req_nomem(subreq
, req
)) {
181 TALLOC_FREE(state
->req_445
);
182 return tevent_req_post(req
, ev
);
184 tevent_req_set_callback(subreq
, smbsock_connect_do_139
, req
);
188 static int smbsock_connect_state_destructor(
189 struct smbsock_connect_state
*state
)
191 if (state
->sock
!= -1) {
197 static void smbsock_connect_do_139(struct tevent_req
*subreq
)
199 struct tevent_req
*req
= tevent_req_callback_data(
200 subreq
, struct tevent_req
);
201 struct smbsock_connect_state
*state
= tevent_req_data(
202 req
, struct smbsock_connect_state
);
205 ret
= tevent_wakeup_recv(subreq
);
208 tevent_req_nterror(req
, NT_STATUS_INTERNAL_ERROR
);
211 state
->req_139
= nb_connect_send(state
, state
->ev
, state
->addr
,
212 state
->called_name
, 0x20,
213 state
->calling_name
, 0x0);
214 if (tevent_req_nomem(state
->req_139
, req
)) {
217 tevent_req_set_callback(state
->req_139
, smbsock_connect_connected
,
221 static void smbsock_connect_connected(struct tevent_req
*subreq
)
223 struct tevent_req
*req
= tevent_req_callback_data(
224 subreq
, struct tevent_req
);
225 struct smbsock_connect_state
*state
= tevent_req_data(
226 req
, struct smbsock_connect_state
);
227 struct tevent_req
*unfinished_req
;
230 if (subreq
== state
->req_445
) {
232 status
= open_socket_out_recv(subreq
, &state
->sock
);
233 TALLOC_FREE(state
->req_445
);
234 unfinished_req
= state
->req_139
;
237 } else if (subreq
== state
->req_139
) {
239 status
= nb_connect_recv(subreq
, &state
->sock
);
240 TALLOC_FREE(state
->req_139
);
241 unfinished_req
= state
->req_445
;
245 tevent_req_nterror(req
, NT_STATUS_INTERNAL_ERROR
);
249 if (NT_STATUS_IS_OK(status
)) {
250 TALLOC_FREE(unfinished_req
);
251 state
->req_139
= NULL
;
252 state
->req_445
= NULL
;
253 tevent_req_done(req
);
256 if (unfinished_req
== NULL
) {
258 * Both requests failed
260 tevent_req_nterror(req
, status
);
264 * Do nothing, wait for the second request to come here.
268 NTSTATUS
smbsock_connect_recv(struct tevent_req
*req
, int *sock
,
271 struct smbsock_connect_state
*state
= tevent_req_data(
272 req
, struct smbsock_connect_state
);
275 if (tevent_req_is_nterror(req
, &status
)) {
284 NTSTATUS
smbsock_connect(const struct sockaddr_storage
*addr
,
285 const char *called_name
, const char *calling_name
,
286 int *pfd
, uint16_t *port
)
288 TALLOC_CTX
*frame
= talloc_stackframe();
289 struct event_context
*ev
;
290 struct tevent_req
*req
;
291 NTSTATUS status
= NT_STATUS_NO_MEMORY
;
293 ev
= event_context_init(frame
);
297 req
= smbsock_connect_send(frame
, ev
, addr
, called_name
, calling_name
);
301 if (!tevent_req_poll_ntstatus(req
, ev
, &status
)) {
304 status
= smbsock_connect_recv(req
, pfd
, port
);