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);