Coverage Report

Created: 2026-07-25 07:00

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/samba/lib/tsocket/tsocket_bsd.c
Line
Count
Source
1
/*
2
   Unix SMB/CIFS implementation.
3
4
   Copyright (C) Stefan Metzmacher 2009
5
6
     ** NOTE! The following LGPL license applies to the tsocket
7
     ** library. This does NOT imply that all of Samba is released
8
     ** under the LGPL
9
10
   This library is free software; you can redistribute it and/or
11
   modify it under the terms of the GNU Lesser General Public
12
   License as published by the Free Software Foundation; either
13
   version 3 of the License, or (at your option) any later version.
14
15
   This library is distributed in the hope that it will be useful,
16
   but WITHOUT ANY WARRANTY; without even the implied warranty of
17
   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
18
   Lesser General Public License for more details.
19
20
   You should have received a copy of the GNU Lesser General Public
21
   License along with this library; if not, see <http://www.gnu.org/licenses/>.
22
*/
23
24
#include "replace.h"
25
#include "system/filesys.h"
26
#include "system/network.h"
27
#include "tsocket.h"
28
#include "tsocket_internal.h"
29
#include "lib/util/iov_buf.h"
30
#include "lib/util/blocking.h"
31
#include "lib/util/util_net.h"
32
#include "lib/util/samba_util.h"
33
#include "lib/async_req/async_sock.h"
34
#include "lib/util/smb_strtox.h"
35
36
static int tsocket_bsd_error_from_errno(int ret,
37
          int sys_errno,
38
          bool *retry)
39
0
{
40
0
  *retry = false;
41
42
0
  if (ret >= 0) {
43
0
    return 0;
44
0
  }
45
46
0
  if (ret != -1) {
47
0
    return EIO;
48
0
  }
49
50
0
  if (sys_errno == 0) {
51
0
    return EIO;
52
0
  }
53
54
0
  if (sys_errno == EINTR) {
55
0
    *retry = true;
56
0
    return sys_errno;
57
0
  }
58
59
0
  if (sys_errno == EINPROGRESS) {
60
0
    *retry = true;
61
0
    return sys_errno;
62
0
  }
63
64
0
  if (sys_errno == EAGAIN) {
65
0
    *retry = true;
66
0
    return sys_errno;
67
0
  }
68
69
  /* ENOMEM is retryable on Solaris/illumos, and possibly other systems. */
70
0
  if (sys_errno == ENOMEM) {
71
0
    *retry = true;
72
0
    return sys_errno;
73
0
  }
74
75
0
#ifdef EWOULDBLOCK
76
0
  if (sys_errno == EWOULDBLOCK) {
77
0
    *retry = true;
78
0
    return sys_errno;
79
0
  }
80
0
#endif
81
82
0
  return sys_errno;
83
0
}
84
85
static int tsocket_bsd_common_prepare_fd(int fd, bool high_fd)
86
0
{
87
0
  int i;
88
0
  int sys_errno = 0;
89
0
  int fds[3];
90
0
  int num_fds = 0;
91
92
0
  int result;
93
0
  bool ok;
94
95
0
  if (fd == -1) {
96
0
    return -1;
97
0
  }
98
99
  /* first make a fd >= 3 */
100
0
  if (high_fd) {
101
0
    while (fd < 3) {
102
0
      fds[num_fds++] = fd;
103
0
      fd = dup(fd);
104
0
      if (fd == -1) {
105
0
        sys_errno = errno;
106
0
        break;
107
0
      }
108
0
    }
109
0
    for (i=0; i<num_fds; i++) {
110
0
      close(fds[i]);
111
0
    }
112
0
    if (fd == -1) {
113
0
      errno = sys_errno;
114
0
      return fd;
115
0
    }
116
0
  }
117
118
0
  result = set_blocking(fd, false);
119
0
  if (result == -1) {
120
0
    goto fail;
121
0
  }
122
123
0
  ok = smb_set_close_on_exec(fd);
124
0
  if (!ok) {
125
0
    goto fail;
126
0
  }
127
128
0
  return fd;
129
130
0
 fail:
131
0
  if (fd != -1) {
132
0
    sys_errno = errno;
133
0
    close(fd);
134
0
    errno = sys_errno;
135
0
  }
136
0
  return -1;
137
0
}
138
139
#ifdef HAVE_LINUX_RTNETLINK_H
140
/**
141
 * Get the amount of pending bytes from a netlink socket
142
 *
143
 * For some reason netlink sockets don't support querying the amount of pending
144
 * data via ioctl with FIONREAD, which is what we use in tsocket_bsd_pending()
145
 * below.
146
 *
147
 * We know we are on Linux as we're using netlink, which means we have a working
148
 * MSG_TRUNC flag to recvmsg() as well, so we use that together with MSG_PEEK.
149
 **/
150
static ssize_t tsocket_bsd_netlink_pending(int fd)
151
0
{
152
0
  struct iovec iov;
153
0
  struct msghdr msg;
154
0
  char buf[1];
155
156
0
  iov = (struct iovec) {
157
0
    .iov_base = buf,
158
0
    .iov_len = sizeof(buf)
159
0
  };
160
161
0
  msg = (struct msghdr) {
162
0
    .msg_iov = &iov,
163
0
    .msg_iovlen = 1
164
0
  };
165
166
0
  return recvmsg(fd, &msg, MSG_PEEK | MSG_TRUNC);
167
0
}
168
#else
169
static ssize_t tsocket_bsd_netlink_pending(int fd)
170
{
171
  errno = ENOSYS;
172
  return -1;
173
}
174
#endif
175
176
static ssize_t tsocket_bsd_pending(int fd)
177
0
{
178
0
  int ret;
179
0
  int value = 0;
180
181
0
  ret = ioctl(fd, FIONREAD, &value);
182
0
  if (ret == -1) {
183
0
    return ret;
184
0
  }
185
186
0
  if (ret != 0) {
187
    /* this should not be reached */
188
0
    errno = EIO;
189
0
    return -1;
190
0
  }
191
192
0
  if (value != 0) {
193
0
    return value;
194
0
  }
195
196
0
  return samba_socket_poll_or_sock_error(fd);
197
0
}
198
199
static const struct tsocket_address_ops tsocket_address_bsd_ops;
200
201
int _tsocket_address_bsd_from_sockaddr(TALLOC_CTX *mem_ctx,
202
               const struct sockaddr *sa,
203
               size_t sa_socklen,
204
               struct tsocket_address **_addr,
205
               const char *location)
206
0
{
207
0
  struct tsocket_address *addr;
208
0
  struct samba_sockaddr *bsda = NULL;
209
210
0
  if (sa_socklen < sizeof(sa->sa_family)) {
211
0
    errno = EINVAL;
212
0
    return -1;
213
0
  }
214
215
0
  switch (sa->sa_family) {
216
0
  case AF_UNIX:
217
0
    if (sa_socklen > sizeof(struct sockaddr_un)) {
218
0
      sa_socklen = sizeof(struct sockaddr_un);
219
0
    }
220
0
    break;
221
0
  case AF_INET:
222
0
    if (sa_socklen < sizeof(struct sockaddr_in)) {
223
0
      errno = EINVAL;
224
0
      return -1;
225
0
    }
226
0
    sa_socklen = sizeof(struct sockaddr_in);
227
0
    break;
228
0
#ifdef HAVE_IPV6
229
0
  case AF_INET6:
230
0
    if (sa_socklen < sizeof(struct sockaddr_in6)) {
231
0
      errno = EINVAL;
232
0
      return -1;
233
0
    }
234
0
    sa_socklen = sizeof(struct sockaddr_in6);
235
0
    break;
236
0
#endif
237
0
  default:
238
0
    errno = EAFNOSUPPORT;
239
0
    return -1;
240
0
  }
241
242
0
  if (sa_socklen > sizeof(struct sockaddr_storage)) {
243
0
    errno = EINVAL;
244
0
    return -1;
245
0
  }
246
247
0
  addr = tsocket_address_create(mem_ctx,
248
0
              &tsocket_address_bsd_ops,
249
0
              &bsda,
250
0
              struct samba_sockaddr,
251
0
              location);
252
0
  if (!addr) {
253
0
    errno = ENOMEM;
254
0
    return -1;
255
0
  }
256
257
0
  ZERO_STRUCTP(bsda);
258
259
0
  memcpy(&bsda->u.ss, sa, sa_socklen);
260
261
0
  bsda->sa_socklen = sa_socklen;
262
#ifdef HAVE_STRUCT_SOCKADDR_SA_LEN
263
  bsda->u.sa.sa_len = bsda->sa_socklen;
264
#endif
265
266
0
  *_addr = addr;
267
0
  return 0;
268
0
}
269
270
int _tsocket_address_bsd_from_samba_sockaddr(TALLOC_CTX *mem_ctx,
271
           const struct samba_sockaddr *xs_addr,
272
           struct tsocket_address **t_addr,
273
           const char *location)
274
0
{
275
0
  return _tsocket_address_bsd_from_sockaddr(mem_ctx,
276
0
              &xs_addr->u.sa,
277
0
              xs_addr->sa_socklen,
278
0
              t_addr,
279
0
              location);
280
0
}
281
282
ssize_t tsocket_address_bsd_sockaddr(const struct tsocket_address *addr,
283
             struct sockaddr *sa,
284
             size_t sa_socklen)
285
0
{
286
0
  struct samba_sockaddr *bsda = talloc_get_type(addr->private_data,
287
0
             struct samba_sockaddr);
288
289
0
  if (!bsda) {
290
0
    errno = EINVAL;
291
0
    return -1;
292
0
  }
293
294
0
  if (sa_socklen < bsda->sa_socklen) {
295
0
    errno = EINVAL;
296
0
    return -1;
297
0
  }
298
299
0
  if (sa_socklen > bsda->sa_socklen) {
300
0
    memset(sa, 0, sa_socklen);
301
0
    sa_socklen = bsda->sa_socklen;
302
0
  }
303
304
0
  memcpy(sa, &bsda->u.ss, sa_socklen);
305
#ifdef HAVE_STRUCT_SOCKADDR_SA_LEN
306
  sa->sa_len = sa_socklen;
307
#endif
308
0
  return sa_socklen;
309
0
}
310
311
bool tsocket_address_is_inet(const struct tsocket_address *addr, const char *fam)
312
0
{
313
0
  struct samba_sockaddr *bsda = talloc_get_type(addr->private_data,
314
0
             struct samba_sockaddr);
315
316
0
  if (!bsda) {
317
0
    return false;
318
0
  }
319
320
0
  switch (bsda->u.sa.sa_family) {
321
0
  case AF_INET:
322
0
    if (strcasecmp(fam, "ip") == 0) {
323
0
      return true;
324
0
    }
325
326
0
    if (strcasecmp(fam, "ipv4") == 0) {
327
0
      return true;
328
0
    }
329
330
0
    return false;
331
0
#ifdef HAVE_IPV6
332
0
  case AF_INET6:
333
0
    if (strcasecmp(fam, "ip") == 0) {
334
0
      return true;
335
0
    }
336
337
0
    if (strcasecmp(fam, "ipv6") == 0) {
338
0
      return true;
339
0
    }
340
341
0
    return false;
342
0
#endif
343
0
  }
344
345
0
  return false;
346
0
}
347
348
int _tsocket_address_inet_from_strings(TALLOC_CTX *mem_ctx,
349
               const char *fam,
350
               const char *addr,
351
               uint16_t port,
352
               struct tsocket_address **_addr,
353
               const char *location)
354
0
{
355
0
  struct addrinfo hints = {};
356
0
  struct addrinfo *result = NULL;
357
0
  char port_str[6];
358
0
  int ret;
359
360
  /*
361
   * we use SOCKET_STREAM here to get just one result
362
   * back from getaddrinfo().
363
   */
364
0
  hints.ai_socktype = SOCK_STREAM;
365
0
  hints.ai_flags = AI_NUMERICHOST | AI_NUMERICSERV;
366
367
0
  if (strcasecmp(fam, "ip") == 0) {
368
0
    hints.ai_family = AF_UNSPEC;
369
0
    if (!addr) {
370
0
#ifdef HAVE_IPV6
371
0
      addr = "::";
372
#else
373
      addr = "0.0.0.0";
374
#endif
375
0
    }
376
0
  } else if (strcasecmp(fam, "ipv4") == 0) {
377
0
    hints.ai_family = AF_INET;
378
0
    if (!addr) {
379
0
      addr = "0.0.0.0";
380
0
    }
381
0
#ifdef HAVE_IPV6
382
0
  } else if (strcasecmp(fam, "ipv6") == 0) {
383
0
    hints.ai_family = AF_INET6;
384
0
    if (!addr) {
385
0
      addr = "::";
386
0
    }
387
0
#endif
388
0
  } else {
389
0
    errno = EAFNOSUPPORT;
390
0
    return -1;
391
0
  }
392
393
0
  snprintf(port_str, sizeof(port_str), "%u", port);
394
395
0
  ret = getaddrinfo(addr, port_str, &hints, &result);
396
0
  if (ret != 0) {
397
0
    switch (ret) {
398
0
    case EAI_FAIL:
399
0
    case EAI_NONAME:
400
0
#ifdef EAI_ADDRFAMILY
401
0
    case EAI_ADDRFAMILY:
402
0
#endif
403
0
      errno = EINVAL;
404
0
      break;
405
0
    }
406
0
    ret = -1;
407
0
    goto done;
408
0
  }
409
410
0
  if (result->ai_socktype != SOCK_STREAM) {
411
0
    errno = EINVAL;
412
0
    ret = -1;
413
0
    goto done;
414
0
  }
415
416
0
  ret = _tsocket_address_bsd_from_sockaddr(mem_ctx,
417
0
              result->ai_addr,
418
0
              result->ai_addrlen,
419
0
              _addr,
420
0
              location);
421
422
0
done:
423
0
  if (result) {
424
0
    freeaddrinfo(result);
425
0
  }
426
0
  return ret;
427
0
}
428
429
int _tsocket_address_inet_from_hostport_strings(TALLOC_CTX *mem_ctx,
430
            const char *fam,
431
            const char *host_port_addr,
432
            uint16_t default_port,
433
            struct tsocket_address **_addr,
434
            const char *location)
