Coverage Report

Created: 2025-07-23 07:04

/src/samba/source3/libsmb/smbsock_connect.c
Line
Count
Source (jump to first uncovered line)
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/param/param.h"
22
#include "../lib/async_req/async_sock.h"
23
#include "../lib/util/tevent_ntstatus.h"
24
#include "../lib/util/tevent_unix.h"
25
#include "../lib/tsocket/tsocket.h"
26
#include "client.h"
27
#include "../libcli/smb/smbXcli_base.h"
28
#include "async_smb.h"
29
#include "../libcli/smb/read_smb.h"
30
#include "libsmb/nmblib.h"
31
#include "libsmb/smbsock_connect.h"
32
#include "../source4/lib/tls/tls.h"
33
34
#ifdef HAVE_LIBQUIC
35
#include <netinet/quic.h>
36
#endif
37
38
struct cli_session_request_state {
39
  struct tevent_context *ev;
40
  int sock;
41
  uint32_t len_hdr;
42
  struct iovec iov[3];
43
  uint8_t nb_session_response;
44
};
45
46
static void cli_session_request_sent(struct tevent_req *subreq);
47
static void cli_session_request_recvd(struct tevent_req *subreq);
48
49
static struct tevent_req *cli_session_request_send(TALLOC_CTX *mem_ctx,
50
          struct tevent_context *ev,
51
          int sock,
52
          const struct nmb_name *called,
53
          const struct nmb_name *calling)
54
0
{
55
0
  struct tevent_req *req, *subreq;
56
0
  struct cli_session_request_state *state;
57
58
0
  req = tevent_req_create(mem_ctx, &state,
59
0
        struct cli_session_request_state);
60
0
  if (req == NULL) {
61
0
    return NULL;
62
0
  }
63
0
  state->ev = ev;
64
0
  state->sock = sock;
65
66
0
  state->iov[1].iov_base = name_mangle(
67
0
    state, called->name, called->name_type);
68
0
  if (tevent_req_nomem(state->iov[1].iov_base, req)) {
69
0
    return tevent_req_post(req, ev);
70
0
  }
71
0
  state->iov[1].iov_len = name_len(
72
0
    (unsigned char *)state->iov[1].iov_base,
73
0
    talloc_get_size(state->iov[1].iov_base));
74
75
0
  state->iov[2].iov_base = name_mangle(
76
0
    state, calling->name, calling->name_type);
77
0
  if (tevent_req_nomem(state->iov[2].iov_base, req)) {
78
0
    return tevent_req_post(req, ev);
79
0
  }
80
0
  state->iov[2].iov_len = name_len(
81
0
    (unsigned char *)state->iov[2].iov_base,
82
0
    talloc_get_size(state->iov[2].iov_base));
83
84
0
  _smb_setlen(((char *)&state->len_hdr),
85
0
        state->iov[1].iov_len + state->iov[2].iov_len);
86
0
  SCVAL((char *)&state->len_hdr, 0, 0x81);
87
88
0
  state->iov[0].iov_base = &state->len_hdr;
89
0
  state->iov[0].iov_len = sizeof(state->len_hdr);
90
91
0
  subreq = writev_send(state, ev, NULL, sock, true, state->iov, 3);
92
0
  if (tevent_req_nomem(subreq, req)) {
93
0
    return tevent_req_post(req, ev);
94
0
  }
95
0
  tevent_req_set_callback(subreq, cli_session_request_sent, req);
96
0
  return req;
97
0
}
98
99
static void cli_session_request_sent(struct tevent_req *subreq)
100
0
{
101
0
  struct tevent_req *req = tevent_req_callback_data(
102
0
    subreq, struct tevent_req);
103
0
  struct cli_session_request_state *state = tevent_req_data(
104
0
    req, struct cli_session_request_state);
105
0
  ssize_t ret;
106
0
  int err;
107
108
0
  ret = writev_recv(subreq, &err);
109
0
  TALLOC_FREE(subreq);
110
0
  if (ret == -1) {
111
0
    tevent_req_error(req, err);
112
0
    return;
113
0
  }
114
0
  subreq = read_smb_send(state, state->ev, state->sock);
115
0
  if (tevent_req_nomem(subreq, req)) {
116
0
    return;
117
0
  }
118
0
  tevent_req_set_callback(subreq, cli_session_request_recvd, req);
119
0
}
120
121
static void cli_session_request_recvd(struct tevent_req *subreq)
122
0
{
123
0
  struct tevent_req *req = tevent_req_callback_data(
124
0
    subreq, struct tevent_req);
125
0
  struct cli_session_request_state *state = tevent_req_data(
126
0
    req, struct cli_session_request_state);
127
0
  uint8_t *buf;
128
0
  ssize_t ret;
129
0
  int err;
130
131
0
  ret = read_smb_recv(subreq, talloc_tos(), &buf, &err);
132
0
  TALLOC_FREE(subreq);
133
134
0
  if (ret < 4) {
135
0
    ret = -1;
136
0
    err = EIO;
137
0
  }
138
0
  if (ret == -1) {
139
0
    tevent_req_error(req, err);
140
0
    return;
141
0
  }
142
  /*
143
   * In case of an error there is more information in the data
144
   * portion according to RFC1002. We're not subtle enough to
145
   * respond to the different error conditions, so drop the
146
   * error info here.
147
   */
148
0
  state->nb_session_response = CVAL(buf, 0);
149
0
  tevent_req_done(req);
150
0
}
151
152
static bool cli_session_request_recv(struct tevent_req *req, int *err, uint8_t *resp)
153
0
{
154
0
  struct cli_session_request_state *state = tevent_req_data(
155
0
    req, struct cli_session_request_state);
156
157
0
  if (tevent_req_is_unix_error(req, err)) {
158
0
    return false;
159
0
  }
160
0
  *resp = state->nb_session_response;
161
0
  return true;
162
0
}
163
164
struct nb_connect_state {
165
  struct tevent_context *ev;
166
  const struct sockaddr_storage *addr;
167
  const char *called_name;
168
  int sock;
169
  struct tevent_req *session_subreq;
170
  struct nmb_name called;
171
  struct nmb_name calling;
172
};
173
174
static void nb_connect_cleanup(struct tevent_req *req,
175
             enum tevent_req_state req_state);
176
static void nb_connect_connected(struct tevent_req *subreq);
177
static void nb_connect_done(struct tevent_req *subreq);
178
179
static struct tevent_req *nb_connect_send(TALLOC_CTX *mem_ctx,
180
            struct tevent_context *ev,
181
            const struct sockaddr_storage *addr,
182
            const char *called_name,
183
            int called_type,
184
            const char *calling_name,
185
            int calling_type,
186
            uint16_t port)
