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