435
0
{
436
0
  char *pl_sq = NULL;
437
0
  char *pr_sq = NULL;
438
0
  char *pl_period = NULL;
439
0
  char *port_sep = NULL;
440
0
  char *cport = NULL;
441
0
  char *buf = NULL;
442
0
  uint64_t port = 0;
443
0
  int ret;
444
0
  char *s_addr = NULL;
445
0
  uint16_t s_port = default_port;
446
0
  int error = 0;
447
0
  bool is_ipv6_by_squares = false;
448
449
0
  if (host_port_addr == NULL) {
450
    /* got straight to next function if host_port_addr is NULL */
451
0
    goto get_addr;
452
0
  }
453
0
  buf = talloc_strdup(mem_ctx, host_port_addr);
454
0
  if (buf == NULL) {
455
0
    errno = ENOMEM;
456
0
    return -1;
457
0
  }
458
0
  pl_period = strchr_m(buf, '.');
459
0
  port_sep = strrchr_m(buf, ':');
460
0
  pl_sq = strchr_m(buf, '[');
461
0
  pr_sq = strrchr_m(buf, ']');
462
  /* See if its IPv4 or IPv6 */
463
  /* Only parse IPv6 with squares with/without port, and IPv4 with port */
464
  /* Everything else, let tsocket_address_inet_from string() */
465
  /* find parsing errors */
466
0
#ifdef HAVE_IPV6
467
0
  is_ipv6_by_squares = (pl_sq != NULL && pr_sq != NULL && pr_sq > pl_sq);
468
0
#endif
469
0
  if (is_ipv6_by_squares) {
470
    /* IPv6 possibly with port - squares detected */
471
0
    port_sep = pr_sq + 1;
472
0
    if (*port_sep == '\0') {
473
0
      s_addr = pl_sq + 1;
474
0
      *pr_sq = 0;
475
0
      s_port = default_port;
476
0
      goto get_addr;
477
0
    }
478
0
    if (*port_sep != ':') {
479
0
      errno = EINVAL;
480
0
      return -1;
481
0
    }
482
0
    cport = port_sep + 1;
483
0
    port = smb_strtoull(
484
0
      cport, NULL, 10, &error, SMB_STR_FULL_STR_CONV);
485
0
    if (error != 0) {
486
0
      errno = EINVAL;
487
0
      return -1;
488
0
    }
489
0
    if (port > 65535) {
490
0
      errno = EINVAL;
491
0
      return -1;
492
0
    }
493
0
    s_port = (uint16_t)port;
494
0
    *port_sep = 0;
495
0
    *pr_sq = 0;
496
0
    s_addr = pl_sq + 1;
497
0
    *pl_sq = 0;
498
0
    goto get_addr;
499
0
  } else if (pl_period != NULL && port_sep != NULL) {
500
    /* IPv4 with port - more than one period in string */
501
0
    cport = port_sep + 1;
502
0
    port = smb_strtoull(
503
0
      cport, NULL, 10, &error, SMB_STR_FULL_STR_CONV);
504
0
    if (error != 0) {
505
0
      errno = EINVAL;
506
0
      return -1;
507
0
    }
508
0
    if (port > 65535) {
509
0
      errno = EINVAL;
510
0
      return -1;
511
0
    }
512
0
    s_port = (uint16_t)port;
513
0
    *port_sep = 0;
514
0
    s_addr = buf;
515
0
    goto get_addr;
516
0
  } else {
517
    /* Everything else, let tsocket_address_inet_from string() */
518
    /* find parsing errors */
519
0
    s_addr = buf;
520
0
    s_port = default_port;
521
0
    goto get_addr;
522
0
  }
523
0
get_addr:
524
0
  ret = _tsocket_address_inet_from_strings(
525
0
      mem_ctx, fam, s_addr, s_port, _addr, location);
526
527
0
  return ret;
528
0
}
529
530
char *tsocket_address_inet_addr_string(const struct tsocket_address *addr,
531
               TALLOC_CTX *mem_ctx)
532
0
{
533
0
  struct samba_sockaddr *bsda = talloc_get_type(addr->private_data,
534
0
             struct samba_sockaddr);
535
0
  char addr_str[INET6_ADDRSTRLEN+1];
536
0
  const char *str;
537
538
0
  if (!bsda) {
539
0
    errno = EINVAL;
540
0
    return NULL;
541
0
  }
542
543
0
  switch (bsda->u.sa.sa_family) {
544
0
  case AF_INET:
545
0
    str = inet_ntop(bsda->u.in.sin_family,
546
0
        &bsda->u.in.sin_addr,
547
0
        addr_str, sizeof(addr_str));
548
0
    break;
549
0
#ifdef HAVE_IPV6
550
0
  case AF_INET6:
551
0
    str = inet_ntop(bsda->u.in6.sin6_family,
552
0
        &bsda->u.in6.sin6_addr,
553
0
        addr_str, sizeof(addr_str));
554
0
    break;
555
0
#endif
556
0
  default:
557
0
    errno = EINVAL;
558
0
    return NULL;
559
0
  }
560
561
0
  if (!str) {
562
0
    return NULL;
563
0
  }
564
565
0
  return talloc_strdup(mem_ctx, str);
566
0
}
567
568
uint16_t tsocket_address_inet_port(const struct tsocket_address *addr)
569
0
{
570
0
  struct samba_sockaddr *bsda = talloc_get_type(addr->private_data,
571
0
             struct samba_sockaddr);
572
0
  uint16_t port = 0;
573
574
0
  if (!bsda) {
575
0
    errno = EINVAL;
576
0
    return 0;
577
0
  }
578
579
0
  switch (bsda->u.sa.sa_family) {
580
0
  case AF_INET:
581
0
    port = ntohs(bsda->u.in.sin_port);
582
0
    break;
583
0
#ifdef HAVE_IPV6
584
0
  case AF_INET6:
585
0
    port = ntohs(bsda->u.in6.sin6_port);
586
0
    break;
587
0
#endif
588
0
  default:
589
0
    errno = EINVAL;
590
0
    return 0;
591
0
  }
592
593
0
  return port;
594
0
}
595
596
int tsocket_address_inet_set_port(struct tsocket_address *addr,
597
          uint16_t port)
598
0
{
599
0
  struct samba_sockaddr *bsda = talloc_get_type(addr->private_data,
600
0
             struct samba_sockaddr);
601
602
0
  if (!bsda) {
603
0
    errno = EINVAL;
604
0
    return -1;
605
0
  }
606
607
0
  switch (bsda->u.sa.sa_family) {
608
0
  case AF_INET:
609
0
    bsda->u.in.sin_port = htons(port);
610
0
    break;
611
0
#ifdef HAVE_IPV6
612
0
  case AF_INET6:
613
0
    bsda->u.in6.sin6_port = htons(port);
614
0
    break;
615
0
#endif
616
0
  default:
617
0
    errno = EINVAL;
618
0
    return -1;
619
0
  }
620
621
0
  return 0;
622
0
}
623
624
bool tsocket_address_is_unix(const struct tsocket_address *addr)
625
0
{
626
0
  struct samba_sockaddr *bsda = talloc_get_type(addr->private_data,
627
0
             struct samba_sockaddr);
628
629
0
  if (!bsda) {
630
0
    return false;
631
0
  }
632
633
0
  switch (bsda->u.sa.sa_family) {
634
0
  case AF_UNIX:
635
0
    return true;
636
0
  }
637
638
0
  return false;
639
0
}
640
641
int _tsocket_address_unix_from_path(TALLOC_CTX *mem_ctx,
642
            const char *path,
643
            struct tsocket_address **_addr,
644
            const char *location)
645
0
{
646
0
  struct sockaddr_un un;
647
0
  void *p = &un;
648
0
  int ret;
649
650
0
  if (!path) {
651
0
    path = "";
652
0
  }
653
654
0
  if (strlen(path) > sizeof(un.sun_path)-1) {
655
0
    errno = ENAMETOOLONG;
656
0
    return -1;
657
0
  }
658
659
0
  ZERO_STRUCT(un);
660
0
  un.sun_family = AF_UNIX;
661
0
  strncpy(un.sun_path, path, sizeof(un.sun_path)-1);
662
663
0
  ret = _tsocket_address_bsd_from_sockaddr(mem_ctx,
664
0
             (struct sockaddr *)p,
665
0
             sizeof(un),
666
0
             _addr,
667
0
             location);
668
669
0
  return ret;
670
0
}
671
672
char *tsocket_address_unix_path(const struct tsocket_address *addr,
673
        TALLOC_CTX *mem_ctx)
674
0
{
675
0
  struct samba_sockaddr *bsda = talloc_get_type(addr->private_data,
676
0
             struct samba_sockaddr);
677
0
  const char *str;
678
679
0
  if (!bsda) {
680
0
    errno = EINVAL;
681
0
    return NULL;
682
0
  }
683
684
0
  switch (bsda->u.sa.sa_family) {
685
0
  case AF_UNIX:
686
0
    str = bsda->u.un.sun_path;
687
0
    break;
688
0
  default:
689
0
    errno = EINVAL;
690
0
    return NULL;
691
0
  }
692
693
0
  return talloc_strdup(mem_ctx, str);
694
0
}
695
696
static char *tsocket_address_bsd_string(const struct tsocket_address *addr,
697
          TALLOC_CTX *mem_ctx)
698
0
{
699
0
  struct samba_sockaddr *bsda = talloc_get_type(addr->private_data,
700
0
             struct samba_sockaddr);
701
0
  char *str;
702
0
  char *addr_str;
703
0
  const char *prefix = NULL;
704
0
  uint16_t port;
705
706
0
  switch (bsda->u.sa.sa_family) {
707
0
  case AF_UNIX:
708
0
    return talloc_asprintf(mem_ctx, "unix:%s",
709
0
               bsda->u.un.sun_path);
710
0
  case AF_INET:
711
0
    prefix = "ipv4";
712
0
    break;
713
0
#ifdef HAVE_IPV6
714
0
  case AF_INET6:
715
0
    prefix = "ipv6";
716
0
    break;
717
0
#endif
718
0
  default:
719
0
    errno = EINVAL;
720
0
    return NULL;
721
0
  }
722
723
0
  addr_str = tsocket_address_inet_addr_string(addr, mem_ctx);
724
0
  if (!addr_str) {
725
0
    return NULL;
726
0
  }
727
728
0
  port = tsocket_address_inet_port(addr);
729
730
0
  str = talloc_asprintf(mem_ctx, "%s:%s:%u",
731
0
            prefix, addr_str, port);
732
0
  talloc_free(addr_str);
733
734
0
  return str;
735
0
}
736
737
static struct tsocket_address *tsocket_address_bsd_copy(const struct tsocket_address *addr,
738
               TALLOC_CTX *mem_ctx,
739
               const char *location)
740
0
{
741
0
  struct samba_sockaddr *bsda = talloc_get_type(addr->private_data,
742
0
             struct samba_sockaddr);
743
0
  struct tsocket_address *copy;
744
0
  int ret;
745
746
0
  ret = _tsocket_address_bsd_from_sockaddr(mem_ctx,
747
0
             &bsda->u.sa,
748
0
             bsda->sa_socklen,
749
0
             &copy,
750
0
             location);
751
0
  if (ret != 0) {
752
0
    return NULL;
753
0
  }
754
755
0
  return copy;
756
0
}
757
758
static const struct tsocket_address_ops tsocket_address_bsd_ops = {
759
  .name   = "bsd",
760
  .string   = tsocket_address_bsd_string,
761
  .copy   = tsocket_address_bsd_copy,
762
};
763
764
struct tdgram_bsd {
765
  int fd;
766
767
  void *event_ptr;
768
  struct tevent_fd *fde;
769
  bool optimize_recvfrom;
770
  bool netlink;
771
772
  void *readable_private;
773
  void (*readable_handler)(void *private_data);
774
  void *writeable_private;
775
  void (*writeable_handler)(void *private_data);
776
};
777
778
bool tdgram_bsd_optimize_recvfrom(struct tdgram_context *dgram,
779
          bool on)
780
0
{
781
0
  struct tdgram_bsd *bsds =
782
0
    talloc_get_type(_tdgram_context_data(dgram),
783
0
    struct tdgram_bsd);
784
0
  bool old;
785
786
0
  if (bsds == NULL) {
787
    /* not a bsd socket */
788
0
    return false;
789
0
  }
790
791
0
  old = bsds->optimize_recvfrom;
792
0
  bsds->optimize_recvfrom = on;
793
794
0
  return old;
795
0
}
796
797
static void tdgram_bsd_fde_handler(struct tevent_context *ev,
798
           struct tevent_fd *fde,
799
           uint16_t flags,
800
           void *private_data)
801
0
{
802
0
  struct tdgram_bsd *bsds = talloc_get_type_abort(private_data,
803
0
          struct tdgram_bsd);
804
805
0
  if (flags & TEVENT_FD_WRITE) {
806
0
    bsds->writeable_handler(bsds->writeable_private);
807
0
    return;
808
0
  }
809
0
  if (flags & TEVENT_FD_READ) {
810
0
    if (!bsds->readable_handler) {
811
0
      TEVENT_FD_NOT_READABLE(bsds->fde);
812
0
      return;
813
0
    }
814
0
    bsds->readable_handler(bsds->readable_private);
815
0
    return;
816
0
  }
817
0
}
818
819
static int tdgram_bsd_set_readable_handler(struct tdgram_bsd *bsds,
820
             struct tevent_context *ev,
821
             void (*handler)(void *private_data),
822
             void *private_data)