187
0
{
188
0
  struct tevent_req *req, *subreq;
189
0
  struct nb_connect_state *state;
190
191
0
  req = tevent_req_create(mem_ctx, &state, struct nb_connect_state);
192
0
  if (req == NULL) {
193
0
    return NULL;
194
0
  }
195
0
  state->ev = ev;
196
0
  state->called_name = called_name;
197
0
  state->addr = addr;
198
199
0
  state->sock = -1;
200
0
  make_nmb_name(&state->called, called_name, called_type);
201
0
  make_nmb_name(&state->calling, calling_name, calling_type);
202
203
0
  tevent_req_set_cleanup_fn(req, nb_connect_cleanup);
204
205
0
  subreq = open_socket_out_send(state,
206
0
              ev,
207
0
              IPPROTO_TCP,
208
0
              addr,
209
0
              port,
210
0
              5000);
211
0
  if (tevent_req_nomem(subreq, req)) {
212
0
    return tevent_req_post(req, ev);
213
0
  }
214
0
  tevent_req_set_callback(subreq, nb_connect_connected, req);
215
0
  return req;
216
0
}
217
218
static void nb_connect_cleanup(struct tevent_req *req,
219
             enum tevent_req_state req_state)
220
0
{
221
0
  struct nb_connect_state *state = tevent_req_data(
222
0
    req, struct nb_connect_state);
223
224
  /*
225
   * we need to free a pending request before closing the
226
   * socket, see bug #11141
227
   */
228
0
  TALLOC_FREE(state->session_subreq);
229
230
0
  if (req_state == TEVENT_REQ_DONE) {
231
    /*
232
     * we keep the socket open for the caller to use
233
     */
234
0
    return;
235
0
  }
236
237
0
  if (state->sock != -1) {
238
0
    close(state->sock);
239
0
    state->sock = -1;
240
0
  }
241
242
0
  return;
243
0
}
244
245
static void nb_connect_connected(struct tevent_req *subreq)
246
0
{
247
0
  struct tevent_req *req = tevent_req_callback_data(
248
0
    subreq, struct tevent_req);
249
0
  struct nb_connect_state *state = tevent_req_data(
250
0
    req, struct nb_connect_state);
251
0
  NTSTATUS status;
252
253
0
  status = open_socket_out_recv(subreq, &state->sock);
254
0
  TALLOC_FREE(subreq);
255
0
  if (tevent_req_nterror(req, status)) {
256
0
    return;
257
0
  }
258
0
  subreq = cli_session_request_send(state, state->ev, state->sock,
259
0
            &state->called, &state->calling);
260
0
  if (tevent_req_nomem(subreq, req)) {
261
0
    return;
262
0
  }
263
0
  tevent_req_set_callback(subreq, nb_connect_done, req);
264
0
  state->session_subreq = subreq;
265
0
}
266
267
static void nb_connect_done(struct tevent_req *subreq)
268
0
{
269
0
  struct tevent_req *req = tevent_req_callback_data(
270
0
    subreq, struct tevent_req);
271
0
  struct nb_connect_state *state = tevent_req_data(
272
0
    req, struct nb_connect_state);
273
0
  bool ret;
274
0
  int err;
275
0
  uint8_t resp;
276
277
0
  state->session_subreq = NULL;
278
279
0
  ret = cli_session_request_recv(subreq, &err, &resp);
280
0
  TALLOC_FREE(subreq);
281
0
  if (!ret) {
282
0
    tevent_req_nterror(req, map_nt_error_from_unix(err));
283
0
    return;
284
0
  }
285
286
  /*
287
   * RFC1002: 0x82 - POSITIVE SESSION RESPONSE
288
   */
289
290
0
  if (resp != 0x82) {
291
    /*
292
     * The server did not like our session request
293
     */
294
0
    close(state->sock);
295
0
    state->sock = -1;
296
297
0
    if (strequal(state->called_name, "*SMBSERVER")) {
298
      /*
299
       * Here we could try a name status request and
300
       * use the first 0x20 type name.
301
       */
302
0
      tevent_req_nterror(
303
0
        req, NT_STATUS_RESOURCE_NAME_NOT_FOUND);
304
0
      return;
305
0
    }
306
307
    /*
308
     * We could be subtle and distinguish between
309
     * different failure modes, but what we do here
310
     * instead is just retry with *SMBSERVER type 0x20.
311
     */
312
0
    state->called_name = "*SMBSERVER";
313
0
    make_nmb_name(&state->called, state->called_name, 0x20);
314
315
0
    subreq = open_socket_out_send(state,
316
0
                state->ev,
317
0
                IPPROTO_TCP,
318
0
                state->addr,
319
0
                NBT_SMB_PORT,
320
0
                5000);
321
0
    if (tevent_req_nomem(subreq, req)) {
322
0
      return;
323
0
    }
324
0
    tevent_req_set_callback(subreq, nb_connect_connected, req);
325
0
    return;
326
0
  }
327
328
0
  tevent_req_done(req);
329
0
  return;
330
0
}
331
332
static NTSTATUS nb_connect_recv(struct tevent_req *req, int *sock)
333
0
{
334
0
  struct nb_connect_state *state = tevent_req_data(
335
0
    req, struct nb_connect_state);
336
0
  NTSTATUS status;
337
338
0
  if (tevent_req_is_nterror(req, &status)) {
339
0
    tevent_req_received(req);
340
0
    return status;
341
0
  }
342
0
  *sock = state->sock;
343
0
  state->sock = -1;
344
0
  tevent_req_received(req);
345
0
  return NT_STATUS_OK;
346
0
}
347
348
struct smb_transports smbsock_transports_from_port(uint16_t port)
349
0
{
350
0
  struct smb_transports ts = { .num_transports = 0, };
351
352
0
  if (port == 0) {
353
0
    ts = smb_transports_parse("client smb transports",
354
0
            lp_client_smb_transports());
355
0
  } else if (port == NBT_SMB_PORT) {
356
0
    struct smb_transport *t = &ts.transports[0];
357
358
0
    *t = (struct smb_transport) {
359
0
      .type = SMB_TRANSPORT_TYPE_NBT,
360
0
      .port = NBT_SMB_PORT,
361
0
    };
362
0
    ts.num_transports = 1;
363
0
  } else {
364
0
    struct smb_transport *t = &ts.transports[0];
365
366
0
    *t = (struct smb_transport) {
367
0
      .type = SMB_TRANSPORT_TYPE_TCP,
368
0
      .port = port,
369
0
    };
370
0
    ts.num_transports = 1;
371
0
  }
372
373
0
  return ts;
374
0
}
375
376
bool smbsock_connect_require_bsd_socket;
377
378
struct smbsock_connect_substate {
379
  struct tevent_req *req;
380
  size_t idx;
381
  struct smb_transport transport;
382
  struct tevent_req *subreq;
383
  int sockfd;
384
  struct samba_sockaddr laddr;
385
  struct samba_sockaddr raddr;
386
};
387
388
struct smbsock_connect_state {
389
  struct tevent_context *ev;
390
  const struct sockaddr_storage *addr;
391
  const char *target_name;
392
  const char *called_name;
393
  uint8_t called_type;
394
  const char *calling_name;
395
  uint8_t calling_type;
396
  struct tstream_tls_params *quic_tlsp;
397
  bool allow_ngtcp2;
398
  bool force_ngtcp2;
399
  struct tevent_req *wake_subreq;
400
  uint8_t num_substates;
401
  uint8_t submit_idx;
402
  uint8_t num_pending;
403
  struct smbsock_connect_substate substates[SMB_TRANSPORTS_MAX_TRANSPORTS];
404
  struct smbXcli_transport *transport;
405
  struct smbXcli_transport *(*create_bsd_transport)(
406
            TALLOC_CTX *mem_ctx,
407
            int *fd,
408
            const struct smb_transport *tp);
409
};
410
411
static void smbsock_connect_cleanup(struct tevent_req *req,
412
            enum tevent_req_state req_state);
