wscript: Add check for --wrap linker flag
[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                 state->req_139 = nb_connect_send(state, state->ev, state->addr,
380                                                  state->called_name,
381                                                  state->called_type,
382                                                  state->calling_name,
383                                                  state->calling_type);
384                 if (tevent_req_nomem(state->req_139, req)) {
385                         return tevent_req_post(req, ev);
386                 }
387                 tevent_req_set_callback(
388                         state->req_139, smbsock_connect_connected, req);
389                 return req;
390         }
391         if (port != 0) {
392                 state->req_445 = open_socket_out_send(state, ev, addr, port,
393                                                       5000);
394                 if (tevent_req_nomem(state->req_445, req)) {
395                         return tevent_req_post(req, ev);
396                 }
397                 tevent_req_set_callback(
398                         state->req_445, smbsock_connect_connected, req);
399                 return req;
400         }
401
402         /*
403          * port==0, try both
404          */
405
406         state->req_445 = open_socket_out_send(state, ev, addr, TCP_SMB_PORT, 5000);
407         if (tevent_req_nomem(state->req_445, req)) {
408                 return tevent_req_post(req, ev);
409         }
410         tevent_req_set_callback(state->req_445, smbsock_connect_connected,
411                                 req);
412
413         /*
414          * After 5 msecs, fire the 139 (NBT) request
415          */
416         state->req_139 = tevent_wakeup_send(
417                 state, ev, timeval_current_ofs(0, 5000));
418         if (tevent_req_nomem(state->req_139, req)) {
419                 TALLOC_FREE(state->req_445);
420                 return tevent_req_post(req, ev);
421         }
422         tevent_req_set_callback(state->req_139, smbsock_connect_do_139,
423                                 req);
424         return req;
425 }
426
427 static void smbsock_connect_cleanup(struct tevent_req *req,
428                                     enum tevent_req_state req_state)
429 {
430         struct smbsock_connect_state *state = tevent_req_data(
431                 req, struct smbsock_connect_state);
432
433         /*
434          * we need to free a pending request before closing the
435          * socket, see bug #11141
436          */
437         TALLOC_FREE(state->req_445);
438         TALLOC_FREE(state->req_139);
439
440         if (req_state == TEVENT_REQ_DONE) {
441                 /*
442                  * we keep the socket open for the caller to use
443                  */
444                 return;
445         }
446
447         if (state->sock != -1) {
448                 close(state->sock);
449                 state->sock = -1;
450         }
451
452         return;
453 }
454
455 static void smbsock_connect_do_139(struct tevent_req *subreq)
456 {
457         struct tevent_req *req = tevent_req_callback_data(
458                 subreq, struct tevent_req);
459         struct smbsock_connect_state *state = tevent_req_data(
460                 req, struct smbsock_connect_state);
461         bool ret;
462
463         ret = tevent_wakeup_recv(subreq);
464         TALLOC_FREE(subreq);
465         if (!ret) {
466                 tevent_req_nterror(req, NT_STATUS_INTERNAL_ERROR);
467                 return;
468         }
469         state->req_139 = nb_connect_send(state, state->ev, state->addr,
470                                          state->called_name,
471                                          state->called_type,
472                                          state->calling_name,
473                                          state->calling_type);
474         if (tevent_req_nomem(state->req_139, req)) {
475                 return;
476         }
477         tevent_req_set_callback(state->req_139, smbsock_connect_connected,
478                                 req);
479 }
480
481 static void smbsock_connect_connected(struct tevent_req *subreq)
482 {
483         struct tevent_req *req = tevent_req_callback_data(
484                 subreq, struct tevent_req);
485         struct smbsock_connect_state *state = tevent_req_data(
486                 req, struct smbsock_connect_state);
487         struct tevent_req *unfinished_req;
488         NTSTATUS status;
489
490         if (subreq == state->req_445) {
491
492                 status = open_socket_out_recv(subreq, &state->sock);
493                 TALLOC_FREE(state->req_445);
494                 unfinished_req = state->req_139;
495                 state->port = TCP_SMB_PORT;
496
497         } else if (subreq == state->req_139) {
498
499                 status = nb_connect_recv(subreq, &state->sock);
500                 TALLOC_FREE(state->req_139);
501                 unfinished_req = state->req_445;
502                 state->port = NBT_SMB_PORT;
503
504         } else {
505                 tevent_req_nterror(req, NT_STATUS_INTERNAL_ERROR);
506                 return;
507         }
508
509         if (NT_STATUS_IS_OK(status)) {
510                 TALLOC_FREE(unfinished_req);
511                 state->req_139 = NULL;
512                 state->req_445 = NULL;
513                 tevent_req_done(req);
514                 return;
515         }
516         if (unfinished_req == NULL) {
517                 /*
518                  * Both requests failed
519                  */
520                 tevent_req_nterror(req, status);
521                 return;
522         }
523         /*
524          * Do nothing, wait for the second request to come here.
525          */
526 }
527
528 NTSTATUS smbsock_connect_recv(struct tevent_req *req, int *sock,
529                               uint16_t *ret_port)
530 {
531         struct smbsock_connect_state *state = tevent_req_data(
532                 req, struct smbsock_connect_state);
533         NTSTATUS status;
534
535         if (tevent_req_is_nterror(req, &status)) {
536                 tevent_req_received(req);
537                 return status;
538         }
539         *sock = state->sock;
540         state->sock = -1;
541         if (ret_port != NULL) {
542                 *ret_port = state->port;
543         }
544         tevent_req_received(req);
545         return NT_STATUS_OK;
546 }
547
548 NTSTATUS smbsock_connect(const struct sockaddr_storage *addr, uint16_t port,
549                          const char *called_name, int called_type,
550                          const char *calling_name, int calling_type,
551                          int *pfd, uint16_t *ret_port, int sec_timeout)
552 {
553         TALLOC_CTX *frame = talloc_stackframe();
554         struct tevent_context *ev;
555         struct tevent_req *req;
556         NTSTATUS status = NT_STATUS_NO_MEMORY;
557
558         ev = samba_tevent_context_init(frame);
559         if (ev == NULL) {
560                 goto fail;
561         }
562         req = smbsock_connect_send(frame, ev, addr, port,
563                                    called_name, called_type,
564                                    calling_name, calling_type);
565         if (req == NULL) {
566                 goto fail;
567         }
568         if ((sec_timeout != 0) &&
569             !tevent_req_set_endtime(
570                     req, ev, timeval_current_ofs(sec_timeout, 0))) {
571                 goto fail;
572         }
573         if (!tevent_req_poll_ntstatus(req, ev, &status)) {
574                 goto fail;
575         }
576         status = smbsock_connect_recv(req, pfd, ret_port);
577  fail:
578         TALLOC_FREE(frame);
579         return status;
580 }
581
582 struct smbsock_any_connect_state {
583         struct tevent_context *ev;
584         const struct sockaddr_storage *addrs;
585         const char **called_names;
586         int *called_types;
587         const char **calling_names;
588         int *calling_types;
589         size_t num_addrs;
590         uint16_t port;
591
592         struct tevent_req **requests;
593         size_t num_sent;
594         size_t num_received;
595
596         int fd;
597         uint16_t chosen_port;
598         size_t chosen_index;
599 };
600
601 static void smbsock_any_connect_cleanup(struct tevent_req *req,
602                                         enum tevent_req_state req_state);
603 static bool smbsock_any_connect_send_next(
604         struct tevent_req *req, struct smbsock_any_connect_state *state);
605 static void smbsock_any_connect_trynext(struct tevent_req *subreq);
606 static void smbsock_any_connect_connected(struct tevent_req *subreq);
607
608 struct tevent_req *smbsock_any_connect_send(TALLOC_CTX *mem_ctx,
609                                             struct tevent_context *ev,
610                                             const struct sockaddr_storage *addrs,
611                                             const char **called_names,
612                                             int *called_types,
613                                             const char **calling_names,
614                                             int *calling_types,
615                                             size_t num_addrs, uint16_t port)
616 {
617         struct tevent_req *req, *subreq;
618         struct smbsock_any_connect_state *state;
619
620         req = tevent_req_create(mem_ctx, &state,
621                                 struct smbsock_any_connect_state);
622         if (req == NULL) {
623                 return NULL;
624         }
625         state->ev = ev;
626         state->addrs = addrs;
627         state->num_addrs = num_addrs;
628         state->called_names = called_names;
629         state->called_types = called_types;
630         state->calling_names = calling_names;
631         state->calling_types = calling_types;
632         state->port = port;
633         state->fd = -1;
634
635         tevent_req_set_cleanup_fn(req, smbsock_any_connect_cleanup);
636
637         if (num_addrs == 0) {
638                 tevent_req_nterror(req, NT_STATUS_INVALID_PARAMETER);
639                 return tevent_req_post(req, ev);
640         }
641
642         state->requests = talloc_zero_array(state, struct tevent_req *,
643                                             num_addrs);
644         if (tevent_req_nomem(state->requests, req)) {
645                 return tevent_req_post(req, ev);
646         }
647         if (!smbsock_any_connect_send_next(req, state)) {
648                 return tevent_req_post(req, ev);
649         }
650         if (state->num_sent >= state->num_addrs) {
651                 return req;
652         }
653         subreq = tevent_wakeup_send(state, ev, timeval_current_ofs(0, 10000));
654         if (tevent_req_nomem(subreq, req)) {
655                 return tevent_req_post(req, ev);
656         }
657         tevent_req_set_callback(subreq, smbsock_any_connect_trynext, req);
658         return req;
659 }
660
661 static void smbsock_any_connect_cleanup(struct tevent_req *req,
662                                         enum tevent_req_state req_state)
663 {
664         struct smbsock_any_connect_state *state = tevent_req_data(
665                 req, struct smbsock_any_connect_state);
666
667         TALLOC_FREE(state->requests);
668
669         if (req_state == TEVENT_REQ_DONE) {
670                 /*
671                  * Keep the socket open for the caller.
672                  */
673                 return;
674         }
675
676         if (state->fd != -1) {
677                 close(state->fd);
678                 state->fd = -1;
679         }
680 }
681
682 static void smbsock_any_connect_trynext(struct tevent_req *subreq)
683 {
684         struct tevent_req *req = tevent_req_callback_data(
685                 subreq, struct tevent_req);
686         struct smbsock_any_connect_state *state = tevent_req_data(
687                 req, struct smbsock_any_connect_state);
688         bool ret;
689
690         ret = tevent_wakeup_recv(subreq);
691         TALLOC_FREE(subreq);
692         if (!ret) {
693                 tevent_req_nterror(req, NT_STATUS_INTERNAL_ERROR);
694                 return;
695         }
696         if (!smbsock_any_connect_send_next(req, state)) {
697                 return;
698         }
699         if (state->num_sent >= state->num_addrs) {
700                 return;
701         }
702         subreq = tevent_wakeup_send(state, state->ev,
703                                     tevent_timeval_set(0, 10000));
704         if (tevent_req_nomem(subreq, req)) {
705                 return;
706         }
707         tevent_req_set_callback(subreq, smbsock_any_connect_trynext, req);
708 }
709
710 static bool smbsock_any_connect_send_next(
711         struct tevent_req *req, struct smbsock_any_connect_state *state)
712 {
713         struct tevent_req *subreq;
714
715         if (state->num_sent >= state->num_addrs) {
716                 tevent_req_nterror(req, NT_STATUS_INTERNAL_ERROR);
717                 return false;
718         }
719         subreq = smbsock_connect_send(
720                 state->requests, state->ev, &state->addrs[state->num_sent],
721                 state->port,
722                 (state->called_names != NULL)
723                 ? state->called_names[state->num_sent] : NULL,
724                 (state->called_types != NULL)
725                 ? state->called_types[state->num_sent] : -1,
726                 (state->calling_names != NULL)
727                 ? state->calling_names[state->num_sent] : NULL,
728                 (state->calling_types != NULL)
729                 ? state->calling_types[state->num_sent] : -1);
730         if (tevent_req_nomem(subreq, req)) {
731                 return false;
732         }
733         tevent_req_set_callback(subreq, smbsock_any_connect_connected, req);
734
735         state->requests[state->num_sent] = subreq;
736         state->num_sent += 1;
737
738         return true;
739 }
740
741 static void smbsock_any_connect_connected(struct tevent_req *subreq)
742 {
743         struct tevent_req *req = tevent_req_callback_data(
744                 subreq, struct tevent_req);
745         struct smbsock_any_connect_state *state = tevent_req_data(
746                 req, struct smbsock_any_connect_state);
747         NTSTATUS status;
748         int fd;
749         uint16_t chosen_port;
750         size_t i;
751         size_t chosen_index = 0;
752
753         for (i=0; i<state->num_sent; i++) {
754                 if (state->requests[i] == subreq) {
755                         chosen_index = i;
756                         break;
757                 }
758         }
759         if (i == state->num_sent) {
760                 tevent_req_nterror(req, NT_STATUS_INTERNAL_ERROR);
761                 return;
762         }
763
764         status = smbsock_connect_recv(subreq, &fd, &chosen_port);
765
766         TALLOC_FREE(subreq);
767         state->requests[chosen_index] = NULL;
768
769         if (NT_STATUS_IS_OK(status)) {
770                 /*
771                  * tevent_req_done() will kill all the other requests
772                  * via smbsock_any_connect_cleanup().
773                  */
774                 state->fd = fd;
775                 state->chosen_port = chosen_port;
776                 state->chosen_index = chosen_index;
777                 tevent_req_done(req);
778                 return;
779         }
780
781         state->num_received += 1;
782         if (state->num_received < state->num_addrs) {
783                 /*
784                  * More addrs pending, wait for the others
785                  */
786                 return;
787         }
788
789         /*
790          * This is the last response, none succeeded.
791          */
792         tevent_req_nterror(req, status);
793         return;
794 }
795
796 NTSTATUS smbsock_any_connect_recv(struct tevent_req *req, int *pfd,
797                                   size_t *chosen_index,
798                                   uint16_t *chosen_port)
799 {
800         struct smbsock_any_connect_state *state = tevent_req_data(
801                 req, struct smbsock_any_connect_state);
802         NTSTATUS status;
803
804         if (tevent_req_is_nterror(req, &status)) {
805                 tevent_req_received(req);
806                 return status;
807         }
808         *pfd = state->fd;
809         state->fd = -1;
810         if (chosen_index != NULL) {
811                 *chosen_index = state->chosen_index;
812         }
813         if (chosen_port != NULL) {
814                 *chosen_port = state->chosen_port;
815         }
816         tevent_req_received(req);
817         return NT_STATUS_OK;
818 }
819
820 NTSTATUS smbsock_any_connect(const struct sockaddr_storage *addrs,
821                              const char **called_names,
822                              int *called_types,
823                              const char **calling_names,
824                              int *calling_types,
825                              size_t num_addrs,
826                              uint16_t port,
827                              int sec_timeout,
828                              int *pfd, size_t *chosen_index,
829                              uint16_t *chosen_port)
830 {
831         TALLOC_CTX *frame = talloc_stackframe();
832         struct tevent_context *ev;
833         struct tevent_req *req;
834         NTSTATUS status = NT_STATUS_NO_MEMORY;
835
836         ev = samba_tevent_context_init(frame);
837         if (ev == NULL) {
838                 goto fail;
839         }
840         req = smbsock_any_connect_send(frame, ev, addrs,
841                                        called_names, called_types,
842                                        calling_names, calling_types,
843                                        num_addrs, port);
844         if (req == NULL) {
845                 goto fail;
846         }
847         if ((sec_timeout != 0) &&
848             !tevent_req_set_endtime(
849                     req, ev, timeval_current_ofs(sec_timeout, 0))) {
850                 goto fail;
851         }
852         if (!tevent_req_poll_ntstatus(req, ev, &status)) {
853                 goto fail;
854         }
855         status = smbsock_any_connect_recv(req, pfd, chosen_index, chosen_port);
856  fail:
857         TALLOC_FREE(frame);
858         return status;
859 }