823
0
{
824
0
  if (ev == NULL) {
825
0
    if (handler) {
826
0
      errno = EINVAL;
827
0
      return -1;
828
0
    }
829
0
    if (!bsds->readable_handler) {
830
0
      return 0;
831
0
    }
832
0
    bsds->readable_handler = NULL;
833
0
    bsds->readable_private = NULL;
834
835
0
    return 0;
836
0
  }
837
838
  /* read and write must use the same tevent_context */
839
0
  if (bsds->event_ptr != ev) {
840
0
    if (bsds->readable_handler || bsds->writeable_handler) {
841
0
      errno = EINVAL;
842
0
      return -1;
843
0
    }
844
0
    bsds->event_ptr = NULL;
845
0
    TALLOC_FREE(bsds->fde);
846
0
  }
847
848
0
  if (tevent_fd_get_flags(bsds->fde) == 0) {
849
0
    TALLOC_FREE(bsds->fde);
850
851
0
    bsds->fde = tevent_add_fd(ev, bsds,
852
0
            bsds->fd, TEVENT_FD_READ,
853
0
            tdgram_bsd_fde_handler,
854
0
            bsds);
855
0
    if (!bsds->fde) {
856
0
      errno = ENOMEM;
857
0
      return -1;
858
0
    }
859
860
    /* cache the event context we're running on */
861
0
    bsds->event_ptr = ev;
862
0
  } else if (!bsds->readable_handler) {
863
0
    TEVENT_FD_READABLE(bsds->fde);
864
0
  }
865
866
0
  bsds->readable_handler = handler;
867
0
  bsds->readable_private = private_data;
868
869
0
  return 0;
870
0
}
871
872
static int tdgram_bsd_set_writeable_handler(struct tdgram_bsd *bsds,
873
              struct tevent_context *ev,
874
              void (*handler)(void *private_data),
875
              void *private_data)
876
0
{
877
0
  if (ev == NULL) {
878
0
    if (handler) {
879
0
      errno = EINVAL;
880
0
      return -1;
881
0
    }
882
0
    if (!bsds->writeable_handler) {
883
0
      return 0;
884
0
    }
885
0
    bsds->writeable_handler = NULL;
886
0
    bsds->writeable_private = NULL;
887
0
    TEVENT_FD_NOT_WRITEABLE(bsds->fde);
888
889
0
    return 0;
890
0
  }
891
892
  /* read and write must use the same tevent_context */
893
0
  if (bsds->event_ptr != ev) {
894
0
    if (bsds->readable_handler || bsds->writeable_handler) {
895
0
      errno = EINVAL;
896
0
      return -1;
897
0
    }
898
0
    bsds->event_ptr = NULL;
899
0
    TALLOC_FREE(bsds->fde);
900
0
  }
901
902
0
  if (tevent_fd_get_flags(bsds->fde) == 0) {
903
0
    TALLOC_FREE(bsds->fde);
904
905
0
    bsds->fde = tevent_add_fd(ev, bsds,
906
0
            bsds->fd, TEVENT_FD_WRITE,
907
0
            tdgram_bsd_fde_handler,
908
0
            bsds);
909
0
    if (!bsds->fde) {
910
0
      errno = ENOMEM;
911
0
      return -1;
912
0
    }
913
914
    /* cache the event context we're running on */
915
0
    bsds->event_ptr = ev;
916
0
  } else if (!bsds->writeable_handler) {
917
0
    TEVENT_FD_WRITEABLE(bsds->fde);
918
0
  }
919
920
0
  bsds->writeable_handler = handler;
921
0
  bsds->writeable_private = private_data;
922
923
0
  return 0;
924
0
}
925
926
struct tdgram_bsd_recvfrom_state {
927
  struct tdgram_context *dgram;
928
  bool first_try;
929
  uint8_t *buf;
930
  size_t len;
931
  struct tsocket_address *src;
932
};
933
934
static void tdgram_bsd_recvfrom_cleanup(struct tevent_req *req,
935
          enum tevent_req_state req_state)
936
0
{
937
0
  struct tdgram_bsd_recvfrom_state *state =
938
0
    tevent_req_data(req,
939
0
    struct tdgram_bsd_recvfrom_state);
940
941
0
  if (state->dgram != NULL) {
942
0
    struct tdgram_bsd *bsds =
943
0
      tdgram_context_data(state->dgram,
944
0
      struct tdgram_bsd);
945
946
0
    tdgram_bsd_set_readable_handler(bsds, NULL, NULL, NULL);
947
0
    state->dgram = NULL;
948
0
  }
949
0
}
950
951
static void tdgram_bsd_recvfrom_handler(void *private_data);
952
953
static struct tevent_req *tdgram_bsd_recvfrom_send(TALLOC_CTX *mem_ctx,
954
          struct tevent_context *ev,
955
          struct tdgram_context *dgram)
956
0
{
957
0
  struct tevent_req *req;
958
0
  struct tdgram_bsd_recvfrom_state *state;
959
0
  struct tdgram_bsd *bsds = tdgram_context_data(dgram, struct tdgram_bsd);
960
0
  int ret;
961
962
0
  req = tevent_req_create(mem_ctx, &state,
963
0
        struct tdgram_bsd_recvfrom_state);
964
0
  if (!req) {
965
0
    return NULL;
966
0
  }
967
968
0
  state->dgram  = dgram;
969
0
  state->first_try= true;
970
0
  state->buf  = NULL;
971
0
  state->len  = 0;
972
0
  state->src  = NULL;
973
974
0
  tevent_req_set_cleanup_fn(req, tdgram_bsd_recvfrom_cleanup);
975
976
0
  if (bsds->fd == -1) {
977
0
    tevent_req_error(req, ENOTCONN);
978
0
    goto post;
979
0
  }
980
981
982
  /*
983
   * this is a fast path, not waiting for the
984
   * socket to become explicit readable gains
985
   * about 10%-20% performance in benchmark tests.
986
   */
987
0
  if (bsds->optimize_recvfrom) {
988
    /*
989
     * We only do the optimization on
990
     * recvfrom if the caller asked for it.
991
     *
992
     * This is needed because in most cases
993
     * we prefer to flush send buffers before
994
     * receiving incoming requests.
995
     */
996
0
    tdgram_bsd_recvfrom_handler(req);
997
0
    if (!tevent_req_is_in_progress(req)) {
998
0
      goto post;
999
0
    }
1000
0
  }
1001
1002
0
  ret = tdgram_bsd_set_readable_handler(bsds, ev,
1003
0
                tdgram_bsd_recvfrom_handler,
1004
0
                req);
1005
0
  if (ret == -1) {
1006
0
    tevent_req_error(req, errno);
1007
0
    goto post;
1008
0
  }
1009
1010
0
  return req;
1011
1012
0
 post:
1013
0
  tevent_req_post(req, ev);
1014
0
  return req;
1015
0
}
1016
1017
static void tdgram_bsd_recvfrom_handler(void *private_data)
1018
0
{
1019
0
  struct tevent_req *req = talloc_get_type_abort(private_data,
1020
0
         struct tevent_req);
1021
0
  struct tdgram_bsd_recvfrom_state *state = tevent_req_data(req,
1022
0
          struct tdgram_bsd_recvfrom_state);
1023
0
  struct tdgram_context *dgram = state->dgram;
1024
0
  struct tdgram_bsd *bsds = tdgram_context_data(dgram, struct tdgram_bsd);
1025
0
  struct samba_sockaddr *bsda = NULL;
1026
0
  ssize_t ret;
1027
0
  int err;
1028
0
  bool retry;
1029
1030
0
  if (bsds->netlink) {
1031
0
    ret = tsocket_bsd_netlink_pending(bsds->fd);
1032
0
  } else {
1033
0
    ret = tsocket_bsd_pending(bsds->fd);
1034
0
  }
1035
1036
0
  if (state->first_try && ret == 0) {
1037
0
    state->first_try = false;
1038
    /* retry later */
1039
0
    return;
1040
0
  }
1041
0
  state->first_try = false;
1042
1043
0
  err = tsocket_bsd_error_from_errno(ret, errno, &retry);
1044
0
  if (retry) {
1045
    /* retry later */
1046
0
    return;
1047
0
  }
1048
0
  if (tevent_req_error(req, err)) {
1049
0
    return;
1050
0
  }
1051
1052
  /* note that 'ret' can be 0 here */
1053
0
  state->buf = talloc_array(state, uint8_t, ret);
1054
0
  if (tevent_req_nomem(state->buf, req)) {
1055
0
    return;
1056
0
  }
1057
0
  state->len = ret;
1058
1059
0
  state->src = tsocket_address_create(state,
1060
0
              &tsocket_address_bsd_ops,
1061
0
              &bsda,
1062
0
              struct samba_sockaddr,
1063
0
              __location__ "bsd_recvfrom");
1064
0
  if (tevent_req_nomem(state->src, req)) {
1065
0
    return;
1066
0
  }
1067
1068
0
  ZERO_STRUCTP(bsda);
1069
0
  bsda->sa_socklen = sizeof(bsda->u.ss);
1070
#ifdef HAVE_STRUCT_SOCKADDR_SA_LEN
1071
  bsda->u.sa.sa_len = bsda->sa_socklen;
1072
#endif
1073
1074
0
  ret = recvfrom(bsds->fd, state->buf, state->len, 0,
1075
0
           &bsda->u.sa, &bsda->sa_socklen);
1076
0
  err = tsocket_bsd_error_from_errno(ret, errno, &retry);
1077
0
  if (retry) {
1078
    /* retry later */
1079
0
    return;
1080
0
  }
1081
0
  if (tevent_req_error(req, err)) {
1082
0
    return;
1083
0
  }
1084
1085
  /*
1086
   * Some systems (FreeBSD, see bug #7115) return too much
1087
   * bytes in tsocket_bsd_pending()/ioctl(fd, FIONREAD, ...),
1088
   * the return value includes some IP/UDP header bytes,
1089
   * while recvfrom() just returns the payload.
1090
   */
1091
0
  state->buf = talloc_realloc(state, state->buf, uint8_t, ret);
1092
0
  if (tevent_req_nomem(state->buf, req)) {
1093
0
    return;
1094
0
  }
1095
0
  state->len = ret;
1096
1097
0
  tevent_req_done(req);
1098
0
}
1099
1100
static ssize_t tdgram_bsd_recvfrom_recv(struct tevent_req *req,
1101
          int *perrno,
1102
          TALLOC_CTX *mem_ctx,
1103
          uint8_t **buf,
1104
          struct tsocket_address **src)
1105
0
{
1106
0
  struct tdgram_bsd_recvfrom_state *state = tevent_req_data(req,
1107
0
          struct tdgram_bsd_recvfrom_state);
1108
0
  ssize_t ret;
1109
1110
0
  ret = tsocket_simple_int_recv(req, perrno);
1111
0
  if (ret == 0) {
1112
0
    *buf = talloc_move(mem_ctx, &state->buf);
1113
0
    ret = state->len;
1114
0
    if (src) {
1115
0
      *src = talloc_move(mem_ctx, &state->src);
1116
0
    }
1117
0
  }
1118
1119
0
  tevent_req_received(req);
1120
0
  return ret;
1121
0
}
1122
1123
struct tdgram_bsd_sendto_state {
1124
  struct tdgram_context *dgram;
1125
1126
  const uint8_t *buf;
1127
  size_t len;
1128
  const struct tsocket_address *dst;
1129
1130
  ssize_t ret;
1131
};
1132
1133
static void tdgram_bsd_sendto_cleanup(struct tevent_req *req,
1134
              enum tevent_req_state req_state)
1135
0
{
1136
0
  struct tdgram_bsd_sendto_state *state =
1137
0
    tevent_req_data(req,
1138
0
    struct tdgram_bsd_sendto_state);
1139
1140
0
  if (state->dgram != NULL) {
1141
0
    struct tdgram_bsd *bsds =
1142
0
      tdgram_context_data(state->dgram,
1143
0
      struct tdgram_bsd);
1144
1145
0
    tdgram_bsd_set_writeable_handler(bsds, NULL, NULL, NULL);
1146
0
    state->dgram = NULL;
1147
0
  }
1148
0
}
1149
1150
static void tdgram_bsd_sendto_handler(void *private_data);
1151
1152
static struct tevent_req *tdgram_bsd_sendto_send(TALLOC_CTX *mem_ctx,
1153
             struct tevent_context *ev,
1154
             struct tdgram_context *dgram,
1155
             const uint8_t *buf,
1156
             size_t len,
1157
             const struct tsocket_address *dst)