413
static bool smbsock_connect_submit_next(struct tevent_req *req);
414
static void smbsock_connect_waited(struct tevent_req *subreq);
415
static void smbsock_connect_nbt_connected(struct tevent_req *subreq);
416
static void smbsock_connect_tcp_connected(struct tevent_req *subreq);
417
#ifdef HAVE_LIBQUIC
418
static void smbsock_connect_quic_connected(struct tevent_req *subreq);
419
static void smbsock_connect_quic_ready(struct tevent_req *subreq);
420
#endif /* HAVE_LIBQUIC */
421
#ifdef HAVE_LIBNGTCP2
422
static NTSTATUS smbsock_connect_ngtcp2_udp_sock(
423
      const struct sockaddr_storage *addr,
424
      uint16_t port,
425
      int *_sockfd,
426
      struct samba_sockaddr *laddr,
427
      struct samba_sockaddr *raddr);
428
static void smbsock_connect_ngtcp2_ready(struct tevent_req *subreq);
429
#endif /* HAVE_LIBNGTCP2 */
430
431
struct tevent_req *smbsock_connect_send(TALLOC_CTX *mem_ctx,
432
          struct tevent_context *ev,
433
          struct loadparm_context *lp_ctx,
434
          const struct sockaddr_storage *addr,
435
          const struct smb_transports *transports,
436
          const char *called_name,
437
          int called_type,
438
          const char *calling_name,
439
          int calling_type)
440
0
{
441
0
  struct tevent_req *req;
442
0
  struct smbsock_connect_state *state;
443
0
  bool force_bsd_tstream = false;
444
0
  uint8_t num_unsupported = 0;
445
0
  struct smb_transports ts = *transports;
446
0
  uint8_t ti;
447
0
  bool ok;
448
0
  bool request_quic = false;
449
0
  bool try_quic = false;
450
451
0
  req = tevent_req_create(mem_ctx, &state, struct smbsock_connect_state);
452
0
  if (req == NULL) {
453
0
    return NULL;
454
0
  }
455
0
  state->ev = ev;
456
0
  state->addr = addr;
457
0
  state->target_name = called_name;
458
0
  state->called_name =
459
0
    (called_name != NULL) ? called_name : "*SMBSERVER";
460
0
  state->called_type =
461
0
    (called_type != -1) ? called_type : 0x20;
462
0
  state->calling_name =
463
0
    (calling_name != NULL) ? calling_name : lp_netbios_name();
464
0
  state->calling_type =
465
0
    (calling_type != -1) ? calling_type : 0x00;
466
467
0
  force_bsd_tstream = lpcfg_parm_bool(lp_ctx,
468
0
              NULL,
469
0
              "client smb transport",
470
0
              "force_bsd_tstream",
471
0
              false);
472
0
  if (force_bsd_tstream) {
473
0
    state->create_bsd_transport = smbXcli_transport_bsd_tstream;
474
0
  } else {
475
0
    state->create_bsd_transport = smbXcli_transport_bsd;
476
0
  }
477
478
0
  tevent_req_set_cleanup_fn(req, smbsock_connect_cleanup);
479
480
0
  SMB_ASSERT(ts.num_transports <= ARRAY_SIZE(state->substates));
481
482
0
  for (ti = 0; ti < ts.num_transports; ti++) {
483
0
    const struct smb_transport *t = &ts.transports[ti];
484
485
0
    if (t->type != SMB_TRANSPORT_TYPE_QUIC) {
486
0
      continue;
487
0
    }
488
489
0
    if (state->target_name != NULL) {
490
0
      request_quic = true;
491
0
      break;
492
0
    }
493
0
  }
494
495
0
  if (request_quic) {
496
0
    NTSTATUS status;
497
498
0
    status = tstream_tls_params_client_lpcfg(state,
499
0
               lp_ctx,
500
0
               state->target_name,
501
0
               &state->quic_tlsp);
502
0
    if (tevent_req_nterror(req, status)) {
503
0
      return tevent_req_post(req, ev);
504
0
    }
505
506
0
    status = tstream_tls_params_quic_prepare(state->quic_tlsp);
507
0
    if (tevent_req_nterror(req, status)) {
508
0
      return tevent_req_post(req, ev);
509
0
    }
510
511
0
    try_quic = tstream_tls_params_quic_enabled(state->quic_tlsp);
512
513
0
    state->allow_ngtcp2 = lpcfg_parm_bool(lp_ctx,
514
0
                  NULL,
515
0
                  "client smb transport",
516
0
                  "allow_ngtcp2_quic",
517
0
                  try_quic);
518
0
    state->force_ngtcp2 = lpcfg_parm_bool(lp_ctx,
519
0
                  NULL,
520
0
                  "client smb transport",
521
0
                  "force_ngtcp2_quic",
522
0
                  false);
523
0
  }
524
525
0
  if (smbsock_connect_require_bsd_socket) {
526
    /*
527
     * This is libsmbclient in use
528
     * there's no periodic connection
529
     * monitoring, so we can't use
530
     * the ngtcp2 over udp quic support.
531
     */
532
0
    state->allow_ngtcp2 = false;
533
0
  }
534
535
0
  for (ti = 0; ti < ts.num_transports; ti++) {
536
0
    const struct smb_transport *t = &ts.transports[ti];
537
0
    struct smbsock_connect_substate *s =
538
0
      &state->substates[state->num_substates];
539
540
0
    switch (t->type) {
541
0
    case SMB_TRANSPORT_TYPE_UNKNOWN:
542
      /*
543
       * Should never happen
544
       */
545
0
      smb_panic(__location__);
546
0
      continue;
547
0
    case SMB_TRANSPORT_TYPE_NBT:
548
0
      if (lp_disable_netbios()) {
549
0
        num_unsupported += 1;
550
0
        continue;
551
0
      }
552
0
      break;
553
0
    case SMB_TRANSPORT_TYPE_TCP:
554
0
      break;
555
0
    case SMB_TRANSPORT_TYPE_QUIC:
556
0
      if (try_quic) {
557
0
        break;
558
0
      }
559
560
      /*
561
       * Not supported yet or no
562
       * called_name as peer name
563
       * available.
564
       */
565
0
      continue;
566
0
    }
567
568
0
    s->req = req;
569
0
    s->idx = state->num_substates;
570
0
    s->transport = *t;
571
0
    s->sockfd = -1;
572
573
0
    state->num_substates += 1;
574
0
  }
575
576
0
  if (state->num_substates == 0 && num_unsupported != 0) {
577
0
    tevent_req_nterror(req, NT_STATUS_NOT_SUPPORTED);
578
0
    return tevent_req_post(req, ev);
579
0
  }
580
581
0
  if (state->num_substates == 0) {
582
0
    tevent_req_nterror(req, NT_STATUS_PORT_NOT_SET);
583
0
    return tevent_req_post(req, ev);
584
0
  }
585
586
0
  ok = smbsock_connect_submit_next(req);
587
0
  if (!ok) {
588
0
    return tevent_req_post(req, ev);
589
0
  }
590
591
0
  if (state->submit_idx == state->num_substates) {
592
    /* only one transport */
593
0
    return req;
594
0
  }
595
596
  /*
597
   * After 5 msecs, fire all remaining requests
598
   */
599
0
  state->wake_subreq = tevent_wakeup_send(state,
600
0
            ev,
601
0
            timeval_current_ofs(0, 5000));
602
0
  if (tevent_req_nomem(state->wake_subreq, req)) {
603
0
    return tevent_req_post(req, ev);
604
0
  }
605
0
  tevent_req_set_callback(state->wake_subreq,
606
0
        smbsock_connect_waited,
607
0
        req);
608
609
0
  return req;
610
0
}
611
612
static void smbsock_connect_cleanup(struct tevent_req *req,
613
            enum tevent_req_state req_state)
