s3:utils: Use C99 initializer for poptOption in sharesec
[vlendec/samba-autobuild/.git] / source3 / libsmb / smbsock_connect.c
1 /*
2    Unix SMB/CIFS implementation.
3    Connect to 445 and 139/nbsesssetup
4    Copyright (C) Volker Lendecke 2010
5
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.
10
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.
15
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/>.
18 */
19
20 #include "includes.h"
21 #include "../lib/async_req/async_sock.h"
22 #include "../lib/util/tevent_ntstatus.h"
23 #include "../lib/util/tevent_unix.h"
24 #include "client.h"
25 #include "async_smb.h"
26 #include "../libcli/smb/read_smb.h"
27 #include "libsmb/nmblib.h"
28
29 struct cli_session_request_state {
30         struct tevent_context *ev;
31         int sock;
32         uint32_t len_hdr;
33         struct iovec iov[3];
34         uint8_t nb_session_response;
35 };
36
37 static void cli_session_request_sent(struct tevent_req *subreq);
38 static void cli_session_request_recvd(struct tevent_req *subreq);
39
40 static struct tevent_req *cli_session_request_send(TALLOC_CTX *mem_ctx,
41                                         struct tevent_context *ev,
42                                         int sock,
43                                         const struct nmb_name *called,
44                                         const struct nmb_name *calling)
45 {
46         struct tevent_req *req, *subreq;
47         struct cli_session_request_state *state;
48
49         req = tevent_req_create(mem_ctx, &state,
50                                 struct cli_session_request_state);
51         if (req == NULL) {
52                 return NULL;
53         }
54         state->ev = ev;
55         state->sock = sock;
56
57         state->iov[1].iov_base = name_mangle(
58                 state, called->name, called->name_type);
59         if (tevent_req_nomem(state->iov[1].iov_base, req)) {
60                 return tevent_req_post(req, ev);
61         }
62         state->iov[1].iov_len = name_len(
63                 (unsigned char *)state->iov[1].iov_base,
64                 talloc_get_size(state->iov[1].iov_base));
65
66         state->iov[2].iov_base = name_mangle(
67                 state, calling->name, calling->name_type);
68         if (tevent_req_nomem(state->iov[2].iov_base, req)) {
69                 return tevent_req_post(req, ev);
70         }
71         state->iov[2].iov_len = name_len(
72                 (unsigned char *)state->iov[2].iov_base,
73                 talloc_get_size(state->iov[2].iov_base));
74
75         _smb_setlen(((char *)&state->len_hdr),
76                     state->iov[1].iov_len + state->iov[2].iov_len);
77         SCVAL((char *)&state->len_hdr, 0, 0x81);
78
79         state->iov[0].iov_base = &state->len_hdr;
80         state->iov[0].iov_len = sizeof(state->len_hdr);
81
82         subreq = writev_send(state, ev, NULL, sock, true, state->iov, 3);
83         if (tevent_req_nomem(subreq, req)) {
84                 return tevent_req_post(req, ev);
85         }
86         tevent_req_set_callback(subreq, cli_session_request_sent, req);
87         return req;
88 }
89
90 static void cli_session_request_sent(struct tevent_req *subreq)
91 {
92         struct tevent_req *req = tevent_req_callback_data(
93                 subreq, struct tevent_req);
94         struct cli_session_request_state *state = tevent_req_data(
95                 req, struct cli_session_request_state);
96         ssize_t ret;
97         int err;
98
99         ret = writev_recv(subreq, &err);
100         TALLOC_FREE(subreq);
101         if (ret == -1) {
102                 tevent_req_error(req, err);
103                 return;
104         }
105         subreq = read_smb_send(state, state->ev, state->sock);
106         if (tevent_req_nomem(subreq, req)) {
107                 return;
108         }
109         tevent_req_set_callback(subreq, cli_session_request_recvd, req);
110 }
111
112 static void cli_session_request_recvd(struct tevent_req *subreq)
113 {
114         struct tevent_req *req = tevent_req_callback_data(
115                 subreq, struct tevent_req);
116         struct cli_session_request_state *state = tevent_req_data(
117                 req, struct cli_session_request_state);
118         uint8_t *buf;
119         ssize_t ret;
120         int err;
121
122         ret = read_smb_recv(subreq, talloc_tos(), &buf, &err);
123         TALLOC_FREE(subreq);
124
125         if (ret < 4) {
126                 ret = -1;
127                 err = EIO;
128         }
129         if (ret == -1) {
130                 tevent_req_error(req, err);
131                 return;
132         }
133         /*
134          * In case of an error there is more information in the data
135          * portion according to RFC1002. We're not subtle enough to
136          * respond to the different error conditions, so drop the
137          * error info here.
138          */
139         state->nb_session_response = CVAL(buf, 0);
140         tevent_req_done(req);
141 }
142
143 static bool cli_session_request_recv(struct tevent_req *req, int *err, uint8_t *resp)
144 {
145         struct cli_session_request_state *state = tevent_req_data(
146                 req, struct cli_session_request_state);
147
148         if (tevent_req_is_unix_error(req, err)) {
149                 return false;
150         }
151         *resp = state->nb_session_response;
152         return true;
153 }
154
155 struct nb_connect_state {
156         struct tevent_context *ev;
157         const struct sockaddr_storage *addr;
158         const char *called_name;
159         int sock;
160         struct tevent_req *session_subreq;
161         struct nmb_name called;
162         struct nmb_name calling;
163 };
164
165 static void nb_connect_cleanup(struct tevent_req *req,
166                                enum tevent_req_state req_state);
167 static void nb_connect_connected(struct tevent_req *subreq);
168 static void nb_connect_done(struct tevent_req *subreq);
169
170 static struct tevent_req *nb_connect_send(TALLOC_CTX *mem_ctx,
171                                           struct tevent_context *ev,
172                                           const struct sockaddr_storage *addr,
173                                           const char *called_name,
174                                           int called_type,
175                                           const char *calling_name,
176                                           int calling_type)
177 {
178         struct tevent_req *req, *subreq;
179         struct nb_connect_state *state;
180
181         req = tevent_req_create(mem_ctx, &state, struct nb_connect_state);
182         if (req == NULL) {
183                 return NULL;
184         }
185         state->ev = ev;
186         state->called_name = called_name;
187         state->addr = addr;
188
189         state->sock = -1;
190         make_nmb_name(&state->called, called_name, called_type);
191         make_nmb_name(&state->calling, calling_name, calling_type);
192
193         tevent_req_set_cleanup_fn(req, nb_connect_cleanup);
194
195         subreq = open_socket_out_send(state, ev, addr, NBT_SMB_PORT, 5000);
196         if (tevent_req_nomem(subreq, req)) {
197                 return tevent_req_post(req, ev);
198         }
199         tevent_req_set_callback(subreq, nb_connect_connected, req);
200         return req;
201 }
202
203 static void nb_connect_cleanup(struct tevent_req *req,
204                                enum tevent_req_state req_state)
205 {
206         struct nb_connect_state *state = tevent_req_data(
207                 req, struct nb_connect_state);
208
209         /*
210          * we need to free a pending request before closing the
211          * socket, see bug #11141
212          */
213         TALLOC_FREE(state->session_subreq);
214
215         if (req_state == TEVENT_REQ_DONE) {
216                 /*
217                  * we keep the socket open for the caller to use
218                  */
219                 return;
220         }
221
222         if (state->sock != -1) {
223                 close(state->sock);
224                 state->sock = -1;
225         }
226
227         return;
228 }
229
230 static void nb_connect_connected(struct tevent_req *subreq)
231 {
232         struct tevent_req *req = tevent_req_callback_data(
233                 subreq, struct tevent_req);
234         struct nb_connect_state *state = tevent_req_data(
235                 req, struct nb_connect_state);
236         NTSTATUS status;
237
238         status = open_socket_out_recv(subreq, &state->sock);
239         TALLOC_FREE(subreq);
240         if (!NT_STATUS_IS_OK(status)) {
241                 tevent_req_nterror(req, status);
242                 return;
243         }
244         subreq = cli_session_request_send(state, state->ev, state->sock,
245                                           &state->called, &state->calling);
246         if (tevent_req_nomem(subreq, req)) {
247                 return;
248         }
249         tevent_req_set_callback(subreq, nb_connect_done, req);
250         state->session_subreq = subreq;
251 }
252
253 static void nb_connect_done(struct tevent_req *subreq)
254 {
255         struct tevent_req *req = tevent_req_callback_data(
256                 subreq, struct tevent_req);
257         struct nb_connect_state *state = tevent_req_data(
258                 req, struct nb_connect_state);
259         bool ret;
260         int err;
261         uint8_t resp;
262
263         state->session_subreq = NULL;
264
265         ret = cli_session_request_recv(subreq, &err, &resp);
266         TALLOC_FREE(subreq);
267         if (!ret) {
268                 tevent_req_nterror(req, map_nt_error_from_unix(err));
269                 return;
270         }
271
272         /*
273          * RFC1002: 0x82 - POSITIVE SESSION RESPONSE
274          */
275
276         if (resp != 0x82) {
277                 /*
278                  * The server did not like our session request
279                  */
280                 close(state->sock);
281                 state->sock = -1;
282
283                 if (strequal(state->called_name, "*SMBSERVER")) {
284                         /*
285                          * Here we could try a name status request and
286                          * use the first 0x20 type name.
287                          */
288                         tevent_req_nterror(
289                                 req, NT_STATUS_RESOURCE_NAME_NOT_FOUND);
290                         return;
291                 }
292
293                 /*
294                  * We could be subtle and distinguish between
295                  * different failure modes, but what we do here
296                  * instead is just retry with *SMBSERVER type 0x20.
297                  */
298                 state->called_name = "*SMBSERVER";
299                 make_nmb_name(&state->called, state->called_name, 0x20);
300
301                 subreq = open_socket_out_send(state, state->ev, state->addr,
302                                               NBT_SMB_PORT, 5000);
303                 if (tevent_req_nomem(subreq, req)) {
304                         return;
305                 }
306                 tevent_req_set_callback(subreq, nb_connect_connected, req);
307                 return;
308         }
309
310         tevent_req_done(req);
311         return;
312 }
313
314 static NTSTATUS nb_connect_recv(struct tevent_req *req, int *sock)
315 {
316         struct nb_connect_state *state = tevent_req_data(
317                 req, struct nb_connect_state);
318         NTSTATUS status;
319
320         if (tevent_req_is_nterror(req, &status)) {
321                 tevent_req_received(req);
322                 return status;
323         }
324         *sock = state->sock;
325         state->sock = -1;
326         tevent_req_received(req);
327         return NT_STATUS_OK;
328 }
329
330 struct smbsock_connect_state {
331         struct tevent_context *ev;
332         const struct sockaddr_storage *addr;
333         const char *called_name;
334         uint8_t called_type;
335         const char *calling_name;
336         uint8_t calling_type;
337         struct tevent_req *req_139;
338         struct tevent_req *req_445;
339         int sock;
340         uint16_t port;
341 };
342
343 static void smbsock_connect_cleanup(struct tevent_req *req,
344                                     enum tevent_req_state req_state);
345 static void smbsock_connect_connected(struct tevent_req *subreq);
346 static void smbsock_connect_do_139(struct tevent_req *subreq);
347
348 struct tevent_req *smbsock_connect_send(TALLOC_CTX *mem_ctx,
349                                         struct tevent_context *ev,
350                                         const struct sockaddr_storage *addr,
351                                         uint16_t port,
352                                         const char *called_name,
353                                         int called_type,
354                                         const char *calling_name,
355                                         int calling_type)
356 {
357         struct tevent_req *req;
358         struct smbsock_connect_state *state;
359
360         req = tevent_req_create(mem_ctx, &state, struct smbsock_connect_state);
361         if (req == NULL) {
362                 return NULL;
363         }
364         state->ev = ev;
365         state->addr = addr;
366         state->sock = -1;
367         state->called_name =
368                 (called_name != NULL) ? called_name : "*SMBSERVER";
369         state->called_type =
370                 (called_type != -1) ? called_type : 0x20;
371         state->calling_name =
372                 (calling_name != NULL) ? calling_name : lp_netbios_name();
373         state->calling_type =
374                 (calling_type != -1) ? calling_type : 0x00;
375
376         tevent_req_set_cleanup_fn(req, smbsock_connect_cleanup);
377
378         if (port == NBT_SMB_PORT) {
379                 if (lp_disable_netbios()) {
380                         tevent_req_nterror(req, NT_STATUS_NOT_SUPPORTED);
381                         return tevent_req_post(req, ev);
382                 }
383
384                 state->req_139 = nb_connect_send(state, state->ev, state->addr,
385                                                  state->called_name,
386                                                  state->called_type,
387                                                  state->calling_name,
388                                                  state->calling_type);
389                 if (tevent_req_nomem(state->req_139, req)) {
390                         return tevent_req_post(req, ev);
391                 }
392                 tevent_req_set_callback(
393                         state->req_139, smbsock_connect_connected, req);
394                 return req;
395         }
396         if (port != 0) {
397                 state->req_445 = open_socket_out_send(state, ev, addr, port,
398                                                       5000);
399                 if (tevent_req_nomem(state->req_445, req)) {
400                         return tevent_req_post(req, ev);
401                 }
402                 tevent_req_set_callback(
403                         state->req_445, smbsock_connect_connected, req);
404                 return req;
405         }
406
407         /*
408          * port==0, try both
409          */
410
411         state->req_445 = open_socket_out_send(state, ev, addr, TCP_SMB_PORT, 5000);
412         if (tevent_req_nomem(state->req_445, req)) {
413                 return tevent_req_post(req, ev);
414         }
415         tevent_req_set_callback(state->req_445, smbsock_connect_connected,
416                                 req);
417
418         /*
419          * Check for disable_netbios
420          */
421         if (lp_disable_netbios()) {
422                 return req;
423         }
424
425         /*
426          * After 5 msecs, fire the 139 (NBT) request
427          */
428         state->req_139 = tevent_wakeup_send(
429                 state, ev, timeval_current_ofs(0, 5000));
430         if (tevent_req_nomem(state->req_139, req)) {
431                 TALLOC_FREE(state->req_445);
432                 return tevent_req_post(req, ev);
433         }
434         tevent_req_set_callback(state->req_139, smbsock_connect_do_139,
435                                 req);
436         return req;
437 }
438
439 static void smbsock_connect_cleanup(struct tevent_req *req,
440                                     enum tevent_req_state req_state)
441 {
442         struct smbsock_connect_state *state = tevent_req_data(
443                 req, struct smbsock_connect_state);
444
445         /*
446          * we need to free a pending request before closing the
447          * socket, see bug #11141
448          */
449         TALLOC_FREE(state->req_445);
450         TALLOC_FREE(state->req_139);
451
452         if (req_state == TEVENT_REQ_DONE) {
453                 /*
454                  * we keep the socket open for the caller to use
455                  */
456                 return;
457         }
458
459         if (state->sock != -1) {
460                 close(state->sock);
461                 state->sock = -1;
462         }
463
464         return;
465 }
466
467 static void smbsock_connect_do_139(struct tevent_req *subreq)
468 {
469         struct tevent_req *req = tevent_req_callback_data(
470                 subreq, struct tevent_req);
471         struct smbsock_connect_state *state = tevent_req_data(
472                 req, struct smbsock_connect_state);
473         bool ret;
474
475         ret = tevent_wakeup_recv(subreq);
476         TALLOC_FREE(subreq);
477         if (!ret) {
478                 tevent_req_nterror(req, NT_STATUS_INTERNAL_ERROR);
479                 return;
480         }
481         state->req_139 = nb_connect_send(state, state->ev, state->addr,
482                                          state->called_name,
483                                          state->called_type,
484                                          state->calling_name,
485                                          state->calling_type);
486         if (tevent_req_nomem(state->req_139, req)) {
487                 return;
488         }
489         tevent_req_set_callback(state->req_139, smbsock_connect_connected,
490                                 req);
491 }
492
493 static void smbsock_connect_connected(struct tevent_req *subreq)
494 {
495         struct tevent_req *req = tevent_req_callback_data(
496                 subreq, struct tevent_req);
497         struct smbsock_connect_state *state = tevent_req_data(
498                 req, struct smbsock_connect_state);
499         struct tevent_req *unfinished_req;
500         NTSTATUS status;
501
502         if (subreq == state->req_445) {
503
504                 status = open_socket_out_recv(subreq, &state->sock);
505                 TALLOC_FREE(state->req_445);
506                 unfinished_req = state->req_139;
507                 state->port = TCP_SMB_PORT;
508
509         } else if (subreq == state->req_139) {
510
511                 status = nb_connect_recv(subreq, &state->sock);
512                 TALLOC_FREE(state->req_139);
513                 unfinished_req = state->req_445;
514                 state->port = NBT_SMB_PORT;
515
516         } else {
517                 tevent_req_nterror(req, NT_STATUS_INTERNAL_ERROR);
518                 return;
519         }
520
521         if (NT_STATUS_IS_OK(status)) {
522                 TALLOC_FREE(unfinished_req);
523                 state->req_139 = NULL;
524                 state->req_445 = NULL;
525                 tevent_req_done(req);
526                 return;
527         }
528         if (unfinished_req == NULL) {
529                 /*
530                  * Both requests failed
531                  */
532                 tevent_req_nterror(req, status);
533                 return;
534         }
535         /*
536          * Do nothing, wait for the second request to come here.
537          */
538 }
539
540 NTSTATUS smbsock_connect_recv(struct tevent_req *req, int *sock,
541                               uint16_t *ret_port)
542 {
543         struct smbsock_connect_state *state = tevent_req_data(
544                 req, struct smbsock_connect_state);
545         NTSTATUS status;
546
547         if (tevent_req_is_nterror(req, &status)) {
548                 tevent_req_received(req);
549                 return status;
550         }
551         *sock = state->sock;
552         state->sock = -1;
553         if (ret_port != NULL) {
554                 *ret_port = state->port;
555         }
556         tevent_req_received(req);
557         return NT_STATUS_OK;
558 }
559
560 NTSTATUS smbsock_connect(const struct sockaddr_storage *addr, uint16_t port,
561                          const char *called_name, int called_type,
562                          const char *calling_name, int calling_type,
563                          int *pfd, uint16_t *ret_port, int sec_timeout)
564 {
565         TALLOC_CTX *frame = talloc_stackframe();
566         struct tevent_context *ev;
567         struct tevent_req *req;
568         NTSTATUS status = NT_STATUS_NO_MEMORY;
569
570         ev = samba_tevent_context_init(frame);
571         if (ev == NULL) {
572                 goto fail;
573         }
574         req = smbsock_connect_send(frame, ev, addr, port,
575                                    called_name, called_type,
576                                    calling_name, calling_type);
577         if (req == NULL) {
578                 goto fail;
579         }
580         if ((sec_timeout != 0) &&
581             !tevent_req_set_endtime(
582                     req, ev, timeval_current_ofs(sec_timeout, 0))) {
583                 goto fail;
584         }
585         if (!tevent_req_poll_ntstatus(req, ev, &status)) {
586                 goto fail;
587         }
588         status = smbsock_connect_recv(req, pfd, ret_port);
589  fail:
590         TALLOC_FREE(frame);
591         return status;
592 }
593
594 struct smbsock_any_connect_state {
595         struct tevent_context *ev;
596         const struct sockaddr_storage *addrs;
597         const char **called_names;
598         int *called_types;
599         const char **calling_names;
600         int *calling_types;
601         size_t num_addrs;
602         uint16_t port;
603
604         struct tevent_req **requests;
605         size_t num_sent;
606         size_t num_received;
607
608         int fd;
609         uint16_t chosen_port;
610         size_t chosen_index;
611 };
612
613 static void smbsock_any_connect_cleanup(struct tevent_req *req,
614                                         enum tevent_req_state req_state);
615 static bool smbsock_any_connect_send_next(
616         struct tevent_req *req, struct smbsock_any_connect_state *state);
617 static void smbsock_any_connect_trynext(struct tevent_req *subreq);
618 static void smbsock_any_connect_connected(struct tevent_req *subreq);
619
620 struct tevent_req *smbsock_any_connect_send(TALLOC_CTX *mem_ctx,
621                                             struct tevent_context *ev,
622                                             const struct sockaddr_storage *addrs,
623                                             const char **called_names,
624                                             int *called_types,
625                                             const char **calling_names,
626                                             int *calling_types,
627                                             size_t num_addrs, uint16_t port)
628 {
629         struct tevent_req *req, *subreq;
630         struct smbsock_any_connect_state *state;
631
632         req = tevent_req_create(mem_ctx, &state,
633                                 struct smbsock_any_connect_state);
634         if (req == NULL) {
635                 return NULL;
636         }
637         state->ev = ev;
638         state->addrs = addrs;
639         state->num_addrs = num_addrs;
640         state->called_names = called_names;
641         state->called_types = called_types;
642         state->calling_names = calling_names;
643         state->calling_types = calling_types;
644         state->port = port;
645         state->fd = -1;
646
647         tevent_req_set_cleanup_fn(req, smbsock_any_connect_cleanup);
648
649         if (num_addrs == 0) {
650                 tevent_req_nterror(req, NT_STATUS_INVALID_PARAMETER);
651                 return tevent_req_post(req, ev);
652         }
653
654         state->requests = talloc_zero_array(state, struct tevent_req *,
655                                             num_addrs);
656         if (tevent_req_nomem(state->requests, req)) {
657                 return tevent_req_post(req, ev);
658         }
659         if (!smbsock_any_connect_send_next(req, state)) {
660                 return tevent_req_post(req, ev);
661         }
662         if (state->num_sent >= state->num_addrs) {
663                 return req;
664         }
665         subreq = tevent_wakeup_send(state, ev, timeval_current_ofs(0, 10000));
666         if (tevent_req_nomem(subreq, req)) {
667                 return tevent_req_post(req, ev);
668         }
669         tevent_req_set_callback(subreq, smbsock_any_connect_trynext, req);
670         return req;
671 }
672
673 static void smbsock_any_connect_cleanup(struct tevent_req *req,
674                                         enum tevent_req_state req_state)
675 {
676         struct smbsock_any_connect_state *state = tevent_req_data(
677                 req, struct smbsock_any_connect_state);
678
679         TALLOC_FREE(state->requests);
680
681         if (req_state == TEVENT_REQ_DONE) {
682                 /*
683                  * Keep the socket open for the caller.
684                  */
685                 return;
686         }
687
688         if (state->fd != -1) {
689                 close(state->fd);
690                 state->fd = -1;
691         }
692 }
693
694 static void smbsock_any_connect_trynext(struct tevent_req *subreq)
695 {
696         struct tevent_req *req = tevent_req_callback_data(
697                 subreq, struct tevent_req);
698         struct smbsock_any_connect_state *state = tevent_req_data(
699                 req, struct smbsock_any_connect_state);
700         bool ret;
701
702         ret = tevent_wakeup_recv(subreq);
703         TALLOC_FREE(subreq);
704         if (!ret) {
705                 tevent_req_nterror(req, NT_STATUS_INTERNAL_ERROR);
706                 return;
707         }
708         if (!smbsock_any_connect_send_next(req, state)) {
709                 return;
710         }
711         if (state->num_sent >= state->num_addrs) {
712                 return;
713         }
714         subreq = tevent_wakeup_send(state, state->ev,
715                                     tevent_timeval_set(0, 10000));
716         if (tevent_req_nomem(subreq, req)) {
717                 return;
718         }
719         tevent_req_set_callback(subreq, smbsock_any_connect_trynext, req);
720 }
721
722 static bool smbsock_any_connect_send_next(
723         struct tevent_req *req, struct smbsock_any_connect_state *state)
724 {
725         struct tevent_req *subreq;
726
727         if (state->num_sent >= state->num_addrs) {
728                 tevent_req_nterror(req, NT_STATUS_INTERNAL_ERROR);
729                 return false;
730         }
731         subreq = smbsock_connect_send(
732                 state->requests, state->ev, &state->addrs[state->num_sent],
733                 state->port,
734                 (state->called_names != NULL)
735                 ? state->called_names[state->num_sent] : NULL,
736                 (state->called_types != NULL)
737                 ? state->called_types[state->num_sent] : -1,
738                 (state->calling_names != NULL)
739                 ? state->calling_names[state->num_sent] : NULL,
740                 (state->calling_types != NULL)
741                 ? state->calling_types[state->num_sent] : -1);
742         if (tevent_req_nomem(subreq, req)) {
743                 return false;
744         }
745         tevent_req_set_callback(subreq, smbsock_any_connect_connected, req);
746
747         state->requests[state->num_sent] = subreq;
748         state->num_sent += 1;
749
750         return true;
751 }
752
753 static void smbsock_any_connect_connected(struct tevent_req *subreq)
754 {
755         struct tevent_req *req = tevent_req_callback_data(
756                 subreq, struct tevent_req);
757         struct smbsock_any_connect_state *state = tevent_req_data(
758                 req, struct smbsock_any_connect_state);
759         NTSTATUS status;
760         int fd;
761         uint16_t chosen_port;
762         size_t i;
763         size_t chosen_index = 0;
764
765         for (i=0; i<state->num_sent; i++) {
766                 if (state->requests[i] == subreq) {
767                         chosen_index = i;
768                         break;
769                 }
770         }
771         if (i == state->num_sent) {
772                 tevent_req_nterror(req, NT_STATUS_INTERNAL_ERROR);
773                 return;
774         }
775
776         status = smbsock_connect_recv(subreq, &fd, &chosen_port);
777
778         TALLOC_FREE(subreq);
779         state->requests[chosen_index] = NULL;
780
781         if (NT_STATUS_IS_OK(status)) {
782                 /*
783                  * tevent_req_done() will kill all the other requests
784                  * via smbsock_any_connect_cleanup().
785                  */
786                 state->fd = fd;
787                 state->chosen_port = chosen_port;
788                 state->chosen_index = chosen_index;
789                 tevent_req_done(req);
790                 return;
791         }
792
793         state->num_received += 1;
794         if (state->num_received < state->num_addrs) {
795                 /*
796                  * More addrs pending, wait for the others
797                  */
798                 return;
799         }
800
801         /*
802          * This is the last response, none succeeded.
803          */
804         tevent_req_nterror(req, status);
805         return;
806 }
807
808 NTSTATUS smbsock_any_connect_recv(struct tevent_req *req, int *pfd,
809                                   size_t *chosen_index,
810                                   uint16_t *chosen_port)
811 {
812         struct smbsock_any_connect_state *state = tevent_req_data(
813                 req, struct smbsock_any_connect_state);
814         NTSTATUS status;
815
816         if (tevent_req_is_nterror(req, &status)) {
817                 tevent_req_received(req);
818                 return status;
819         }
820         *pfd = state->fd;
821         state->fd = -1;
822         if (chosen_index != NULL) {
823                 *chosen_index = state->chosen_index;
824         }
825         if (chosen_port != NULL) {
826                 *chosen_port = state->chosen_port;
827         }
828         tevent_req_received(req);
829         return NT_STATUS_OK;
830 }
831
832 NTSTATUS smbsock_any_connect(const struct sockaddr_storage *addrs,
833                              const char **called_names,
834                              int *called_types,
835                              const char **calling_names,
836                              int *calling_types,
837                              size_t num_addrs,
838                              uint16_t port,
839                              int sec_timeout,
840                              int *pfd, size_t *chosen_index,
841                              uint16_t *chosen_port)
842 {
843         TALLOC_CTX *frame = talloc_stackframe();
844         struct tevent_context *ev;
845         struct tevent_req *req;
846         NTSTATUS status = NT_STATUS_NO_MEMORY;
847
848         ev = samba_tevent_context_init(frame);
849         if (ev == NULL) {
850                 goto fail;
851         }
852         req = smbsock_any_connect_send(frame, ev, addrs,
853                                        called_names, called_types,
854                                        calling_names, calling_types,
855                                        num_addrs, port);
856         if (req == NULL) {
857                 goto fail;
858         }
859         if ((sec_timeout != 0) &&
860             !tevent_req_set_endtime(
861                     req, ev, timeval_current_ofs(sec_timeout, 0))) {
862                 goto fail;
863         }
864         if (!tevent_req_poll_ntstatus(req, ev, &status)) {
865                 goto fail;
866         }
867         status = smbsock_any_connect_recv(req, pfd, chosen_index, chosen_port);
868  fail:
869         TALLOC_FREE(frame);
870         return status;
871 }