1158
0
{
1159
0
  struct tevent_req *req;
1160
0
  struct tdgram_bsd_sendto_state *state;
1161
0
  struct tdgram_bsd *bsds = tdgram_context_data(dgram, struct tdgram_bsd);
1162
0
  int ret;
1163
1164
0
  req = tevent_req_create(mem_ctx, &state,
1165
0
        struct tdgram_bsd_sendto_state);
1166
0
  if (!req) {
1167
0
    return NULL;
1168
0
  }
1169
1170
0
  state->dgram  = dgram;
1171
0
  state->buf  = buf;
1172
0
  state->len  = len;
1173
0
  state->dst  = dst;
1174
0
  state->ret  = -1;
1175
1176
0
  tevent_req_set_cleanup_fn(req, tdgram_bsd_sendto_cleanup);
1177
1178
0
  if (bsds->fd == -1) {
1179
0
    tevent_req_error(req, ENOTCONN);
1180
0
    goto post;
1181
0
  }
1182
1183
  /*
1184
   * this is a fast path, not waiting for the
1185
   * socket to become explicit writeable gains
1186
   * about 10%-20% performance in benchmark tests.
1187
   */
1188
0
  tdgram_bsd_sendto_handler(req);
1189
0
  if (!tevent_req_is_in_progress(req)) {
1190
0
    goto post;
1191
0
  }
1192
1193
0
  ret = tdgram_bsd_set_writeable_handler(bsds, ev,
1194
0
                 tdgram_bsd_sendto_handler,
1195
0
                 req);
1196
0
  if (ret == -1) {
1197
0
    tevent_req_error(req, errno);
1198
0
    goto post;
1199
0
  }
1200
1201
0
  return req;
1202
1203
0
 post:
1204
0
  tevent_req_post(req, ev);
1205
0
  return req;
1206
0
}
1207
1208
static void tdgram_bsd_sendto_handler(void *private_data)
1209
0
{
1210
0
  struct tevent_req *req = talloc_get_type_abort(private_data,
1211
0
         struct tevent_req);
1212
0
  struct tdgram_bsd_sendto_state *state = tevent_req_data(req,
1213
0
          struct tdgram_bsd_sendto_state);
1214
0
  struct tdgram_context *dgram = state->dgram;
1215
0
  struct tdgram_bsd *bsds = tdgram_context_data(dgram, struct tdgram_bsd);
1216
0
  struct sockaddr *sa = NULL;
1217
0
  socklen_t sa_socklen = 0;
1218
0
  ssize_t ret;
1219
0
  int err;
1220
0
  bool retry;
1221
1222
0
  if (state->dst) {
1223
0
    struct samba_sockaddr *bsda =
1224
0
      talloc_get_type(state->dst->private_data,
1225
0
      struct samba_sockaddr);
1226
1227
0
    sa = &bsda->u.sa;
1228
0
    sa_socklen = bsda->sa_socklen;
1229
0
  }
1230
1231
0
  ret = sendto(bsds->fd, state->buf, state->len, 0, sa, sa_socklen);
1232
0
  err = tsocket_bsd_error_from_errno(ret, errno, &retry);
1233
0
  if (retry) {
1234
    /* retry later */
1235
0
    return;
1236
0
  }
1237
1238
0
  if (err == EMSGSIZE) {
1239
    /* round up in 1K increments */
1240
0
    int bufsize = ((state->len + 1023) & (~1023));
1241
1242
0
    ret = setsockopt(bsds->fd, SOL_SOCKET, SO_SNDBUF, &bufsize,
1243
0
         sizeof(bufsize));
1244
0
    if (ret == 0) {
1245
      /*
1246
       * We do the retry here, rather then via the
1247
       * handler, as we only want to retry once for
1248
       * this condition, so if there is a mismatch
1249
       * between what setsockopt() accepts and what can
1250
       * actually be sent, we do not end up in a
1251
       * loop.
1252
       */
1253
1254
0
      ret = sendto(bsds->fd, state->buf, state->len,
1255
0
             0, sa, sa_socklen);
1256
0
      err = tsocket_bsd_error_from_errno(ret, errno, &retry);
1257
0
      if (retry) { /* retry later */
1258
0
        return;
1259
0
      }
1260
0
    }
1261
0
  }
1262
1263
0
  if (tevent_req_error(req, err)) {
1264
0
    return;
1265
0
  }
1266
1267
0
  state->ret = ret;
1268
1269
0
  tevent_req_done(req);
1270
0
}
1271
1272
static ssize_t tdgram_bsd_sendto_recv(struct tevent_req *req, int *perrno)
1273
0
{
1274
0
  struct tdgram_bsd_sendto_state *state = tevent_req_data(req,
1275
0
          struct tdgram_bsd_sendto_state);
1276
0
  ssize_t ret;
1277
1278
0
  ret = tsocket_simple_int_recv(req, perrno);
1279
0
  if (ret == 0) {
1280
0
    ret = state->ret;
1281
0
  }
1282
1283
0
  tevent_req_received(req);
1284
0
  return ret;
1285
0
}
1286
1287
struct tdgram_bsd_disconnect_state {
1288
  uint8_t __dummy;
1289
};
1290
1291
static struct tevent_req *tdgram_bsd_disconnect_send(TALLOC_CTX *mem_ctx,
1292
                 struct tevent_context *ev,
1293
                 struct tdgram_context *dgram)
1294
0
{
1295
0
  struct tdgram_bsd *bsds = tdgram_context_data(dgram, struct tdgram_bsd);
1296
0
  struct tevent_req *req;
1297
0
  struct tdgram_bsd_disconnect_state *state;
1298
0
  int ret;
1299
0
  int err;
1300
0
  bool dummy;
1301
1302
0
  req = tevent_req_create(mem_ctx, &state,
1303
0
        struct tdgram_bsd_disconnect_state);
1304
0
  if (req == NULL) {
1305
0
    return NULL;
1306
0
  }
1307
1308
0
  if (bsds->fd == -1) {
1309
0
    tevent_req_error(req, ENOTCONN);
1310
0
    goto post;
1311
0
  }
1312
1313
0
  TALLOC_FREE(bsds->fde);
1314
0
  ret = close(bsds->fd);
1315
0
  bsds->fd = -1;
1316
0
  err = tsocket_bsd_error_from_errno(ret, errno, &dummy);
1317
0
  if (tevent_req_error(req, err)) {
1318
0
    goto post;
1319
0
  }
1320
1321
0
  tevent_req_done(req);
1322
0
post:
1323
0
  tevent_req_post(req, ev);
1324
0
  return req;
1325
0
}
1326
1327
static int tdgram_bsd_disconnect_recv(struct tevent_req *req,
1328
              int *perrno)
1329
0
{
1330
0
  int ret;
1331
1332
0
  ret = tsocket_simple_int_recv(req, perrno);
1333
1334
0
  tevent_req_received(req);
1335
0
  return ret;
1336
0
}
1337
1338
static const struct tdgram_context_ops tdgram_bsd_ops = {
1339
  .name     = "bsd",
1340
1341
  .recvfrom_send    = tdgram_bsd_recvfrom_send,
1342
  .recvfrom_recv    = tdgram_bsd_recvfrom_recv,
1343
1344
  .sendto_send    = tdgram_bsd_sendto_send,
1345
  .sendto_recv    = tdgram_bsd_sendto_recv,
1346
1347
  .disconnect_send  = tdgram_bsd_disconnect_send,
1348
  .disconnect_recv  = tdgram_bsd_disconnect_recv,
1349
};
1350
1351
static int tdgram_bsd_destructor(struct tdgram_bsd *bsds)
1352
0
{
1353
0
  TALLOC_FREE(bsds->fde);
1354
0
  if (bsds->fd != -1) {
1355
0
    close(bsds->fd);
1356
0
    bsds->fd = -1;
1357
0
  }
1358
0
  return 0;
1359
0
}
1360
1361
static int tdgram_bsd_dgram_socket(const struct tsocket_address *local,
1362
           const struct tsocket_address *remote,
1363
           bool broadcast,
1364
           TALLOC_CTX *mem_ctx,
1365
           struct tdgram_context **_dgram,
1366
           const char *location)
1367
0
{
1368
0
  struct samba_sockaddr *lbsda =
1369
0
    talloc_get_type_abort(local->private_data,
1370
0
    struct samba_sockaddr);
1371
0
  struct samba_sockaddr *rbsda = NULL;
1372
0
  struct tdgram_context *dgram;
1373
0
  struct tdgram_bsd *bsds;
1374
0
  int fd;
1375
0
  int ret;
1376
0
  bool do_bind = false;
1377
0
  bool do_reuseaddr = false;
1378
0
  bool do_ipv6only = false;
1379
0
  bool is_inet = false;
1380
0
  int sa_fam = lbsda->u.sa.sa_family;
1381
1382
0
  if (remote) {
1383
0
    rbsda = talloc_get_type_abort(remote->private_data,
1384
0
      struct samba_sockaddr);
1385
0
  }
1386
1387
0
  switch (lbsda->u.sa.sa_family) {
1388
0
  case AF_UNIX:
1389
0
    if (broadcast) {
1390
0
      errno = EINVAL;
1391
0
      return -1;
1392
0
    }
1393
0
    if (lbsda->u.un.sun_path[0] != 0) {
1394
0
      do_reuseaddr = true;
1395
0
      do_bind = true;
1396
0
    }
1397
0
    break;
1398
0
  case AF_INET:
1399
0
    if (lbsda->u.in.sin_port != 0) {
1400
0
      do_reuseaddr = true;
1401
0
      do_bind = true;
1402
0
    }
1403
0
    if (lbsda->u.in.sin_addr.s_addr != INADDR_ANY) {
1404
0
      do_bind = true;
1405
0
    }
1406
0
    is_inet = true;
1407
0
    break;
1408
0
#ifdef HAVE_IPV6
1409
0
  case AF_INET6:
1410
0
    if (lbsda->u.in6.sin6_port != 0) {
1411
0
      do_reuseaddr = true;
1412
0
      do_bind = true;
1413
0
    }
1414
0
    if (memcmp(&in6addr_any,
1415
0
         &lbsda->u.in6.sin6_addr,
1416
0
         sizeof(in6addr_any)) != 0) {
1417
0
      do_bind = true;
1418
0
    }
1419
0
    is_inet = true;
1420
0
    do_ipv6only = true;
1421
0
    break;
1422
0
#endif
1423
0
  default:
1424
0
    errno = EINVAL;
1425
0
    return -1;
1426
0
  }
1427
1428
0
  if (!do_bind && is_inet && rbsda) {
1429
0
    sa_fam = rbsda->u.sa.sa_family;
1430
0
    switch (sa_fam) {
1431
0
    case AF_INET:
1432
0
      do_ipv6only = false;
1433
0
      break;
1434
0
#ifdef HAVE_IPV6
1435
0
    case AF_INET6:
1436
0
      do_ipv6only = true;
1437
0
      break;
1438
0
#endif
1439
0
    }
1440
0
  }
1441
1442
0
  fd = socket(sa_fam, SOCK_DGRAM, 0);
1443
0
  if (fd < 0) {
1444
0
    return -1;
1445
0
  }
1446
1447
0
  fd = tsocket_bsd_common_prepare_fd(fd, true);
1448
0
  if (fd < 0) {
1449
0
    return -1;
1450
0
  }
1451
1452
0
  dgram = tdgram_context_create(mem_ctx,
1453
0
              &tdgram_bsd_ops,
1454
0
              &bsds,
1455
0
              struct tdgram_bsd,
1456
0
              location);
1457
0
  if (!dgram) {
1458
0
    int saved_errno = errno;
1459
0
    close(fd);
1460
0
    errno = saved_errno;
1461
0
    return -1;
1462
0
  }
1463
0
  *bsds = (struct tdgram_bsd){.fd = fd};
1464
0
  talloc_set_destructor(bsds, tdgram_bsd_destructor);
1465
1466
0
#ifdef HAVE_IPV6
1467
0
  if (do_ipv6only) {
1468
0
    int val = 1;
1469
1470
0
    ret = setsockopt(fd, IPPROTO_IPV6, IPV6_V6ONLY,
1471
0
         (const void *)&val, sizeof(val));
1472
0
    if (ret == -1) {
1473
0
      int saved_errno = errno;
1474
0
      talloc_free(dgram);
1475
0
      errno = saved_errno;
1476
0
      return -1;
1477
0
    }
1478
0
  }
1479
0
#endif
1480
1481
0
  if (broadcast) {
1482
0
    int val = 1;
1483
1484
0
    ret = setsockopt(fd, SOL_SOCKET, SO_BROADCAST,
1485
0
         (const void *)&val, sizeof(val));
1486
0
    if (ret == -1) {
1487
0
      int saved_errno = errno;
1488
0
      talloc_free(dgram);
1489
0
      errno = saved_errno;
1490
0
      return -1;
1491
0
    }
1492
0
  }
1493
1494
0
  if (do_reuseaddr) {
1495
0
    int val = 1;
1496
1497
0
    ret = setsockopt(fd, SOL_SOCKET, SO_REUSEADDR,
1498
0
         (const void *)&val, sizeof(val));
1499
0
    if (ret == -1) {
1500
0
      int saved_errno = errno;
1501
0
      talloc_free(dgram);
1502
0
      errno = saved_errno;
1503
0
      return -1;
1504
0
    }
1505
0
  }
1506
1507
0
  if (do_bind) {
1508
0
    ret = bind(fd, &lbsda->u.sa, lbsda->sa_socklen);
1509
0
    if (ret == -1) {
1510
0
      int saved_errno = errno;
1511
0
      talloc_free(dgram);
1512
0
      errno = saved_errno;
1513
0
      return -1;
1514
0
    }
1515
0
  }
1516
1517
0
  if (rbsda) {
1518
0
    if (rbsda->u.sa.sa_family != sa_fam) {
1519
0
      talloc_free(dgram);
1520
0
      errno = EINVAL;
1521
0
      return -1;
1522
0
    }
1523
1524
0
    ret = connect(fd, &rbsda->u.sa, rbsda->sa_socklen);
1525
0
    if (ret == -1) {
1526
0
      int saved_errno = errno;
1527
0
      talloc_free(dgram);
1528
0
      errno = saved_errno;
1529
0
      return -1;
1530
0
    }
1531
0
  }
1532
1533
0
  *_dgram = dgram;
1534
0
  return 0;
1535
0
}
1536
1537
int _tdgram_bsd_existing_socket(TALLOC_CTX *mem_ctx,
1538
        int fd,
1539
        struct tdgram_context **_dgram,
1540
        const char *location)