614
0
{
615
0
  struct smbsock_connect_state *state = tevent_req_data(
616
0
    req, struct smbsock_connect_state);
617
0
  uint8_t si;
618
619
  /*
620
   * we need to free a pending request before closing the
621
   * socket, see bug #11141
622
   */
623
0
  TALLOC_FREE(state->wake_subreq);
624
0
  for (si = 0; si < state->num_substates; si++) {
625
0
    struct smbsock_connect_substate *s =
626
0
      &state->substates[si];
627
628
0
    TALLOC_FREE(s->subreq);
629
0
    if (s->sockfd != -1) {
630
0
      close(s->sockfd);
631
0
      s->sockfd = -1;
632
0
    }
633
0
  }
634
635
0
  if (req_state == TEVENT_REQ_DONE) {
636
    /*
637
     * we keep the socket open for the caller to use
638
     */
639
0
    return;
640
0
  }
641
642
0
  TALLOC_FREE(state->transport);
643
644
0
  return;
645
0
}
646
647
static bool smbsock_connect_submit_next(struct tevent_req *req)
648
0
{
649
0
  struct smbsock_connect_state *state =
650
0
    tevent_req_data(req,
651
0
    struct smbsock_connect_state);
652
0
  struct smbsock_connect_substate *s =
653
0
    &state->substates[state->submit_idx];
654
#ifdef HAVE_LIBNGTCP2
655
  NTSTATUS status;
656
#endif /* HAVE_LIBNGTCP2 */
657
658
0
  SMB_ASSERT(state->submit_idx < state->num_substates);
659
660
0
  switch (s->transport.type) {
661
0
  case SMB_TRANSPORT_TYPE_UNKNOWN:
662
0
    break;
663
664
0
  case SMB_TRANSPORT_TYPE_NBT:
665
0
    s->subreq = nb_connect_send(state,
666
0
              state->ev,
667
0
              state->addr,
668
0
              state->called_name,
669
0
              state->called_type,
670
0
              state->calling_name,
671
0
              state->calling_type,
672
0
              s->transport.port);
673
0
    if (tevent_req_nomem(s->subreq, req)) {
674
0
      return false;
675
0
    }
676
0
    tevent_req_set_callback(s->subreq,
677
0
          smbsock_connect_nbt_connected,
678
0
          s);
679
0
    break;
680
681
0
  case SMB_TRANSPORT_TYPE_TCP:
682
0
    s->subreq = open_socket_out_send(state,
683
0
             state->ev,
684
0
             IPPROTO_TCP,
685
0
             state->addr,
686
0
             s->transport.port,
687
0
             5000);
688
0
    if (tevent_req_nomem(s->subreq, req)) {
689
0
      return false;
690
0
    }
691
0
    tevent_req_set_callback(s->subreq,
692
0
          smbsock_connect_tcp_connected,
693
0
          s);
694
0
    break;
695
696
0
  case SMB_TRANSPORT_TYPE_QUIC:
697
#ifdef HAVE_LIBQUIC
698
    if (state->force_ngtcp2) {
699
      goto try_ngtcp2;
700
    }
701
702
    s->subreq = open_socket_out_send(state,
703
             state->ev,
704
             IPPROTO_QUIC,
705
             state->addr,
706
             s->transport.port,
707
             5000);
708
    if (tevent_req_nomem(s->subreq, req)) {
709
      return false;
710
    }
711
    tevent_req_set_callback(s->subreq,
712
          smbsock_connect_quic_connected,
713
          s);
714
    break;
715
try_ngtcp2:
716
#define __HAVE_LIBQUIC_OR_LIBNGTCP2 1
717
#endif /* HAVE_LIBQUIC */
718
#ifdef HAVE_LIBNGTCP2
719
    if (!state->allow_ngtcp2) {
720
      tevent_req_nterror(req, NT_STATUS_PROTOCOL_NOT_SUPPORTED);
721
      return false;
722
    }
723
724
    status = smbsock_connect_ngtcp2_udp_sock(state->addr,
725
               s->transport.port,
726
               &s->sockfd,
727
               &s->laddr,
728
               &s->raddr);
729
    if (tevent_req_nterror(req, status)) {
730
      return false;
731
    }
732
733
    s->subreq = tstream_tls_ngtcp2_connect_send(state,
734
                  state->ev,
735
                  state->quic_tlsp,
736
                  5000,
737
                  "smb",
738
                  &s->sockfd);
739
    if (tevent_req_nomem(s->subreq, req)) {
740
      return false;
741
    }
742
    tevent_req_set_callback(s->subreq,
743
          smbsock_connect_ngtcp2_ready,
744
          s);
745
    break;
746
#define __HAVE_LIBQUIC_OR_LIBNGTCP2 1
747
#endif /* HAVE_LIBNGTCP2 */
748
0
#ifndef __HAVE_LIBQUIC_OR_LIBNGTCP2
749
    /*
750
     * Not supported yet, should already be
751
     * checked above.
752
     */
753
0
    smb_panic(__location__);
754
0
    break;
755
0
#endif /* ! __HAVE_LIBQUIC_OR_LIBNGTCP2 */
756
0
  }
757
758
0
  if (s->subreq == NULL) {
759
0
    tevent_req_nterror(req, NT_STATUS_INTERNAL_ERROR);
760
0
    return false;
761
0
  }
762
763
0
  state->num_pending += 1;
764
0
  state->submit_idx += 1;
765
0
  if (state->submit_idx == state->num_substates) {
766
0
    TALLOC_FREE(state->wake_subreq);
767
0
  }
768
769
0
  return true;
770
0
}
771
772
static void smbsock_connect_waited(struct tevent_req *subreq)
773
0
{
774
0
  struct tevent_req *req = tevent_req_callback_data(
775
0
    subreq, struct tevent_req);
776
0
  struct smbsock_connect_state *state = tevent_req_data(
777
0
    req, struct smbsock_connect_state);
778
0
  bool ok;
779
780
0
  SMB_ASSERT(state->wake_subreq == subreq);
781
0
  state->wake_subreq = NULL;
782
783
0
  ok = tevent_wakeup_recv(subreq);
784
0
  TALLOC_FREE(subreq);
785
0
  if (!ok) {
786
0
    tevent_req_nterror(req, NT_STATUS_INTERNAL_ERROR);
787
0
    return;
788
0
  }
789
790
0
  SMB_ASSERT(state->submit_idx < state->num_substates);
791
792
0
  while (state->submit_idx < state->num_substates) {
793
0
    ok = smbsock_connect_submit_next(req);
794
0
    if (!ok) {
795
0
      return;
796
0
    }
797
0
  }
798
0
}
799
800
static void smbsock_connect_nbt_connected(struct tevent_req *subreq)
801
0
{
802
0
  struct smbsock_connect_substate *s =
803
0
    (struct smbsock_connect_substate *)
804
0
    tevent_req_callback_data_void(subreq);
805
0
  struct tevent_req *req = s->req;
806
0
  struct smbsock_connect_state *state =
807
0
    tevent_req_data(req,
808
0
    struct smbsock_connect_state);
809
0
  NTSTATUS status;
810
811
0
  SMB_ASSERT(s->subreq == subreq);
812
0
  s->subreq = NULL;
813
0
  SMB_ASSERT(state->num_pending > 0);
814
0
  state->num_pending -= 1;
815
816
0
  status = nb_connect_recv(subreq, &s->sockfd);
817
0
  TALLOC_FREE(subreq);
818
0
  if (NT_STATUS_IS_OK(status)) {
819
    /*
820
     * smbsock_connect_cleanup()
821
     * will free all other subreqs
822
     */
823
0
    set_socket_options(s->sockfd, lp_socket_options());
824
0
    state->transport = state->create_bsd_transport(state,
825
0
                     &s->sockfd,
826
0
                     &s->transport);
827
0
    if (tevent_req_nomem(state->transport, req)) {
828
0
      return;
829
0
    }
830
0
    tevent_req_done(req);
831
0
    return;
832
0
  }
833
834
  /*
835
   * Do nothing, wait for the remaining
836
   * requests to come here.
837
   *
838
   * Submit the next requests if there
839
   * are unsubmitted requests remaining.
840
   */
841
0
  if (state->submit_idx < state->num_substates) {
842
0
    bool ok;
843
844
0
    ok = smbsock_connect_submit_next(req);
845
0
    if (!ok) {
846
0
      return;
847
0
    }
848
0
  }
849
850
0
  if (state->num_pending == 0) {
851
    /*
852
     * All requests failed
853
     *
854
     * smbsock_connect_cleanup()
855
     * will free all other subreqs
856
     */
857
0
    tevent_req_nterror(req, status);
858
0
    return;
859
0
  }
860
0
}
861
862
static void smbsock_connect_tcp_connected(struct tevent_req *subreq)
863
0
{
864
0
  struct smbsock_connect_substate *s =
865
0
    (struct smbsock_connect_substate *)
866
0
    tevent_req_callback_data_void(subreq);
867
0
  struct tevent_req *req = s->req;
868
0
  struct smbsock_connect_state *state =
869
0
    tevent_req_data(req,
870
0
    struct smbsock_connect_state);
871
0
  NTSTATUS status;
872
873
0
  SMB_ASSERT(s->subreq == subreq);
874
0
  s->subreq = NULL;
875
0
  SMB_ASSERT(state->num_pending > 0);
876
0
  state->num_pending -= 1;
877
878
0
  status = open_socket_out_recv(subreq, &s->sockfd);
879
0
  TALLOC_FREE(subreq);
880
0
  if (NT_STATUS_IS_OK(status)) {
881
    /*
882
     * smbsock_connect_cleanup()
883
     * will free all other subreqs
884
     */
885
0
    set_socket_options(s->sockfd, lp_socket_options());
886
0
    state->transport = state->create_bsd_transport(state,
887
0
                     &s->sockfd,
888
0
                     &s->transport);
889
0
    if (tevent_req_nomem(state->transport, req)) {
890
0
      return;
891
0
    }
892
0
    tevent_req_done(req);
893
0
    return;
894
0
  }
895
896
  /*
897
   * Do nothing, wait for the remaining
898
   * requests to come here.
899
   *
900
   * Submit the next requests if there
901
   * are unsubmitted requests remaining.
902
   */
903
0
  if (state->submit_idx < state->num_substates) {
904
0
    bool ok;
905
906
0
    ok = smbsock_connect_submit_next(req);
907
0
    if (!ok) {
908
0
      return;
909
0
    }
910
0
  }
911
912
0
  if (state->num_pending == 0) {
913
    /*
914
     * All requests failed
915
     *
916
     * smbsock_connect_cleanup()
917
     * will free all other subreqs
918
     */
919
0
    tevent_req_nterror(req, status);
920
0
    return;
921
0
  }
922
0
}
923
924
#ifdef HAVE_LIBQUIC
925
static void smbsock_connect_quic_connected(struct tevent_req *subreq)
926
{
927
  struct smbsock_connect_substate *s =
928
    (struct smbsock_connect_substate *)
929
    tevent_req_callback_data_void(subreq);
930
  struct tevent_req *req = s->req;
931
  struct smbsock_connect_state *state =
932
    tevent_req_data(req,
933
    struct smbsock_connect_state);
934
  NTSTATUS status;
935
936
  SMB_ASSERT(s->subreq == subreq);
937
  s->subreq = NULL;
938
  SMB_ASSERT(state->num_pending > 0);
939
  state->num_pending -= 1;
940
941
  status = open_socket_out_recv(subreq, &s->sockfd);
942
  TALLOC_FREE(subreq);
943
#ifdef HAVE_LIBNGTCP2
944
  if (NT_STATUS_EQUAL(status, NT_STATUS_PROTOCOL_NOT_SUPPORTED)) {
945
    /*
946
     * fallback to ngtcp2 over udp sockets
947
     * in order to implement QUIC
948
     */
949
950
    if (!state->allow_ngtcp2) {
951
      goto fail;
952
    }
953
954
    status = smbsock_connect_ngtcp2_udp_sock(state->addr,
955
               s->transport.port,
956
               &s->sockfd,
957
               &s->laddr,
958
               &s->raddr);
959
    if (!NT_STATUS_IS_OK(status)) {
960
      goto fail;
961
    }
962
963
    s->subreq = tstream_tls_ngtcp2_connect_send(state,
964
                  state->ev,
965
                  state->quic_tlsp,
966
                  5000,
967
                  "smb",
968
                  &s->sockfd);
969
    if (s->subreq == NULL) {
970
      status = NT_STATUS_NO_MEMORY;
971
      goto fail;
972
    }
973
    tevent_req_set_callback(s->subreq,
974
          smbsock_connect_ngtcp2_ready,
975
          s);
976
    state->num_pending += 1;
977
    return;
978
  }
979
#endif /* HAVE_LIBNGTCP2 */
980
  if (NT_STATUS_IS_OK(status)) {
981
    s->subreq = tstream_tls_quic_handshake_send(state,
982
                  state->ev,
983
                  state->quic_tlsp,
984
                  false, /* is_server */
985
                  5000,
986
                  "smb",
987
                  s->sockfd);
988
    if (s->subreq == NULL) {
989
      status = NT_STATUS_NO_MEMORY;
990
      goto fail;
991
    }
992
    tevent_req_set_callback(s->subreq,
993
          smbsock_connect_quic_ready,
994
          s);
995
    state->num_pending += 1;
996
    return;
997
  }
998
999
fail:
1000
  /*
1001
   * Do nothing, wait for the remaining
1002
   * requests to come here.
1003
   *
1004
   * Submit the next requests if there
1005
   * are unsubmitted requests remaining.
1006
   */
1007
  if (state->submit_idx < state->num_substates) {
1008
    bool ok;
1009
1010
    ok = smbsock_connect_submit_next(req);
1011
    if (!ok) {
1012
      return;
1013
    }
1014
  }
1015
1016
  if (state->num_pending == 0) {
1017
    /*
1018
     * All requests failed
1019
     *
1020
     * smbsock_connect_cleanup()
1021
     * will free all other subreqs
1022
     */
1023
    tevent_req_nterror(req, status);
1024
    return;
1025
  }
1026
}
1027
1028
static void smbsock_connect_quic_ready(struct tevent_req *subreq)
1029
{
1030
  struct smbsock_connect_substate *s =
1031
    (struct smbsock_connect_substate *)
1032
    tevent_req_callback_data_void(subreq);
1033
  struct tevent_req *req = s->req;
1034
  struct smbsock_connect_state *state =
1035
    tevent_req_data(req,
1036
    struct smbsock_connect_state);
1037
  NTSTATUS status;
1038
1039
  SMB_ASSERT(s->subreq == subreq);
1040
  s->subreq = NULL;
1041
  SMB_ASSERT(state->num_pending > 0);
1042
  state->num_pending -= 1;
1043
1044
  status = tstream_tls_quic_handshake_recv(subreq);
1045
  TALLOC_FREE(subreq);
1046
  if (NT_STATUS_IS_OK(status)) {
1047
    /*
1048
     * smbsock_connect_cleanup()
1049
     * will free all other subreqs
1050
     */
1051
    state->transport = state->create_bsd_transport(state,
1052
                     &s->sockfd,
1053
                     &s->transport);
1054
    if (tevent_req_nomem(state->transport, req)) {
1055
      return;
1056
    }
1057
    tevent_req_done(req);
1058
    return;
1059
  }
1060
1061
  /*
1062
   * Do nothing, wait for the remaining
1063
   * requests to come here.
1064
   *
1065
   * Submit the next requests if there
1066
   * are unsubmitted requests remaining.
1067
   */
1068
  if (state->submit_idx < state->num_substates) {
1069
    bool ok;
1070
1071
    ok = smbsock_connect_submit_next(req);
1072
    if (!ok) {
1073
      return;
1074
    }
1075
  }
1076
1077
  if (state->num_pending == 0) {
1078
    /*
1079
     * All requests failed
1080
     *
1081
     * smbsock_connect_cleanup()
1082
     * will free all other subreqs
1083
     */
1084
    tevent_req_nterror(req, status);
1085
    return;
1086
  }
1087
}
1088
#endif /* HAVE_LIBQUIC */
1089
1090
#ifdef HAVE_LIBNGTCP2
1091
static NTSTATUS smbsock_connect_ngtcp2_udp_sock(
1092
      const struct sockaddr_storage *_addr,
1093
      uint16_t port,
1094
      int *_sockfd,
1095
      struct samba_sockaddr *laddr,
1096
      struct samba_sockaddr *raddr)
