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