1541
0
{
1542
0
  struct tdgram_context *dgram;
1543
0
  struct tdgram_bsd *bsds;
1544
0
#ifdef HAVE_LINUX_RTNETLINK_H
1545
0
  int result;
1546
0
  struct sockaddr sa;
1547
0
  socklen_t sa_len = sizeof(struct sockaddr);
1548
0
#endif
1549
1550
0
  dgram = tdgram_context_create(mem_ctx,
1551
0
              &tdgram_bsd_ops,
1552
0
              &bsds,
1553
0
              struct tdgram_bsd,
1554
0
              location);
1555
0
  if (!dgram) {
1556
0
    return -1;
1557
0
  }
1558
0
  ZERO_STRUCTP(bsds);
1559
0
  bsds->fd = fd;
1560
0
  talloc_set_destructor(bsds, tdgram_bsd_destructor);
1561
1562
0
  *_dgram = dgram;
1563
1564
0
#ifdef HAVE_LINUX_RTNETLINK_H
1565
  /*
1566
   * Try to determine the protocol family and remember if it's
1567
   * AF_NETLINK. We don't care if this fails.
1568
   */
1569
0
  result = getsockname(fd, &sa, &sa_len);
1570
0
  if (result == 0 && sa.sa_family == AF_NETLINK) {
1571
0
    bsds->netlink = true;
1572
0
  }
1573
0
#endif
1574
1575
0
  return 0;
1576
0
}
1577
1578
int _tdgram_inet_udp_socket(const struct tsocket_address *local,
1579
          const struct tsocket_address *remote,
1580
          TALLOC_CTX *mem_ctx,
1581
          struct tdgram_context **dgram,
1582
          const char *location)
1583
0
{
1584
0
  struct samba_sockaddr *lbsda =
1585
0
    talloc_get_type_abort(local->private_data,
1586
0
    struct samba_sockaddr);
1587
0
  int ret;
1588
1589
0
  switch (lbsda->u.sa.sa_family) {
1590
0
  case AF_INET:
1591
0
    break;
1592
0
#ifdef HAVE_IPV6
1593
0
  case AF_INET6:
1594
0
    break;
1595
0
#endif
1596
0
  default:
1597
0
    errno = EINVAL;
1598
0
    return -1;
1599
0
  }
1600
1601
0
  ret = tdgram_bsd_dgram_socket(local, remote, false,
1602
0
              mem_ctx, dgram, location);
1603
1604
0
  return ret;
1605
0
}
1606
1607
int _tdgram_inet_udp_broadcast_socket(const struct tsocket_address *local,
1608
              TALLOC_CTX *mem_ctx,
1609
              struct tdgram_context **dgram,
1610
              const char *location)
1611
0
{
1612
0
  struct samba_sockaddr *lbsda =
1613
0
    talloc_get_type_abort(local->private_data,
1614
0
    struct samba_sockaddr);
1615
0
  int ret;
1616
1617
0
  switch (lbsda->u.sa.sa_family) {
1618
0
  case AF_INET:
1619
0
    break;
1620
0
#ifdef HAVE_IPV6
1621
0
  case AF_INET6:
1622
    /* only ipv4 */
1623
0
    errno = EINVAL;
1624
0
    return -1;
1625
0
#endif
1626
0
  default:
1627
0
    errno = EINVAL;
1628
0
    return -1;
1629
0
  }
1630
1631
0
  ret = tdgram_bsd_dgram_socket(local, NULL, true,
1632
0
              mem_ctx, dgram, location);
1633
1634
0
  return ret;
1635
0
}
1636
1637
int _tdgram_unix_socket(const struct tsocket_address *local,
1638
      const struct tsocket_address *remote,
1639
      TALLOC_CTX *mem_ctx,
1640
      struct tdgram_context **dgram,
1641
      const char *location)
1642
0
{
1643
0
  struct samba_sockaddr *lbsda =
1644
0
    talloc_get_type_abort(local->private_data,
1645
0
    struct samba_sockaddr);
1646
0
  int ret;
1647
1648
0
  switch (lbsda->u.sa.sa_family) {
1649
0
  case AF_UNIX:
1650
0
    break;
1651
0
  default:
1652
0
    errno = EINVAL;
1653
0
    return -1;
1654
0
  }
1655
1656
0
  ret = tdgram_bsd_dgram_socket(local, remote, false,
1657
0
              mem_ctx, dgram, location);
1658
1659
0
  return ret;
1660
0
}
1661
1662
struct tstream_bsd {
1663
  int fd;
1664
  int error;
1665
1666
  void *event_ptr;
1667
  struct tevent_fd *fde;
1668
  bool optimize_readv;
1669
  bool fail_readv_first_error;
1670
1671
  void *error_private;
1672
  void (*error_handler)(void *private_data);
1673
  void *readable_private;
1674
  void (*readable_handler)(void *private_data);
1675
  void *writeable_private;
1676
  void (*writeable_handler)(void *private_data);
1677
};
1678
1679
bool tstream_bsd_optimize_readv(struct tstream_context *stream,
1680
        bool on)
1681
0
{
1682
0
  struct tstream_bsd *bsds =
1683
0
    talloc_get_type(_tstream_context_data(stream),
1684
0
    struct tstream_bsd);
1685
0
  bool old;
1686
1687
0
  if (bsds == NULL) {
1688
    /* not a bsd socket */
1689
0
    return false;
1690
0
  }
1691
1692
0
  old = bsds->optimize_readv;
1693
0
  bsds->optimize_readv = on;
1694
1695
0
  return old;
1696
0
}
1697
1698
bool tstream_bsd_fail_readv_first_error(struct tstream_context *stream,
1699
          bool on)
1700
0
{
1701
0
  struct tstream_bsd *bsds =
1702
0
    talloc_get_type(_tstream_context_data(stream),
1703
0
    struct tstream_bsd);
1704
0
  bool old;
1705
1706
0
  if (bsds == NULL) {
1707
    /* not a bsd socket */
1708
0
    return false;
1709
0
  }
1710
1711
0
  old = bsds->fail_readv_first_error;
1712
0
  bsds->fail_readv_first_error = on;
1713
1714
0
  return old;
1715
0
}
1716
1717
static void tstream_bsd_fde_handler(struct tevent_context *ev,
1718
            struct tevent_fd *fde,
1719
            uint16_t flags,
1720
            void *private_data)
1721
0
{
1722
0
  struct tstream_bsd *bsds = talloc_get_type_abort(private_data,
1723
0
           struct tstream_bsd);
1724
1725
0
  if (flags & TEVENT_FD_ERROR) {
1726
    /*
1727
     * We lazily keep TEVENT_FD_READ alive
1728
     * in tstream_bsd_set_readable_handler()
1729
     *
1730
     * So we have to check TEVENT_FD_READ
1731
     * as well as bsds->readable_handler
1732
     *
1733
     * We only drain remaining data from the
1734
     * the recv queue if available and desired.
1735
     */
1736
0
    if ((flags & TEVENT_FD_READ) &&
1737
0
        !bsds->fail_readv_first_error &&
1738
0
        (bsds->readable_handler != NULL))
1739
0
    {
1740
      /*
1741
       * If there's still data to read
1742
       * we allow it to be read until
1743
       * we reach EOF (=> EPIPE).
1744
       */
1745
0
      bsds->readable_handler(bsds->readable_private);
1746
0
      return;
1747
0
    }
1748
1749
    /*
1750
     * If there's no data left to read,
1751
     * we get the error.
1752
     *
1753
     * It means we no longer call any readv or
1754
     * writev, as bsds->error is checked first.
1755
     */
1756
0
    if (bsds->error == 0) {
1757
0
      int ret = samba_socket_poll_or_sock_error(bsds->fd);
1758
1759
0
      if (ret == -1) {
1760
0
        bsds->error = errno;
1761
0
      }
1762
      /* fallback to EPIPE */
1763
0
      if (bsds->error == 0) {
1764
0
        bsds->error = EPIPE;
1765
0
      }
1766
0
    }
1767
1768
    /*
1769
     * Let write to fail early.
1770
     *
1771
     * Note we only need to check TEVENT_FD_WRITE
1772
     * as tstream_bsd_set_writeable_handler()
1773
     * clear it together with the handler.
1774
     */
1775
0
    if (flags & TEVENT_FD_WRITE) {
1776
0
      bsds->writeable_handler(bsds->writeable_private);
1777
0
      return;
1778
0
    }
1779
1780
    /* We prefer the readable handler to fire first. */
1781
0
    if (bsds->readable_handler != NULL) {
1782
0
      bsds->readable_handler(bsds->readable_private);
1783
0
      return;
1784
0
    }
1785
1786
    /* As last resort we notify the writeable handler */
1787
0
    if (bsds->writeable_handler != NULL) {
1788
0
      bsds->writeable_handler(bsds->writeable_private);
1789
0
      return;
1790
0
    }
1791
1792
    /*
1793
     * Failing reads and writes will also terminate
1794
     * pending monitor requests at the main tstream layer,
1795
     * so we only call the error handler if it is the only
1796
     * pending request
1797
     */
1798
0
    if (bsds->error_handler != NULL) {
1799
0
      bsds->error_handler(bsds->error_private);
1800
0
      return;
1801
0
    }
1802
1803
    /*
1804
     * We may hit this because we don't clear TEVENT_FD_ERROR
1805
     * in tstream_bsd_set_readable_handler() nor
1806
     * tstream_bsd_set_writeable_handler().
1807
     *
1808
     * As we already captured the error, we can remove
1809
     * the fde completely.
1810
     */
1811
0
    TALLOC_FREE(bsds->fde);
1812
0
    return;
1813
0
  }
1814
0
  if (flags & TEVENT_FD_WRITE) {
1815
0
    bsds->writeable_handler(bsds->writeable_private);
1816
0
    return;
1817
0
  }
1818
0
  if (flags & TEVENT_FD_READ) {
1819
0
    if (!bsds->readable_handler) {
1820
      /*
1821
       * tstream_bsd_set_readable_handler
1822
       * doesn't clear TEVENT_FD_READ.
1823
       *
1824
       * In order to avoid cpu-spinning
1825
       * we need to clear it here.
1826
       */
1827
0
      TEVENT_FD_NOT_READABLE(bsds->fde);
1828
1829
      /*
1830
       * Here we're lazy and keep TEVENT_FD_ERROR
1831
       * alive. If it's triggered the next time
1832
       * we'll handle it gracefully above
1833
       * and end up with TALLOC_FREE(bsds->fde);
1834
       * in order to spin on TEVENT_FD_ERROR.
1835
       */
1836
0
      return;
1837
0
    }
1838
0
    bsds->readable_handler(bsds->readable_private);
1839
0
    return;
1840
0
  }
1841
0
}
1842
1843
static int tstream_bsd_set_error_handler(struct tstream_bsd *bsds,
1844
              struct tevent_context *ev,
1845
              void (*handler)(void *private_data),
1846
              void *private_data)
1847
0
{
1848
0
  if (ev == NULL) {
1849
0
    if (handler) {
1850
0
      errno = EINVAL;
1851
0
      return -1;
1852
0
    }
1853
0
    if (!bsds->error_handler) {
1854
0
      return 0;
1855
0
    }
1856
0
    bsds->error_handler = NULL;
1857
0
    bsds->error_private = NULL;
1858
1859
    /*
1860
     * Here we are lazy as it's very likely that the next
1861
     * tevent_monitor_send() will come in shortly,
1862
     * so we keep TEVENT_FD_ERROR alive.
1863
     */
1864
0
    return 0;
1865
0
  }
1866
1867
  /* monitor, read and write must use the same tevent_context */
1868
0
  if (bsds->event_ptr != ev) {
1869
0
    if (bsds->error_handler ||
1870
0
        bsds->readable_handler ||
1871
0
        bsds->writeable_handler)
1872
0
    {
1873
0
      errno = EINVAL;
1874
0
      return -1;
1875
0
    }
1876
0
    bsds->event_ptr = NULL;
1877
0
    TALLOC_FREE(bsds->fde);
1878
0
  }
1879
1880
0
  if (tevent_fd_get_flags(bsds->fde) == 0) {
1881
0
    TALLOC_FREE(bsds->fde);
1882
1883
0
    bsds->fde = tevent_add_fd(ev, bsds,
1884
0
            bsds->fd,
1885
0
            TEVENT_FD_ERROR,
1886
0
            tstream_bsd_fde_handler,
1887
0
            bsds);
1888
0
    if (!bsds->fde) {
1889
0
      errno = ENOMEM;
1890
0
      return -1;
1891
0
    }
1892
1893
    /* cache the event context we're running on */
1894
0
    bsds->event_ptr = ev;
1895
0
  } else if (!bsds->error_handler) {
1896
    /*
1897
     * TEVENT_FD_ERROR is likely already set, so
1898
     * TEVENT_FD_WANTERROR() is most likely a no-op.
1899
     */
1900
0
    TEVENT_FD_WANTERROR(bsds->fde);
1901
0
  }
1902
1903
0
  bsds->error_handler = handler;
1904
0
  bsds->error_private = private_data;
1905
1906
0
  return 0;
1907
0
}
1908
1909
static int tstream_bsd_set_readable_handler(struct tstream_bsd *bsds,
1910
              struct tevent_context *ev,
1911
              void (*handler)(void *private_data),
1912
              void *private_data)