1097
{
1098
  int sockfd = -1;
1099
  int ret;
1100
1101
  *laddr = (struct samba_sockaddr) {
1102
    .sa_socklen = sizeof(laddr->u),
1103
  };
1104
  *raddr = (struct samba_sockaddr) {
1105
    .sa_socklen = sizeof(*_addr),
1106
    .u = {
1107
      .ss = *_addr,
1108
    },
1109
  };
1110
1111
  sockfd = socket(raddr->u.sa.sa_family, SOCK_DGRAM, IPPROTO_UDP);
1112
  if (sockfd == -1) {
1113
    return map_nt_error_from_unix_common(errno);
1114
  }
1115
1116
  switch (raddr->u.sa.sa_family) {
1117
  case AF_INET:
1118
    raddr->sa_socklen = sizeof(struct sockaddr_in);
1119
    break;
1120
  case AF_INET6:
1121
    raddr->sa_socklen = sizeof(struct sockaddr_in6);
1122
    break;
1123
  }
1124
1125
  set_sockaddr_port(&raddr->u.sa, port);
1126
1127
  ret = connect(sockfd, &raddr->u.sa, raddr->sa_socklen);
1128
  if (ret == -1) {
1129
    int saved_errno = errno;
1130
    close(sockfd);
1131
    return map_nt_error_from_unix_common(saved_errno);
1132
  }
1133
1134
  ret = getsockname(sockfd, &laddr->u.sa, &laddr->sa_socklen);
1135
  if (ret == -1) {
1136
    int saved_errno = errno;
1137
    close(sockfd);
1138
    return map_nt_error_from_unix_common(saved_errno);
1139
  }
1140
1141
  *_sockfd = sockfd;
1142
  return NT_STATUS_OK;
1143
}
1144
1145
static void smbsock_connect_ngtcp2_ready(struct tevent_req *subreq)
1146
{
1147
  struct smbsock_connect_substate *s =
1148
    (struct smbsock_connect_substate *)
1149
    tevent_req_callback_data_void(subreq);
1150
  struct tevent_req *req = s->req;
1151
  struct smbsock_connect_state *state =
1152
    tevent_req_data(req,
1153
    struct smbsock_connect_state);
1154
  NTSTATUS status;
1155
  struct tstream_context *tstream = NULL;
1156
  int ret;
1157
  int error;
1158
1159
  SMB_ASSERT(s->subreq == subreq);
1160
  s->subreq = NULL;
1161
  SMB_ASSERT(state->num_pending > 0);
1162
  state->num_pending -= 1;
1163
1164
  ret = tstream_tls_ngtcp2_connect_recv(subreq,
1165
                &error,
1166
                state,
1167
                &tstream);
1168
  TALLOC_FREE(subreq);
1169
  if (ret == 0) {
1170
    /*
1171
     * smbsock_connect_cleanup()
1172
     * will free all other subreqs
1173
     */
1174
    state->transport = smbXcli_transport_tstream(state,
1175
                   &tstream,
1176
                   &s->laddr,
1177
                   &s->raddr,
1178
                   &s->transport);
1179
    if (tevent_req_nomem(state->transport, req)) {
1180
      return;
1181
    }
1182
    tevent_req_done(req);
1183
    return;
1184
  }
1185
  status = map_nt_error_from_unix_common(error);
1186
1187
  /*
1188
   * Do nothing, wait for the remaining
1189
   * requests to come here.
1190
   *
1191
   * Submit the next requests if there
1192
   * are unsubmitted requests remaining.
1193
   */
1194
  if (state->submit_idx < state->num_substates) {
1195
    bool ok;
1196
1197
    ok = smbsock_connect_submit_next(req);
1198
    if (!ok) {
1199
      return;
1200
    }
1201
  }
1202
1203
  if (state->num_pending == 0) {
1204
    /*
1205
     * All requests failed
1206
     *
1207
     * smbsock_connect_cleanup()
1208
     * will free all other subreqs
1209
     */
1210
    tevent_req_nterror(req, status);
1211
    return;
1212
  }
1213
}
1214
#endif /* HAVE_LIBNGTCP2 */
1215
1216
NTSTATUS smbsock_connect_recv(struct tevent_req *req,
1217
            TALLOC_CTX *mem_ctx,
1218
            struct smbXcli_transport **ptransport)
