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