1913
0
{
1914
0
  if (ev == NULL) {
1915
0
    if (handler) {
1916
0
      errno = EINVAL;
1917
0
      return -1;
1918
0
    }
1919
0
    if (!bsds->readable_handler) {
1920
0
      return 0;
1921
0
    }
1922
0
    bsds->readable_handler = NULL;
1923
0
    bsds->readable_private = NULL;
1924
1925
    /*
1926
     * Here we are lazy as it's very likely that the next
1927
     * tevent_readv_send() will come in shortly,
1928
     * so we keep TEVENT_FD_READ alive.
1929
     */
1930
0
    return 0;
1931
0
  }
1932
1933
  /* monitor, read and write must use the same tevent_context */
1934
0
  if (bsds->event_ptr != ev) {
1935
0
    if (bsds->error_handler ||
1936
0
        bsds->readable_handler ||
1937
0
        bsds->writeable_handler)
1938
0
    {
1939
0
      errno = EINVAL;
1940
0
      return -1;
1941
0
    }
1942
0
    bsds->event_ptr = NULL;
1943
0
    TALLOC_FREE(bsds->fde);
1944
0
  }
1945
1946
0
  if (tevent_fd_get_flags(bsds->fde) == 0) {
1947
0
    TALLOC_FREE(bsds->fde);
1948
1949
0
    bsds->fde = tevent_add_fd(ev, bsds,
1950
0
            bsds->fd,
1951
0
            TEVENT_FD_ERROR | TEVENT_FD_READ,
1952
0
            tstream_bsd_fde_handler,
1953
0
            bsds);
1954
0
    if (!bsds->fde) {
1955
0
      errno = ENOMEM;
1956
0
      return -1;
1957
0
    }
1958
1959
    /* cache the event context we're running on */
1960
0
    bsds->event_ptr = ev;
1961
0
  } else if (!bsds->readable_handler) {
1962
0
    TEVENT_FD_READABLE(bsds->fde);
1963
    /*
1964
     * TEVENT_FD_ERROR is likely already set, so
1965
     * TEVENT_FD_WANTERROR() is most likely a no-op.
1966
     */
1967
0
    TEVENT_FD_WANTERROR(bsds->fde);
1968
0
  }
1969
1970
0
  bsds->readable_handler = handler;
1971
0
  bsds->readable_private = private_data;
1972
1973
0
  return 0;
1974
0
}
1975
1976
static int tstream_bsd_set_writeable_handler(struct tstream_bsd *bsds,
1977
               struct tevent_context *ev,
1978
               void (*handler)(void *private_data),
1979
               void *private_data)
1980
0
{
1981
0
  if (ev == NULL) {
1982
0
    if (handler) {
1983
0
      errno = EINVAL;
1984
0
      return -1;
1985
0
    }
1986
0
    if (!bsds->writeable_handler) {
1987
0
      return 0;
1988
0
    }
1989
0
    bsds->writeable_handler = NULL;
1990
0
    bsds->writeable_private = NULL;
1991
1992
    /*
1993
     * The writeable handler is only
1994
     * set if we got EAGAIN or a short
1995
     * writev on the first try, so
1996
     * this isn't the hot path.
1997
     *
1998
     * Here we are lazy and leave TEVENT_FD_ERROR
1999
     * alive as it's shared with the readable
2000
     * handler. So we only clear TEVENT_FD_WRITE.
2001
     */
2002
0
    TEVENT_FD_NOT_WRITEABLE(bsds->fde);
2003
0
    return 0;
2004
0
  }
2005
2006
  /* monitor, read and write must use the same tevent_context */
2007
0
  if (bsds->event_ptr != ev) {
2008
0
    if (bsds->error_handler ||
2009
0
        bsds->readable_handler ||
2010
0
        bsds->writeable_handler)
2011
0
    {
2012
0
      errno = EINVAL;
2013
0
      return -1;
2014
0
    }
2015
0
    bsds->event_ptr = NULL;
2016
0
    TALLOC_FREE(bsds->fde);
2017
0
  }
2018
2019
0
  if (tevent_fd_get_flags(bsds->fde) == 0) {
2020
0
    TALLOC_FREE(bsds->fde);
2021
2022
0
    bsds->fde = tevent_add_fd(ev, bsds,
2023
0
            bsds->fd,
2024
0
            TEVENT_FD_ERROR | TEVENT_FD_WRITE,
2025
0
            tstream_bsd_fde_handler,
2026
0
            bsds);
2027
0
    if (!bsds->fde) {
2028
0
      errno = ENOMEM;
2029
0
      return -1;
2030
0
    }
2031
2032
    /* cache the event context we're running on */
2033
0
    bsds->event_ptr = ev;
2034
0
  } else if (!bsds->writeable_handler) {
2035
0
    TEVENT_FD_WRITEABLE(bsds->fde);
2036
    /*
2037
     * TEVENT_FD_ERROR is likely already set, so
2038
     * TEVENT_FD_WANTERROR() is most likely a no-op.
2039
     */
2040
0
    TEVENT_FD_WANTERROR(bsds->fde);
2041
0
  }
2042
2043
0
  bsds->writeable_handler = handler;
2044
0
  bsds->writeable_private = private_data;
2045
2046
0
  return 0;
2047
0
}
2048
2049
static ssize_t tstream_bsd_pending_bytes(struct tstream_context *stream)
2050
0
{
2051
0
  struct tstream_bsd *bsds = tstream_context_data(stream,
2052
0
           struct tstream_bsd);
2053
0
  ssize_t ret;
2054
2055
0
  if (bsds->fd == -1) {
2056
0
    errno = ENOTCONN;
2057
0
    return -1;
2058
0
  }
2059
2060
0
  if (bsds->error != 0) {
2061
0
    errno = bsds->error;
2062
0
    return -1;
2063
0
  }
2064
2065
0
  ret = tsocket_bsd_pending(bsds->fd);
2066
0
  if (ret == -1) {
2067
    /*
2068
     * remember the error and don't
2069
     * allow further requests
2070
     */
2071
0
    bsds->error = errno;
2072
0
  }
2073
2074
0
  return ret;
2075
0
}
2076
2077
struct tstream_bsd_readv_state {
2078
  struct tstream_context *stream;
2079
2080
  struct iovec *vector;
2081
  size_t count;
2082
2083
  int ret;
2084
};
2085
2086
static void tstream_bsd_readv_cleanup(struct tevent_req *req,
2087
              enum tevent_req_state req_state)
2088
0
{
2089
0
  struct tstream_bsd_readv_state *state =
2090
0
    tevent_req_data(req,
2091
0
    struct tstream_bsd_readv_state);
2092
2093
0
  if (state->stream != NULL) {
2094
0
    struct tstream_bsd *bsds =
2095
0
      tstream_context_data(state->stream,
2096
0
      struct tstream_bsd);
2097
2098
0
    tstream_bsd_set_readable_handler(bsds, NULL, NULL, NULL);
2099
0
    state->stream = NULL;
2100
0
  }
2101
0
}
2102
2103
static void tstream_bsd_readv_handler(void *private_data);
2104
2105
static struct tevent_req *tstream_bsd_readv_send(TALLOC_CTX *mem_ctx,
2106
          struct tevent_context *ev,
2107
          struct tstream_context *stream,
2108
          struct iovec *vector,
2109
          size_t count)
2110
0
{
2111
0
  struct tevent_req *req;
2112
0
  struct tstream_bsd_readv_state *state;
2113
0
  struct tstream_bsd *bsds = tstream_context_data(stream, struct tstream_bsd);
2114
0
  int ret;
2115
2116
0
  req = tevent_req_create(mem_ctx, &state,
2117
0
        struct tstream_bsd_readv_state);
2118
0
  if (!req) {
2119
0
    return NULL;
2120
0
  }
2121
2122
0
  state->stream = stream;
2123
  /* we make a copy of the vector so that we can modify it */
2124
0
  state->vector = talloc_array(state, struct iovec, count);
2125
0
  if (tevent_req_nomem(state->vector, req)) {
2126
0
    goto post;
2127
0
  }
2128
0
  memcpy(state->vector, vector, sizeof(struct iovec)*count);
2129
0
  state->count  = count;
2130
0
  state->ret  = 0;
2131
2132
0
  tevent_req_set_cleanup_fn(req, tstream_bsd_readv_cleanup);
2133
2134
0
  if (bsds->fd == -1) {
2135
0
    tevent_req_error(req, ENOTCONN);
2136
0
    goto post;
2137
0
  }
2138
2139
  /*
2140
   * this is a fast path, not waiting for the
2141
   * socket to become explicit readable gains
2142
   * about 10%-20% performance in benchmark tests.
2143
   */
2144
0
  if (bsds->optimize_readv) {
2145
    /*
2146
     * We only do the optimization on
2147
     * readv if the caller asked for it.
2148
     *
2149
     * This is needed because in most cases
2150
     * we prefer to flush send buffers before
2151
     * receiving incoming requests.
2152
     */
2153
0
    tstream_bsd_readv_handler(req);
2154
0
    if (!tevent_req_is_in_progress(req)) {
2155
0
      goto post;
2156
0
    }
2157
0
  }
2158
2159
0
  ret = tstream_bsd_set_readable_handler(bsds, ev,
2160
0
                tstream_bsd_readv_handler,
2161
0
                req);
2162
0
  if (ret == -1) {
2163
0
    tevent_req_error(req, errno);
2164
0
    goto post;
2165
0
  }
2166
2167
0
  return req;
2168
2169
0
 post:
2170
0
  tevent_req_post(req, ev);
2171
0
  return req;
2172
0
}
2173
2174
static void tstream_bsd_readv_handler(void *private_data)
2175
0
{
2176
0
  struct tevent_req *req = talloc_get_type_abort(private_data,
2177
0
         struct tevent_req);
2178
0
  struct tstream_bsd_readv_state *state = tevent_req_data(req,
2179
0
          struct tstream_bsd_readv_state);
2180
0
  struct tstream_context *stream = state->stream;
2181
0
  struct tstream_bsd *bsds = tstream_context_data(stream, struct tstream_bsd);
2182
0
  int ret;
2183
0
  int err;
2184
0
  int _count;
2185
0
  bool ok, retry;
2186
2187
0
  if (bsds->error != 0) {
2188
0
    tevent_req_error(req, bsds->error);
2189
0
    return;
2190
0
  }
2191
2192
0
  ret = readv(bsds->fd, state->vector, state->count);
2193
0
  if (ret == 0) {
2194
    /* propagate end of file */
2195
0
    bsds->error = EPIPE;
2196
0
    tevent_req_error(req, EPIPE);
2197
0
    return;
2198
0
  }
2199
0
  err = tsocket_bsd_error_from_errno(ret, errno, &retry);
2200
0
  if (retry) {
2201
    /* retry later */
2202
0
    return;
2203
0
  }
2204
0
  if (err != 0) {
2205
    /*
2206
     * remember the error and don't
2207
     * allow further requests
2208
     */
2209
0
    bsds->error = err;
2210
0
  }
2211
0
  if (tevent_req_error(req, err)) {
2212
0
    return;
2213
0
  }
2214
2215
0
  state->ret += ret;
2216
2217
0
  _count = state->count; /* tstream has size_t count, readv has int */
2218
0
  ok = iov_advance(&state->vector, &_count, ret);
2219
0
  state->count = _count;
2220
2221
0
  if (!ok) {
2222
0
    tevent_req_error(req, EINVAL);
2223
0
    return;
2224
0
  }
2225
2226
0
  if (state->count > 0) {
2227
    /* we have more to read */
2228
0
    return;
2229
0
  }
2230
2231
0
  tevent_req_done(req);
2232
0
}
2233
2234
static int tstream_bsd_readv_recv(struct tevent_req *req,
2235
          int *perrno)
2236
0
{
2237
0
  struct tstream_bsd_readv_state *state = tevent_req_data(req,
2238
0
          struct tstream_bsd_readv_state);
2239
0
  int ret;
2240
2241
0
  ret = tsocket_simple_int_recv(req, perrno);
2242
0
  if (ret == 0) {
2243
0
    ret = state->ret;
2244
0
  }
2245
2246
0
  tevent_req_received(req);
2247
0
  return ret;
2248
0
}
2249
2250
struct tstream_bsd_writev_state {
2251
  struct tstream_context *stream;
2252
2253
  struct iovec *vector;
2254
  size_t count;
2255
2256
  int ret;
2257
};
2258
2259
static void tstream_bsd_writev_cleanup(struct tevent_req *req,
2260
               enum tevent_req_state req_state)
2261
0
{
2262
0
  struct tstream_bsd_writev_state *state =
2263
0
    tevent_req_data(req,
2264
0
    struct tstream_bsd_writev_state);
2265
2266
0
  if (state->stream != NULL) {
2267
0
    struct tstream_bsd *bsds =
2268
0
      tstream_context_data(state->stream,
2269
0
      struct tstream_bsd);
2270
2271
0
    tstream_bsd_set_writeable_handler(bsds, NULL, NULL, NULL);
2272
0
    state->stream = NULL;
2273
0
  }
2274
0
}
2275
2276
static void tstream_bsd_writev_handler(void *private_data);
2277
2278
static struct tevent_req *tstream_bsd_writev_send(TALLOC_CTX *mem_ctx,
2279
             struct tevent_context *ev,
2280
             struct tstream_context *stream,
2281
             const struct iovec *vector,
2282
             size_t count)