1219
0
{
1220
0
  struct smbsock_connect_state *state = tevent_req_data(
1221
0
    req, struct smbsock_connect_state);
1222
0
  NTSTATUS status;
1223
1224
0
  if (tevent_req_is_nterror(req, &status)) {
1225
0
    tevent_req_received(req);
1226
0
    return status;
1227
0
  }
1228
0
  *ptransport = talloc_move(mem_ctx, &state->transport);
1229
0
  tevent_req_received(req);
1230
0
  return NT_STATUS_OK;
1231
0
}
1232
1233
NTSTATUS smbsock_connect(const struct sockaddr_storage *addr,
1234
       struct loadparm_context *lp_ctx,
1235
       const struct smb_transports *transports,
1236
       const char *called_name, int called_type,
1237
       const char *calling_name, int calling_type,
1238
       int sec_timeout,
1239
       TALLOC_CTX *mem_ctx,
1240
       struct smbXcli_transport **ptransport)
1241
0
{
1242
0
  TALLOC_CTX *frame = talloc_stackframe();
1243
0
  struct tevent_context *ev;
1244
0
  struct tevent_req *req;
1245
0
  NTSTATUS status = NT_STATUS_NO_MEMORY;
1246
1247
0
  ev = samba_tevent_context_init(frame);
1248
0
  if (ev == NULL) {
1249
0
    goto fail;
1250
0
  }
1251
0
  req = smbsock_connect_send(frame, ev, lp_ctx, addr, transports,
1252
0
           called_name, called_type,
1253
0
           calling_name, calling_type);
1254
0
  if (req == NULL) {
1255
0
    goto fail;
1256
0
  }
1257
0
  if ((sec_timeout != 0) &&
1258
0
      !tevent_req_set_endtime(
1259
0
        req, ev, timeval_current_ofs(sec_timeout, 0))) {
1260
0
    goto fail;
1261
0
  }
1262
0
  if (!tevent_req_poll_ntstatus(req, ev, &status)) {
1263
0
    goto fail;
1264
0
  }
1265
0
  status = smbsock_connect_recv(req, mem_ctx, ptransport);
1266
0
 fail:
1267
0
  TALLOC_FREE(frame);
1268
0
  return status;
1269
0
}
1270
1271
struct smbsock_any_connect_state {
1272
  struct tevent_context *ev;
1273
  struct loadparm_context *lp_ctx;
1274
  const struct sockaddr_storage *addrs;
1275
  const char **called_names;
1276
  int *called_types;
1277
  const char **calling_names;
1278
  int *calling_types;
1279
  size_t num_addrs;
1280
  struct smb_transports transports;
1281
1282
  struct tevent_req **requests;
1283
  size_t num_sent;
1284
  size_t num_received;
1285
1286
  struct smbXcli_transport *transport;
1287
  size_t chosen_index;
1288
};
1289
1290
static void smbsock_any_connect_cleanup(struct tevent_req *req,
1291
          enum tevent_req_state req_state);
1292
static bool smbsock_any_connect_send_next(
1293
  struct tevent_req *req, struct smbsock_any_connect_state *state);
1294
static void smbsock_any_connect_trynext(struct tevent_req *subreq);
1295
static void smbsock_any_connect_connected(struct tevent_req *subreq);
1296
1297
struct tevent_req *smbsock_any_connect_send(TALLOC_CTX *mem_ctx,
1298
              struct tevent_context *ev,
1299
              struct loadparm_context *lp_ctx,
1300
              const struct sockaddr_storage *addrs,
1301
              const char **called_names,
1302
              int *called_types,
1303
              const char **calling_names,
1304
              int *calling_types,
1305
              size_t num_addrs,
1306
              const struct smb_transports *transports)
1307
0
{
1308
0
  struct tevent_req *req, *subreq;
1309
0
  struct smbsock_any_connect_state *state;
1310
1311
0
  req = tevent_req_create(mem_ctx, &state,
1312
0
        struct smbsock_any_connect_state);
1313
0
  if (req == NULL) {
1314
0
    return NULL;
1315
0
  }
1316
0
  state->ev = ev;
1317
0
  state->lp_ctx = lp_ctx;
1318
0
  state->addrs = addrs;
1319
0
  state->num_addrs = num_addrs;
1320
0
  state->called_names = called_names;
1321
0
  state->called_types = called_types;
1322
0
  state->calling_names = calling_names;
1323
0
  state->calling_types = calling_types;
1324
0
  state->transports = *transports;
1325
1326
0
  tevent_req_set_cleanup_fn(req, smbsock_any_connect_cleanup);
1327
1328
0
  if (num_addrs == 0) {
1329
0
    tevent_req_nterror(req, NT_STATUS_INVALID_PARAMETER);
1330
0
    return tevent_req_post(req, ev);
1331
0
  }
1332
1333
0
  state->requests = talloc_zero_array(state, struct tevent_req *,
1334
0
              num_addrs);
1335
0
  if (tevent_req_nomem(state->requests, req)) {
1336
0
    return tevent_req_post(req, ev);
1337
0
  }
1338
0
  if (!smbsock_any_connect_send_next(req, state)) {
1339
0
    return tevent_req_post(req, ev);
1340
0
  }
1341
0
  if (state->num_sent >= state->num_addrs) {
1342
0
    return req;
1343
0
  }
1344
0
  subreq = tevent_wakeup_send(state, ev, timeval_current_ofs(0, 10000));
1345
0
  if (tevent_req_nomem(subreq, req)) {
1346
0
    return tevent_req_post(req, ev);
1347
0
  }
1348
0
  tevent_req_set_callback(subreq, smbsock_any_connect_trynext, req);
1349
0
  return req;
1350
0
}
1351
1352
static void smbsock_any_connect_cleanup(struct tevent_req *req,
1353
          enum tevent_req_state req_state)