2283
0
{
2284
0
  struct tevent_req *req;
2285
0
  struct tstream_bsd_writev_state *state;
2286
0
  struct tstream_bsd *bsds = tstream_context_data(stream, struct tstream_bsd);
2287
0
  int ret;
2288
2289
0
  req = tevent_req_create(mem_ctx, &state,
2290
0
        struct tstream_bsd_writev_state);
2291
0
  if (!req) {
2292
0
    return NULL;
2293
0
  }
2294
2295
0
  state->stream = stream;
2296
  /* we make a copy of the vector so that we can modify it */
2297
0
  state->vector = talloc_array(state, struct iovec, count);
2298
0
  if (tevent_req_nomem(state->vector, req)) {
2299
0
    goto post;
2300
0
  }
2301
0
  memcpy(state->vector, vector, sizeof(struct iovec)*count);
2302
0
  state->count  = count;
2303
0
  state->ret  = 0;
2304
2305
0
  tevent_req_set_cleanup_fn(req, tstream_bsd_writev_cleanup);
2306
2307
0
  if (bsds->fd == -1) {
2308
0
    tevent_req_error(req, ENOTCONN);
2309
0
    goto post;
2310
0
  }
2311
2312
  /*
2313
   * this is a fast path, not waiting for the
2314
   * socket to become explicit writeable gains
2315
   * about 10%-20% performance in benchmark tests.
2316
   */
2317
0
  tstream_bsd_writev_handler(req);
2318
0
  if (!tevent_req_is_in_progress(req)) {
2319
0
    goto post;
2320
0
  }
2321
2322
0
  ret = tstream_bsd_set_writeable_handler(bsds, ev,
2323
0
                 tstream_bsd_writev_handler,
2324
0
                 req);
2325
0
  if (ret == -1) {
2326
0
    tevent_req_error(req, errno);
2327
0
    goto post;
2328
0
  }
2329
2330
0
  return req;
2331
2332
0
 post:
2333
0
  tevent_req_post(req, ev);
2334
0
  return req;
2335
0
}
2336
2337
static void tstream_bsd_writev_handler(void *private_data)
2338
0
{
2339
0
  struct tevent_req *req = talloc_get_type_abort(private_data,
2340
0
         struct tevent_req);
2341
0
  struct tstream_bsd_writev_state *state = tevent_req_data(req,
2342
0
          struct tstream_bsd_writev_state);
2343
0
  struct tstream_context *stream = state->stream;
2344
0
  struct tstream_bsd *bsds = tstream_context_data(stream, struct tstream_bsd);
2345
0
  ssize_t ret;
2346
0
  int err;
2347
0
  int _count;
2348
0
  bool ok, retry;
2349
2350
0
  if (bsds->error != 0) {
2351
0
    tevent_req_error(req, bsds->error);
2352
0
    return;
2353
0
  }
2354
2355
0
  ret = writev(bsds->fd, state->vector, state->count);
2356
0
  if (ret == 0) {
2357
    /* propagate end of file */
2358
0
    bsds->error = EPIPE;
2359
0
    tevent_req_error(req, EPIPE);
2360
0
    return;
2361
0
  }
2362
0
  err = tsocket_bsd_error_from_errno(ret, errno, &retry);
2363
0
  if (retry) {
2364
    /*
2365
     * retry later...
2366
     */
2367
0
    return;
2368
0
  }
2369
0
  if (err != 0) {
2370
    /*
2371
     * remember the error and don't
2372
     * allow further requests
2373
     */
2374
0
    bsds->error = err;
2375
0
  }
2376
0
  if (tevent_req_error(req, err)) {
2377
0
    return;
2378
0
  }
2379
2380
0
  state->ret += ret;
2381
2382
0
  _count = state->count; /* tstream has size_t count, writev has int */
2383
0
  ok = iov_advance(&state->vector, &_count, ret);
2384
0
  state->count = _count;
2385
2386
0
  if (!ok) {
2387
0
    tevent_req_error(req, EINVAL);
2388
0
    return;
2389
0
  }
2390
2391
0
  if (state->count > 0) {
2392
    /*
2393
     * we have more to write
2394
     */
2395
0
    return;
2396
0
  }
2397
2398
0
  tevent_req_done(req);
2399
0
}
2400
2401
static int tstream_bsd_writev_recv(struct tevent_req *req, int *perrno)
2402
0
{
2403
0
  struct tstream_bsd_writev_state *state = tevent_req_data(req,
2404
0
          struct tstream_bsd_writev_state);
2405
0
  int ret;
2406
2407
0
  ret = tsocket_simple_int_recv(req, perrno);
2408
0
  if (ret == 0) {
2409
0
    ret = state->ret;
2410
0
  }
2411
2412
0
  tevent_req_received(req);
2413
0
  return ret;
2414
0
}
2415
2416
struct tstream_bsd_disconnect_state {
2417
  void *__dummy;
2418
};
2419
2420
static struct tevent_req *tstream_bsd_disconnect_send(TALLOC_CTX *mem_ctx,
2421
                 struct tevent_context *ev,
2422
                 struct tstream_context *stream)
2423
0
{
2424
0
  struct tstream_bsd *bsds = tstream_context_data(stream, struct tstream_bsd);
2425
0
  struct tevent_req *req;
2426
0
  struct tstream_bsd_disconnect_state *state;
2427
0
  int ret;
2428
0
  int err;
2429
0
  bool dummy;
2430
2431
0
  req = tevent_req_create(mem_ctx, &state,
2432
0
        struct tstream_bsd_disconnect_state);
2433
0
  if (req == NULL) {
2434
0
    return NULL;
2435
0
  }
2436
2437
0
  if (bsds->fd == -1) {
2438
0
    tevent_req_error(req, ENOTCONN);
2439
0
    goto post;
2440
0
  }
2441
2442
0
  TALLOC_FREE(bsds->fde);
2443
0
  ret = close(bsds->fd);
2444
0
  bsds->fd = -1;
2445
0
  err = tsocket_bsd_error_from_errno(ret, errno, &dummy);
2446
0
  if (tevent_req_error(req, err)) {
2447
0
    goto post;
2448
0
  }
2449
2450
0
  tevent_req_done(req);
2451
0
post:
2452
0
  tevent_req_post(req, ev);
2453
0
  return req;
2454
0
}
2455
2456
static int tstream_bsd_disconnect_recv(struct tevent_req *req,
2457
              int *perrno)
2458
0
{
2459
0
  int ret;
2460
2461
0
  ret = tsocket_simple_int_recv(req, perrno);
2462
2463
0
  tevent_req_received(req);
2464
0
  return ret;
2465
0
}
2466
2467
struct tstream_bsd_monitor_state {
2468
  struct tstream_context *stream;
2469
};
2470
2471
static void tstream_bsd_monitor_cleanup(struct tevent_req *req,
2472
          enum tevent_req_state req_state)
2473
0
{
2474
0
  struct tstream_bsd_monitor_state *state =
2475
0
    tevent_req_data(req,
2476
0
    struct tstream_bsd_monitor_state);
2477
2478
0
  if (state->stream != NULL) {
2479
0
    struct tstream_bsd *bsds =
2480
0
      tstream_context_data(state->stream,
2481
0
      struct tstream_bsd);
2482
2483
0
    tstream_bsd_set_error_handler(bsds, NULL, NULL, NULL);
2484
0
    state->stream = NULL;
2485
0
  }
2486
0
}
2487
2488
static void tstream_bsd_monitor_handler(void *private_data);
2489
2490
static struct tevent_req *tstream_bsd_monitor_send(TALLOC_CTX *mem_ctx,
2491
          struct tevent_context *ev,
2492
          struct tstream_context *stream)
2493
0
{
2494
0
  struct tevent_req *req = NULL;
2495
0
  struct tstream_bsd_monitor_state *state = NULL;
2496
0
  struct tstream_bsd *bsds =
2497
0
    tstream_context_data(stream, struct tstream_bsd);
2498
0
  int ret;
2499
2500
0
  req = tevent_req_create(mem_ctx, &state,
2501
0
        struct tstream_bsd_monitor_state);
2502
0
  if (req == NULL) {
2503
0
    return NULL;
2504
0
  }
2505
0
  state->stream = stream;
2506
2507
0
  tevent_req_set_cleanup_fn(req, tstream_bsd_monitor_cleanup);
2508
2509
0
  if (bsds->fd == -1) {
2510
0
    tevent_req_error(req, ENOTCONN);
2511
0
    return tevent_req_post(req, ev);
2512
0
  }
2513
2514
0
  ret = tstream_bsd_set_error_handler(bsds, ev,
2515
0
              tstream_bsd_monitor_handler,
2516
0
              req);
2517
0
  if (ret == -1) {
2518
0
    tevent_req_error(req, errno);
2519
0
    return tevent_req_post(req, ev);
2520
0
  }
2521
2522
0
  return req;
2523
0
}
2524
2525
static void tstream_bsd_monitor_handler(void *private_data)
2526
0
{
2527
0
  struct tevent_req *req = talloc_get_type_abort(private_data,
2528
0
         struct tevent_req);
2529
0
  struct tstream_bsd_monitor_state *state = tevent_req_data(req,
2530
0
          struct tstream_bsd_monitor_state);
2531
0
  struct tstream_context *stream = state->stream;
2532
0
  struct tstream_bsd *bsds = tstream_context_data(stream, struct tstream_bsd);
2533
2534
  /*
2535
   * tstream_bsd_fde_handler already
2536
   * made sure that bsds->error is not 0.
2537
   */
2538
0
  tevent_req_error(req, bsds->error);
2539
0
}
2540
2541
static int tstream_bsd_monitor_recv(struct tevent_req *req,
2542
            int *perrno)
2543
0
{
2544
0
  int ret;
2545
2546
0
  ret = tsocket_simple_int_recv(req, perrno);
2547
2548
0
  tevent_req_received(req);
2549
0
  return ret;
2550
0
}
2551
2552
static const struct tstream_context_ops tstream_bsd_ops = {
2553
  .name     = "bsd",
2554
2555
  .pending_bytes    = tstream_bsd_pending_bytes,
2556
2557
  .readv_send   = tstream_bsd_readv_send,
2558
  .readv_recv   = tstream_bsd_readv_recv,
2559
2560
  .writev_send    = tstream_bsd_writev_send,
2561
  .writev_recv    = tstream_bsd_writev_recv,
2562
2563
  .disconnect_send  = tstream_bsd_disconnect_send,
2564
  .disconnect_recv  = tstream_bsd_disconnect_recv,
2565
2566
  .monitor_send   = tstream_bsd_monitor_send,
2567
  .monitor_recv   = tstream_bsd_monitor_recv,
2568
};
2569
2570
static int tstream_bsd_destructor(struct tstream_bsd *bsds)
2571
0
{
2572
0
  TALLOC_FREE(bsds->fde);
2573
0
  if (bsds->fd != -1) {
2574
0
    close(bsds->fd);
2575
0
    bsds->fd = -1;
2576
0
  }
2577
0
  return 0;
2578
0
}
2579
2580
int _tstream_bsd_existing_socket(TALLOC_CTX *mem_ctx,
2581
         int fd,
2582
         struct tstream_context **_stream,
2583
         const char *location)
2584
0
{
2585
0
  struct tstream_context *stream;
2586
0
  struct tstream_bsd *bsds;
2587
2588
0
  stream = tstream_context_create(mem_ctx,
2589
0
          &tstream_bsd_ops,
2590
0
          &bsds,
2591
0
          struct tstream_bsd,
2592
0
          location);
2593
0
  if (!stream) {
2594
0
    return -1;
2595
0
  }
2596
0
  ZERO_STRUCTP(bsds);
2597
0
  bsds->fd = fd;
2598
0
  talloc_set_destructor(bsds, tstream_bsd_destructor);
2599
2600
0
  *_stream = stream;
2601
0
  return 0;
2602
0
}
2603
2604
struct tstream_bsd_connect_state {
2605
  int fd;
2606
  struct tevent_fd *fde;
2607
  struct tsocket_address *local;
2608
};
2609
2610
static void tstream_bsd_connect_cleanup(struct tevent_req *req,
2611
          enum tevent_req_state req_state)
2612
0
{
2613
0
  struct tstream_bsd_connect_state *state =
2614
0
    tevent_req_data(req,
2615
0
    struct tstream_bsd_connect_state);
2616
2617
0
  if (req_state == TEVENT_REQ_DONE) {
2618
0
    return;
2619
0
  }
2620
2621
0
  TALLOC_FREE(state->fde);
2622
0
  if (state->fd != -1) {
2623
0
    close(state->fd);
2624
0
    state->fd = -1;
2625
0
  }
2626
0
}
2627
2628
static void tstream_bsd_connect_fde_handler(struct tevent_context *ev,
2629
              struct tevent_fd *fde,
2630
              uint16_t flags,
2631
              void *private_data);
2632
2633
static struct tevent_req *tstream_bsd_connect_send(TALLOC_CTX *mem_ctx,
2634
          struct tevent_context *ev,
2635
          int sys_errno,
2636
          const struct tsocket_address *local,
2637
          const struct tsocket_address *remote)