1354
0
{
1355
0
  struct smbsock_any_connect_state *state = tevent_req_data(
1356
0
    req, struct smbsock_any_connect_state);
1357
1358
0
  TALLOC_FREE(state->requests);
1359
1360
0
  if (req_state == TEVENT_REQ_DONE) {
1361
    /*
1362
     * Keep the socket open for the caller.
1363
     */
1364
0
    return;
1365
0
  }
1366
1367
0
  TALLOC_FREE(state->transport);
1368
0
}
1369
1370
static void smbsock_any_connect_trynext(struct tevent_req *subreq)
1371
0
{
1372
0
  struct tevent_req *req = tevent_req_callback_data(
1373
0
    subreq, struct tevent_req);
1374
0
  struct smbsock_any_connect_state *state = tevent_req_data(
1375
0
    req, struct smbsock_any_connect_state);
1376
0
  bool ret;
1377
1378
0
  ret = tevent_wakeup_recv(subreq);
1379
0
  TALLOC_FREE(subreq);
1380
0
  if (!ret) {
1381
0
    tevent_req_nterror(req, NT_STATUS_INTERNAL_ERROR);
1382
0
    return;
1383
0
  }
1384
0
  if (!smbsock_any_connect_send_next(req, state)) {
1385
0
    return;
1386
0
  }
1387
0
  if (state->num_sent >= state->num_addrs) {
1388
0
    return;
1389
0
  }
1390
0
  subreq = tevent_wakeup_send(state, state->ev,
1391
0
            tevent_timeval_set(0, 10000));
1392
0
  if (tevent_req_nomem(subreq, req)) {
1393
0
    return;
1394
0
  }
1395
0
  tevent_req_set_callback(subreq, smbsock_any_connect_trynext, req);
1396
0
}
1397
1398
static bool smbsock_any_connect_send_next(
1399
  struct tevent_req *req, struct smbsock_any_connect_state *state)
1400
0
{
1401
0
  struct tevent_req *subreq;
1402
1403
0
  if (state->num_sent >= state->num_addrs) {
1404
0
    tevent_req_nterror(req, NT_STATUS_INTERNAL_ERROR);
1405
0
    return false;
1406
0
  }
1407
0
  subreq = smbsock_connect_send(
1408
0
    state->requests,
1409
0
    state->ev,
1410
0
    state->lp_ctx,
1411
0
    &state->addrs[state->num_sent],
1412
0
    &state->transports,
1413
0
    (state->called_names != NULL)
1414
0
    ? state->called_names[state->num_sent] : NULL,
1415
0
    (state->called_types != NULL)
1416
0
    ? state->called_types[state->num_sent] : -1,
1417
0
    (state->calling_names != NULL)
1418
0
    ? state->calling_names[state->num_sent] : NULL,
1419
0
    (state->calling_types != NULL)
1420
0
    ? state->calling_types[state->num_sent] : -1);
1421
0
  if (tevent_req_nomem(subreq, req)) {
1422
0
    return false;
1423
0
  }
1424
0
  tevent_req_set_callback(subreq, smbsock_any_connect_connected, req);
1425
1426
0
  state->requests[state->num_sent] = subreq;
1427
0
  state->num_sent += 1;
1428
1429
0
  return true;
1430
0
}
1431
1432
static void smbsock_any_connect_connected(struct tevent_req *subreq)
1433
0
{
1434
0
  struct tevent_req *req = tevent_req_callback_data(
1435
0
    subreq, struct tevent_req);
1436
0
  struct smbsock_any_connect_state *state = tevent_req_data(
1437
0
    req, struct smbsock_any_connect_state);
1438
0
  NTSTATUS status;
1439
0
  size_t i;
1440
0
  size_t chosen_index = 0;
1441
1442
0
  for (i=0; i<state->num_sent; i++) {
1443
0
    if (state->requests[i] == subreq) {
1444
0
      chosen_index = i;
1445
0
      break;
1446
0
    }
1447
0
  }
1448
0
  if (i == state->num_sent) {
1449
0
    tevent_req_nterror(req, NT_STATUS_INTERNAL_ERROR);
1450
0
    return;
1451
0
  }
1452
1453
0
  status = smbsock_connect_recv(subreq, state, &state->transport);
1454
1455
0
  TALLOC_FREE(subreq);
1456
0
  state->requests[chosen_index] = NULL;
1457
1458
0
  if (NT_STATUS_IS_OK(status)) {
1459
0
    state->chosen_index = chosen_index;
1460
0
    tevent_req_done(req);
1461
0
    return;
1462
0
  }
1463
1464
0
  state->num_received += 1;
1465
0
  if (state->num_received < state->num_addrs) {
1466
    /*
1467
     * More addrs pending, wait for the others
1468
     */
1469
0
    return;
1470
0
  }
1471
1472
  /*
1473
   * This is the last response, none succeeded.
1474
   */
1475
0
  tevent_req_nterror(req, status);
1476
0
  return;
1477
0
}
1478
1479
NTSTATUS smbsock_any_connect_recv(struct tevent_req *req,
1480
          TALLOC_CTX *mem_ctx,
1481
          struct smbXcli_transport **ptransport,
1482
          size_t *chosen_index)
1483
0
{
1484
0
  struct smbsock_any_connect_state *state = tevent_req_data(
1485
0
    req, struct smbsock_any_connect_state);
1486
0
  NTSTATUS status;
1487
1488
0
  if (tevent_req_is_nterror(req, &status)) {
1489
0
    tevent_req_received(req);
1490
0
    return status;
1491
0
  }
1492
0
  *ptransport = talloc_move(mem_ctx, &state->transport);
1493
0
  if (chosen_index != NULL) {
1494
0
    *chosen_index = state->chosen_index;
1495
0
  }
1496
0
  tevent_req_received(req);
1497
0
  return NT_STATUS_OK;
1498
0
}
1499
1500
NTSTATUS smbsock_any_connect(const struct sockaddr_storage *addrs,
1501
           const char **called_names,
1502
           int *called_types,
1503
           const char **calling_names,
1504
           int *calling_types,
1505
           size_t num_addrs,
1506
           struct loadparm_context *lp_ctx,
1507
           const struct smb_transports *transports,
1508
           int sec_timeout,
1509
           TALLOC_CTX *mem_ctx,
1510
           struct smbXcli_transport **ptransport,
1511
           size_t *chosen_index)
1512
0
{
1513
0
  TALLOC_CTX *frame = talloc_stackframe();
1514
0
  struct tevent_context *ev;
1515
0
  struct tevent_req *req;
1516
0
  NTSTATUS status = NT_STATUS_NO_MEMORY;
1517
1518
0
  ev = samba_tevent_context_init(frame);
1519
0
  if (ev == NULL) {
1520
0
    goto fail;
1521
0
  }
1522
0
  req = smbsock_any_connect_send(frame, ev, lp_ctx, addrs,
1523
0
               called_names, called_types,
1524
0
               calling_names, calling_types,
1525
0
               num_addrs, transports);
1526
0
  if (req == NULL) {
1527
0
    goto fail;
1528
0
  }
1529
0
  if ((sec_timeout != 0) &&
1530
0
      !tevent_req_set_endtime(
1531
0
        req, ev, timeval_current_ofs(sec_timeout, 0))) {
1532
0
    goto fail;
1533
0
  }
1534
0
  if (!tevent_req_poll_ntstatus(req, ev, &status)) {
1535
0
    goto fail;
1536
0
  }
1537
0
  status = smbsock_any_connect_recv(req, mem_ctx, ptransport, chosen_index);
1538
0
 fail:
1539
0
  TALLOC_FREE(frame);
1540
0
  return status;
1541
0
}