2638
0
{
2639
0
  struct tevent_req *req;
2640
0
  struct tstream_bsd_connect_state *state;
2641
0
  struct samba_sockaddr *lbsda =
2642
0
    talloc_get_type_abort(local->private_data,
2643
0
    struct samba_sockaddr);
2644
0
  struct samba_sockaddr *lrbsda = NULL;
2645
0
  struct samba_sockaddr *rbsda =
2646
0
    talloc_get_type_abort(remote->private_data,
2647
0
    struct samba_sockaddr);
2648
0
  int ret;
2649
0
  bool do_bind = false;
2650
0
  bool do_reuseaddr = false;
2651
0
  bool do_ipv6only = false;
2652
0
  bool is_inet = false;
2653
0
  int sa_fam = lbsda->u.sa.sa_family;
2654
2655
0
  req = tevent_req_create(mem_ctx, &state,
2656
0
        struct tstream_bsd_connect_state);
2657
0
  if (!req) {
2658
0
    return NULL;
2659
0
  }
2660
0
  state->fd = -1;
2661
0
  state->fde = NULL;
2662
2663
0
  tevent_req_set_cleanup_fn(req, tstream_bsd_connect_cleanup);
2664
2665
  /* give the wrappers a chance to report an error */
2666
0
  if (sys_errno != 0) {
2667
0
    tevent_req_error(req, sys_errno);
2668
0
    goto post;
2669
0
  }
2670
2671
0
  switch (lbsda->u.sa.sa_family) {
2672
0
  case AF_UNIX:
2673
0
    if (lbsda->u.un.sun_path[0] != 0) {
2674
0
      do_reuseaddr = true;
2675
0
      do_bind = true;
2676
0
    }
2677
0
    break;
2678
0
  case AF_INET:
2679
0
    if (lbsda->u.in.sin_port != 0) {
2680
0
      do_reuseaddr = true;
2681
0
      do_bind = true;
2682
0
    }
2683
0
    if (lbsda->u.in.sin_addr.s_addr != INADDR_ANY) {
2684
0
      do_bind = true;
2685
0
    }
2686
0
    is_inet = true;
2687
0
    break;
2688
0
#ifdef HAVE_IPV6
2689
0
  case AF_INET6:
2690
0
    if (lbsda->u.in6.sin6_port != 0) {
2691
0
      do_reuseaddr = true;
2692
0
      do_bind = true;
2693
0
    }
2694
0
    if (memcmp(&in6addr_any,
2695
0
         &lbsda->u.in6.sin6_addr,
2696
0
         sizeof(in6addr_any)) != 0) {
2697
0
      do_bind = true;
2698
0
    }
2699
0
    is_inet = true;
2700
0
    do_ipv6only = true;
2701
0
    break;
2702
0
#endif
2703
0
  default:
2704
0
    tevent_req_error(req, EINVAL);
2705
0
    goto post;
2706
0
  }
2707
2708
0
  if (!do_bind && is_inet) {
2709
0
    sa_fam = rbsda->u.sa.sa_family;
2710
0
    switch (sa_fam) {
2711
0
    case AF_INET:
2712
0
      do_ipv6only = false;
2713
0
      break;
2714
0
#ifdef HAVE_IPV6
2715
0
    case AF_INET6:
2716
0
      do_ipv6only = true;
2717
0
      break;
2718
0
#endif
2719
0
    }
2720
0
  }
2721
2722
0
  if (is_inet) {
2723
0
    state->local = tsocket_address_create(state,
2724
0
                  &tsocket_address_bsd_ops,
2725
0
                  &lrbsda,
2726
0
                  struct samba_sockaddr,
2727
0
                  __location__ "bsd_connect");
2728
0
    if (tevent_req_nomem(state->local, req)) {
2729
0
      goto post;
2730
0
    }
2731
2732
0
    ZERO_STRUCTP(lrbsda);
2733
0
    lrbsda->sa_socklen = sizeof(lrbsda->u.ss);
2734
#ifdef HAVE_STRUCT_SOCKADDR_SA_LEN
2735
    lrbsda->u.sa.sa_len = lrbsda->sa_socklen;
2736
#endif
2737
0
  }
2738
2739
0
  state->fd = socket(sa_fam, SOCK_STREAM, 0);
2740
0
  if (state->fd == -1) {
2741
0
    tevent_req_error(req, errno);
2742
0
    goto post;
2743
0
  }
2744
2745
0
  state->fd = tsocket_bsd_common_prepare_fd(state->fd, true);
2746
0
  if (state->fd == -1) {
2747
0
    tevent_req_error(req, errno);
2748
0
    goto post;
2749
0
  }
2750
2751
0
#ifdef HAVE_IPV6
2752
0
  if (do_ipv6only) {
2753
0
    int val = 1;
2754
2755
0
    ret = setsockopt(state->fd, IPPROTO_IPV6, IPV6_V6ONLY,
2756
0
         (const void *)&val, sizeof(val));
2757
0
    if (ret == -1) {
2758
0
      tevent_req_error(req, errno);
2759
0
      goto post;
2760
0
    }
2761
0
  }
2762
0
#endif
2763
2764
0
  if (do_reuseaddr) {
2765
0
    int val = 1;
2766
2767
0
    ret = setsockopt(state->fd, SOL_SOCKET, SO_REUSEADDR,
2768
0
         (const void *)&val, sizeof(val));
2769
0
    if (ret == -1) {
2770
0
      tevent_req_error(req, errno);
2771
0
      goto post;
2772
0
    }
2773
0
  }
2774
2775
0
  if (do_bind) {
2776
0
    ret = bind(state->fd, &lbsda->u.sa, lbsda->sa_socklen);
2777
0
    if (ret == -1) {
2778
0
      tevent_req_error(req, errno);
2779
0
      goto post;
2780
0
    }
2781
0
  }
2782
2783
0
  if (rbsda->u.sa.sa_family != sa_fam) {
2784
0
    tevent_req_error(req, EINVAL);
2785
0
    goto post;
2786
0
  }
2787
2788
0
  ret = connect(state->fd, &rbsda->u.sa, rbsda->sa_socklen);
2789
0
  if (ret == -1) {
2790
0
    if (errno == EINPROGRESS) {
2791
0
      goto async;
2792
0
    }
2793
0
    tevent_req_error(req, errno);
2794
0
    goto post;
2795
0
  }
2796
2797
0
  if (!state->local) {
2798
0
    tevent_req_done(req);
2799
0
    goto post;
2800
0
  }
2801
2802
0
  if (lrbsda != NULL) {
2803
0
    ret = getsockname(state->fd,
2804
0
          &lrbsda->u.sa,
2805
0
          &lrbsda->sa_socklen);
2806
0
    if (ret == -1) {
2807
0
      tevent_req_error(req, errno);
2808
0
      goto post;
2809
0
    }
2810
0
  }
2811
2812
0
  tevent_req_done(req);
2813
0
  goto post;
2814
2815
0
 async:
2816
2817
  /*
2818
   * Note for historic reasons TEVENT_FD_WRITE is not enough
2819
   * to get notified for POLLERR or EPOLLHUP even if they
2820
   * come together with POLLOUT. That means we need to
2821
   * use TEVENT_FD_READ in addition until we have
2822
   * TEVENT_FD_ERROR.
2823
   */
2824
0
  state->fde = tevent_add_fd(ev, state,
2825
0
           state->fd,
2826
0
           TEVENT_FD_ERROR | TEVENT_FD_WRITE,
2827
0
           tstream_bsd_connect_fde_handler,
2828
0
           req);
2829
0
  if (tevent_req_nomem(state->fde, req)) {
2830
0
    goto post;
2831
0
  }
2832
2833
0
  return req;
2834
2835
0
 post:
2836
0
  tevent_req_post(req, ev);
2837
0
  return req;
2838
0
}
2839
2840
static void tstream_bsd_connect_fde_handler(struct tevent_context *ev,
2841
              struct tevent_fd *fde,
2842
              uint16_t flags,
2843
              void *private_data)
2844
0
{
2845
0
  struct tevent_req *req = talloc_get_type_abort(private_data,
2846
0
         struct tevent_req);
2847
0
  struct tstream_bsd_connect_state *state = tevent_req_data(req,
2848
0
          struct tstream_bsd_connect_state);
2849
0
  struct samba_sockaddr *lrbsda = NULL;
2850
0
  int ret;
2851
0
  int err;
2852
0
  bool retry;
2853
2854
0
  ret = samba_socket_sock_error(state->fd);
2855
0
  err = tsocket_bsd_error_from_errno(ret, errno, &retry);
2856
0
  if (retry) {
2857
    /* retry later */
2858
0
    return;
2859
0
  }
2860
0
  if (tevent_req_error(req, err)) {
2861
0
    return;
2862
0
  }
2863
2864
0
  if (!state->local) {
2865
0
    tevent_req_done(req);
2866
0
    return;
2867
0
  }
2868
2869
0
  lrbsda = talloc_get_type_abort(state->local->private_data,
2870
0
               struct samba_sockaddr);
2871
2872
0
  ret = getsockname(state->fd, &lrbsda->u.sa, &lrbsda->sa_socklen);
2873
0
  if (ret == -1) {
2874
0
    tevent_req_error(req, errno);
2875
0
    return;
2876
0
  }
2877
2878
0
  tevent_req_done(req);
2879
0
}
2880
2881
static int tstream_bsd_connect_recv(struct tevent_req *req,
2882
            int *perrno,
2883
            TALLOC_CTX *mem_ctx,
2884
            struct tstream_context **stream,
2885
            struct tsocket_address **local,
2886
            const char *location)
2887
0
{
2888
0
  struct tstream_bsd_connect_state *state = tevent_req_data(req,
2889
0
          struct tstream_bsd_connect_state);
2890
0
  int ret;
2891
2892
0
  ret = tsocket_simple_int_recv(req, perrno);
2893
0
  if (ret == 0) {
2894
0
    ret = _tstream_bsd_existing_socket(mem_ctx,
2895
0
               state->fd,
2896
0
               stream,
2897
0
               location);
2898
0
    if (ret == -1) {
2899
0
      *perrno = errno;
2900
0
      goto done;
2901
0
    }
2902
0
    TALLOC_FREE(state->fde);
2903
0
    state->fd = -1;
2904
2905
0
    if (local) {
2906
0
      *local = talloc_move(mem_ctx, &state->local);
2907
0
    }
2908
0
  }
2909
2910
0
done:
2911
0
  tevent_req_received(req);
2912
0
  return ret;
2913
0
}
2914
2915
struct tevent_req * tstream_inet_tcp_connect_send(TALLOC_CTX *mem_ctx,
2916
          struct tevent_context *ev,
2917
          const struct tsocket_address *local,
2918
          const struct tsocket_address *remote)
2919
0
{
2920
0
  struct samba_sockaddr *lbsda =
2921
0
    talloc_get_type_abort(local->private_data,
2922
0
    struct samba_sockaddr);
2923
0
  struct tevent_req *req;
2924
0
  int sys_errno = 0;
2925
2926
0
  switch (lbsda->u.sa.sa_family) {
2927
0
  case AF_INET:
2928
0
    break;
2929
0
#ifdef HAVE_IPV6
2930
0
  case AF_INET6:
2931
0
    break;
2932
0
#endif
2933
0
  default:
2934
0
    sys_errno = EINVAL;
2935
0
    break;
2936
0
  }
2937
2938
0
  req = tstream_bsd_connect_send(mem_ctx, ev, sys_errno, local, remote);
2939
2940
0
  return req;
2941
0
}
2942
2943
int _tstream_inet_tcp_connect_recv(struct tevent_req *req,
2944
           int *perrno,
2945
           TALLOC_CTX *mem_ctx,
2946
           struct tstream_context **stream,
2947
           struct tsocket_address **local,
2948
           const char *location)
2949
0
{
2950
0
  return tstream_bsd_connect_recv(req, perrno,
2951
0
          mem_ctx, stream, local,
2952
0
          location);
2953
0
}
2954
2955
struct tevent_req * tstream_unix_connect_send(TALLOC_CTX *mem_ctx,
2956
          struct tevent_context *ev,
2957
          const struct tsocket_address *local,
2958
          const struct tsocket_address *remote)
2959
0
{
2960
0
  struct samba_sockaddr *lbsda =
2961
0
    talloc_get_type_abort(local->private_data,
2962
0
    struct samba_sockaddr);
2963
0
  struct tevent_req *req;
2964
0
  int sys_errno = 0;
2965
2966
0
  switch (lbsda->u.sa.sa_family) {
2967
0
  case AF_UNIX:
2968
0
    break;
2969
0
  default:
2970
0
    sys_errno = EINVAL;
2971
0
    break;
2972
0
  }
2973
2974
0
  req = tstream_bsd_connect_send(mem_ctx, ev, sys_errno, local, remote);
2975
2976
0
  return req;
2977
0
}
2978
2979
int _tstream_unix_connect_recv(struct tevent_req *req,
2980
              int *perrno,
2981
              TALLOC_CTX *mem_ctx,
2982
              struct tstream_context **stream,
2983
              const char *location)
2984
0
{
2985
0
  return tstream_bsd_connect_recv(req, perrno,
2986
0
          mem_ctx, stream, NULL,
2987
0
          location);
2988
0
}
2989
2990
int _tstream_unix_socketpair(TALLOC_CTX *mem_ctx1,
2991
           struct tstream_context **_stream1,
2992
           TALLOC_CTX *mem_ctx2,
2993
           struct tstream_context **_stream2,
2994
           const char *location)
2995
0
{
2996
0
  int ret;
2997
0
  int fds[2];
2998
0
  int fd1;
2999
0
  int fd2;
3000
0
  struct tstream_context *stream1 = NULL;
3001
0
  struct tstream_context *stream2 = NULL;
3002
3003
0
  ret = socketpair(AF_UNIX, SOCK_STREAM, 0, fds);
3004
0
  if (ret == -1) {
3005
0
    return -1;
3006
0
  }
3007
0
  fd1 = fds[0];
3008
0
  fd2 = fds[1];
3009
3010
0
  fd1 = tsocket_bsd_common_prepare_fd(fd1, true);
3011
0
  if (fd1 == -1) {
3012
0
    int sys_errno = errno;
3013
0
    close(fd2);
3014
0
    errno = sys_errno;
3015
0
    return -1;
3016
0
  }
3017
3018
0
  fd2 = tsocket_bsd_common_prepare_fd(fd2, true);
3019
0
  if (fd2 == -1) {
3020
0
    int sys_errno = errno;
3021
0
    close(fd1);
3022
0
    errno = sys_errno;
3023
0
    return -1;
3024
0
  }
3025
3026
0
  ret = _tstream_bsd_existing_socket(mem_ctx1,
3027
0
             fd1,
3028
0
             &stream1,
3029
0
             location);
3030
0
  if (ret == -1) {
3031
0
    int sys_errno = errno;
3032
0
    close(fd1);
3033
0
    close(fd2);
3034
0
    errno = sys_errno;
3035
0
    return -1;
3036
0
  }
3037
3038
0
  ret = _tstream_bsd_existing_socket(mem_ctx2,
3039
0
             fd2,
3040
0
             &stream2,
3041
0
             location);
3042
0
  if (ret == -1) {
3043
0
    int sys_errno = errno;
3044
0
    talloc_free(stream1);
3045
0
    close(fd2);
3046
0
    errno = sys_errno;
3047
0
    return -1;
3048
0
  }
3049
3050
0
  *_stream1 = stream1;
3051
0
  *_stream2 = stream2;
3052
0
  return 0;
3053
0
}
3054