The FreeRADIUS server $Id: a4e7f8c94e8038b7627bcf52356b7ed15955c1d7 $
Loading...
Searching...
No Matches
fd.c
Go to the documentation of this file.
1/*
2 * This program is free software; you can redistribute it and/or modify
3 * it under the terms of the GNU General Public License as published by
4 * the Free Software Foundation; either version 2 of the License, or (at
5 * your option) any later version.
6 *
7 * This program is distributed in the hope that it will be useful,
8 * but WITHOUT ANY WARRANTY; without even the implied warranty of
9 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
10 * GNU General Public License for more details.
11 *
12 * You should have received a copy of the GNU General Public License
13 * along with this program; if not, write to the Free Software
14 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
15 */
16
17/**
18 * $Id: a7762af93055263c2ceed71f06fc8102b6f5d8a4 $
19 * @file lib/bio/fd.c
20 * @brief BIO abstractions for file descriptors
21 *
22 * @copyright 2024 Network RADIUS SAS (legal@networkradius.com)
23 */
24
25#include <freeradius-devel/bio/fd_priv.h>
26#include <freeradius-devel/bio/fd_read.h>
27#include <freeradius-devel/bio/fd_write.h>
28#include <freeradius-devel/bio/null.h>
29
30/*
31 * More portability idiocy
32 * Mac OSX Lion doesn't define SOL_IP. But IPPROTO_IP works.
33 */
34#ifndef SOL_IP
35# define SOL_IP IPPROTO_IP
36#endif
37
38/*
39 * glibc 2.4 and uClibc 0.9.29 introduce IPV6_RECVPKTINFO etc. and
40 * change IPV6_PKTINFO This is only supported in Linux kernel >=
41 * 2.6.14
42 *
43 * This is only an approximation because the kernel version that libc
44 * was compiled against could be older or newer than the one being
45 * run. But this should not be a problem -- we just keep using the
46 * old kernel interface.
47 */
48#ifdef __linux__
49# ifdef IPV6_RECVPKTINFO
50# include <linux/version.h>
51# if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,14)
52# ifdef IPV6_2292PKTINFO
53# undef IPV6_RECVPKTINFO
54# undef IPV6_PKTINFO
55# define IPV6_RECVPKTINFO IPV6_2292PKTINFO
56# define IPV6_PKTINFO IPV6_2292PKTINFO
57# endif
58# endif
59/* Fall back to the legacy socket option if IPV6_RECVPKTINFO isn't defined */
60# elif defined(IPV6_2292PKTINFO)
61# define IPV6_RECVPKTINFO IPV6_2292PKTINFO
62# endif
63#else
64
65/*
66 * For everything that's not Linux we assume RFC 3542 compliance
67 * - setsockopt() takes IPV6_RECVPKTINFO
68 * - cmsg_type is IPV6_PKTINFO (in sendmsg, recvmsg)
69 *
70 * If we don't have IPV6_RECVPKTINFO defined but do have IPV6_PKTINFO
71 * defined, chances are the API is RFC2292 compliant and we need to use
72 * IPV6_PKTINFO for both.
73 */
74# if !defined(IPV6_RECVPKTINFO) && defined(IPV6_PKTINFO)
75# define IPV6_RECVPKTINFO IPV6_PKTINFO
76
77/*
78 * Ensure IPV6_RECVPKTINFO is not defined somehow if we have we
79 * don't have IPV6_PKTINFO.
80 */
81# elif !defined(IPV6_PKTINFO)
82# undef IPV6_RECVPKTINFO
83# endif
84#endif
85
86#define ADDR_INIT do { \
87 addr->when = fr_time(); \
88 addr->socket.type = my->info.socket.type; \
89 addr->socket.fd = -1; \
90 addr->socket.inet.ifindex = my->info.socket.inet.ifindex; \
91 } while (0)
92
93/** Orderly shutdown.
94 *
95 */
97{
98 int rcode;
99 fr_bio_fd_t *my = talloc_get_type_abort(bio, fr_bio_fd_t);
100
101 if (my->info.state == FR_BIO_FD_STATE_CLOSED) return 0;
102
103 FR_TIMER_DELETE(&my->connect.ev);
104 if (my->connect.el) {
106 my->connect.el = NULL;
107 }
108
109 rcode = fr_bio_fd_close(&my->bio);
110 if (rcode < 0) return rcode;
111
112 /*
113 * A Unix domain socket has a path in the file system, which has to be removed.
114 *
115 * This is done on shutdown rather than in fr_bio_fd_close(), because a close leaves the bio
116 * alive and able to be re-opened, and a shutdown destroys it.
117 */
118 if (my->info.socket.af == AF_LOCAL) return fr_bio_fd_unix_shutdown(&my->bio);
119
120 return 0;
121}
122
123static int fr_bio_fd_eof(fr_bio_t *bio)
124{
125 fr_bio_fd_t *my = talloc_get_type_abort(bio, fr_bio_fd_t);
126
127 my->info.eof = true;
128
129 /*
130 * A read returns zero, which is what EOF means to the caller.
131 *
132 * A write returns "this BIO was shutdown", which is true for both BIOs at EOF, and BIOs which
133 * were shut down due to an error.
134 */
135 bio->read = fr_bio_null_read;
137
138 /*
139 * Nothing more for us to do, tell fr_bio_eof() that it can continue with poking other BIOs.
140 */
141 return 1;
142}
143
145{
146 fr_bio_fd_t *my = talloc_get_type_abort(bio, fr_bio_fd_t);
147
148 my->info.write_blocked = false;
149 return 1;
150}
151
152/** Stream read.
153 *
154 * Stream sockets return 0 at EOF. However, we want to distinguish that from the case of datagram
155 * sockets, which return 0 when there's no data. So we return 0 to the caller for "no data", but also
156 * call the EOF function to tell all of the related BIOs that we're at EOF.
157 */
158static ssize_t fr_bio_fd_read_stream(fr_bio_t *bio, UNUSED void *packet_ctx, void *buffer, size_t size)
159{
160 int tries = 0;
161 ssize_t rcode;
162 fr_bio_fd_t *my = talloc_get_type_abort(bio, fr_bio_fd_t);
163
164 do {
165 rcode = read(my->info.socket.fd, buffer, size);
166 if (rcode == 0) {
167 fr_bio_t *head;
168
169 /*
170 * Flush any pending writes, shut down the BIO, and then mark it as EOF.
171 */
172 head = fr_bio_head(bio);
173
174 (void) fr_bio_write(head, NULL, NULL, SIZE_MAX);
175
176 /*
177 * Shut down through this bio, not through the head. fr_bio_shutdown() walks
178 * back up from here, so that any bio holding data can hand it to the
179 * application before the chain is torn down.
180 */
181 rcode = fr_bio_shutdown(bio);
182 if (rcode < 0) return rcode;
183
184 return 0;
185 }
186 } while (fr_bio_fd_read_retry(my, &rcode, &tries));
187
188 return rcode;
189}
190
191/** Connected datagram read.
192 *
193 * The difference between this and stream protocols is that for datagrams. a read of zero means "no packets",
194 * where a read of zero on a steam socket means "EOF".
195 *
196 * Connected sockets do _not_ update per-packet contexts.
197 */
199{
200 int tries = 0;
201 ssize_t rcode;
202 fr_bio_fd_t *my = talloc_get_type_abort(bio, fr_bio_fd_t);
203 socklen_t salen;
204 struct sockaddr_storage sockaddr;
205
206#ifdef STATIC_ANALYZER
207 sockaddr = (struct sockaddr_storage) {};
208#endif
209
210 do {
211 salen = sizeof(sockaddr);
212
213 rcode = recvfrom(my->info.socket.fd, buffer, size, 0, (struct sockaddr *) &sockaddr, &salen);
214 if (rcode > 0) {
215 fr_assert(salen == my->remote_sockaddr_len);
216 fr_assert(sockaddr.ss_family == my->remote_sockaddr.ss_family);
217 fr_assert((sockaddr.ss_family == AF_INET) || (sockaddr.ss_family == AF_INET6)); /* datagram unix is not supported */
218 }
219
220 /*
221 * We do NOT call fr_bio_eof(), as 0 just means "no more data".
222 */
223 if (rcode == 0) return rcode;
224 } while (fr_bio_fd_read_retry(my, &rcode, &tries));
225
226 return rcode;
227}
228
229/** Return the datagram which fr_bio_fd_accept() read from the listening socket
230 *
231 * fr_bio_fd_accept_datagram() has to read the datagram in order to name the peer, so the datagram is no
232 * longer in the socket. The first read returns the saved datagram, and then switches to reading the
233 * connected socket.
234 *
235 * A datagram which is larger than the buffer is truncated, in the same way as a read of the socket.
236 */
238{
239 fr_bio_fd_t *my = talloc_get_type_abort(bio, fr_bio_fd_t);
240 size_t len;
241
242 fr_assert(my->first_datagram != NULL);
243
245 if (len > size) len = size;
246
247 memcpy(buffer, my->first_datagram, len);
248
249 TALLOC_FREE(my->first_datagram);
250 my->first_datagram_len = 0;
251
253
254 return len;
255}
256
257/** Read from a UDP socket where we know our IP
258 */
259static ssize_t fr_bio_fd_recvfrom(fr_bio_t *bio, void *packet_ctx, void *buffer, size_t size)
260{
261 int tries = 0;
262 ssize_t rcode;
263 fr_bio_fd_t *my = talloc_get_type_abort(bio, fr_bio_fd_t);
264 socklen_t salen;
265 struct sockaddr_storage sockaddr;
266
267 do {
268 salen = sizeof(sockaddr);
269
270 rcode = recvfrom(my->info.socket.fd, buffer, size, 0, (struct sockaddr *) &sockaddr, &salen);
271 if (rcode > 0) {
273
274 ADDR_INIT;
275
276 addr->socket.inet.dst_ipaddr = my->info.socket.inet.src_ipaddr;
277 addr->socket.inet.dst_port = my->info.socket.inet.src_port;
278
279 (void) fr_ipaddr_from_sockaddr(&addr->socket.inet.src_ipaddr, &addr->socket.inet.src_port,
280 &sockaddr, salen);
281 }
282
283 if (rcode == 0) return rcode;
284 } while (fr_bio_fd_read_retry(my, &rcode, &tries));
285
286 return rcode;
287}
288
289/** Write to fd.
290 *
291 * This function is used for connected sockets, where we ignore the packet_ctx.
292 */
293static ssize_t fr_bio_fd_write(fr_bio_t *bio, UNUSED void *packet_ctx, const void *buffer, size_t size)
294{
295 int tries = 0;
296 ssize_t rcode;
297 fr_bio_fd_t *my = talloc_get_type_abort(bio, fr_bio_fd_t);
298
299 /*
300 * FD bios do nothing on flush.
301 */
302 if (!buffer) return 0;
303
304 do {
305 /*
306 * We could call send() instead of write()! Posix says:
307 *
308 * "A write was attempted on a socket that is shut down for writing, or is no longer
309 * connected. In the latter case, if the socket is of type SOCK_STREAM, a SIGPIPE signal shall
310 * also be sent to the thread."
311 *
312 * We can override this behavior by calling send(), and passing the special flag which says
313 * "don't do that!". The system call will then return EPIPE, which indicates that the socket is
314 * no longer usable.
315 *
316 * However, we also set the SO_NOSIGPIPE socket option, which means that we can just call write()
317 * here.
318 */
319 rcode = write(my->info.socket.fd, buffer, size);
320 } while (fr_bio_fd_write_retry(my, &rcode, &tries, size));
321
322 return rcode;
323}
324
325/** Write to a UDP socket where we know our IP
326 *
327 */
328static ssize_t fr_bio_fd_sendto(fr_bio_t *bio, void *packet_ctx, const void *buffer, size_t size)
329{
330 int tries = 0;
331 ssize_t rcode;
332 fr_bio_fd_t *my = talloc_get_type_abort(bio, fr_bio_fd_t);
334 socklen_t salen;
335 struct sockaddr_storage sockaddr;
336
337 /*
338 * FD bios do nothing on flush.
339 */
340 if (!buffer) return 0;
341
342 // get destination IP
343 (void) fr_ipaddr_to_sockaddr(&sockaddr, &salen, &addr->socket.inet.dst_ipaddr, addr->socket.inet.dst_port);
344
345 do {
346 rcode = sendto(my->info.socket.fd, buffer, size, 0, (struct sockaddr *) &sockaddr, salen);
347 } while (fr_bio_fd_write_retry(my, &rcode, &tries, size));
348
350
351 return rcode;
352}
353
354
355#if defined(IP_PKTINFO) || defined(IP_RECVDSTADDR) || defined(IPV6_PKTINFO)
356static ssize_t fd_fd_recvfromto_common(fr_bio_fd_t *my, void *packet_ctx, void *buffer, size_t size)
357{
358 int tries = 0;
359 ssize_t rcode;
360 struct sockaddr_storage from;
362
363#ifdef STATIC_ANALYZER
364 from.ss_family = AF_UNSPEC;
365#endif
366
367 memset(&my->cbuf, 0, sizeof(my->cbuf));
368 memset(&my->msgh, 0, sizeof(struct msghdr));
369
370 my->iov = (struct iovec) {
371 .iov_base = buffer,
372 .iov_len = size,
373 };
374
375 my->msgh = (struct msghdr) {
376 .msg_control = my->cbuf,
377 .msg_controllen = sizeof(my->cbuf),
378 .msg_name = &from,
379 .msg_namelen = sizeof(from),
380 .msg_iov = &my->iov,
381 .msg_iovlen = 1,
382 .msg_flags = 0,
383 };
384
385 do {
386 rcode = recvmsg(my->info.socket.fd, &my->msgh, 0);
387 if (rcode > 0) {
388 if ((my->msgh.msg_flags & MSG_TRUNC) != 0) return 0;
389 if ((my->msgh.msg_flags & MSG_CTRUNC) != 0) return 0;
390
391 ADDR_INIT;
392
393 (void) fr_ipaddr_from_sockaddr(&addr->socket.inet.src_ipaddr, &addr->socket.inet.src_port,
394 &from, my->msgh.msg_namelen);
395 }
396
397 if (rcode == 0) return rcode;
398 } while (fr_bio_fd_read_retry(my, &rcode, &tries));
399
400 return rcode;
401}
402#endif
403
404#if defined(IP_PKTINFO) || defined(IP_RECVDSTADDR)
405
406/** Read from a UDP socket where we can change our IP, IPv4 version.
407 */
408static ssize_t fr_bio_fd_recvfromto4(fr_bio_t *bio, void *packet_ctx, void *buffer, size_t size)
409{
410 ssize_t rcode;
411 struct cmsghdr *cmsg;
412 fr_time_t when = fr_time_wrap(0);
413 fr_bio_fd_t *my = talloc_get_type_abort(bio, fr_bio_fd_t);
415
416 rcode = fd_fd_recvfromto_common(my, packet_ctx, buffer, size);
417 if (rcode <= 0) return rcode;
418
419DIAG_OFF(sign-compare)
420 /* Process auxiliary received data in msgh */
421 for (cmsg = CMSG_FIRSTHDR(&my->msgh);
422 cmsg != NULL;
423 cmsg = CMSG_NXTHDR(&my->msgh, cmsg)) {
424DIAG_ON(sign-compare)
425
426#ifdef IP_PKTINFO
427 if ((cmsg->cmsg_level == SOL_IP) &&
428 (cmsg->cmsg_type == IP_PKTINFO)) {
429 struct in_pktinfo *i = (struct in_pktinfo *) CMSG_DATA(cmsg);
430 struct sockaddr_in to = {
431 .sin_family = AF_INET,
432 .sin_addr = i->ipi_addr,
433 .sin_port = htons(my->info.socket.inet.src_port),
434 };
435
436 (void) fr_ipaddr_from_sockaddr(&addr->socket.inet.dst_ipaddr, &addr->socket.inet.dst_port,
437 (struct sockaddr_storage *) &to, sizeof(struct sockaddr_in));
438 addr->socket.inet.ifindex = i->ipi_ifindex;
439 break;
440 }
441#endif
442
443#ifdef IP_RECVDSTADDR
444 if ((cmsg->cmsg_level == IPPROTO_IP) &&
445 (cmsg->cmsg_type == IP_RECVDSTADDR)) {
446 struct in_addr *i = (struct in_addr *) CMSG_DATA(cmsg);
447 struct sockaddr_in to = {
448 .sin_family = AF_INET,
449 .sin_addr = *i,
450 .sin_port = htons(my->info.socket.inet.src_port),
451 };
452
453 (void) fr_ipaddr_from_sockaddr(&addr->socket.inet.dst_ipaddr, &addr->socket.inet.dst_port,
454 (struct sockaddr_storage *) &to, sizeof(struct sockaddr_in));
455 break;
456 }
457#endif
458
459#ifdef SO_TIMESTAMPNS
460 if ((cmsg->cmsg_level == SOL_SOCKET) && (cmsg->cmsg_type == SO_TIMESTAMPNS)) {
461 when = fr_time_from_timespec((struct timespec *)CMSG_DATA(cmsg));
462 }
463
464#elif defined(SO_TIMESTAMP)
465 if ((cmsg->cmsg_level == SOL_SOCKET) && (cmsg->cmsg_type == SO_TIMESTAMP)) {
466 when = fr_time_from_timeval((struct timeval *)CMSG_DATA(cmsg));
467 }
468#endif
469 }
470
471 if fr_time_eq(when, fr_time_wrap(0)) when = fr_time();
472
473 addr->when = when;
474
475 return rcode;
476}
477
478/** Send to UDP socket where we can change our IP, IPv4 version.
479 */
480static ssize_t fr_bio_fd_sendfromto4(fr_bio_t *bio, void *packet_ctx, const void *buffer, size_t size)
481{
482 int tries = 0;
483 ssize_t rcode;
484 struct cmsghdr *cmsg;
485 struct sockaddr_storage to;
486 socklen_t to_len;
487 fr_bio_fd_t *my = talloc_get_type_abort(bio, fr_bio_fd_t);
489
490 memset(&my->cbuf, 0, sizeof(my->cbuf));
491 memset(&my->msgh, 0, sizeof(struct msghdr));
492
493 (void) fr_ipaddr_to_sockaddr(&to, &to_len, &addr->socket.inet.dst_ipaddr, addr->socket.inet.dst_port);
494
495 my->iov = (struct iovec) {
496 .iov_base = UNCONST(void *, buffer),
497 .iov_len = size,
498 };
499
500 my->msgh = (struct msghdr) {
501 .msg_control = my->cbuf,
502 // controllen is set below
503 .msg_name = &to,
504 .msg_namelen = to_len,
505 .msg_iov = &my->iov,
506 .msg_iovlen = 1,
507 .msg_flags = 0,
508 };
509
510 {
511#ifdef IP_PKTINFO
512 struct in_pktinfo *pkt;
513
514 my->msgh.msg_controllen = CMSG_SPACE(sizeof(*pkt));
515
516 cmsg = CMSG_FIRSTHDR(&my->msgh);
517 cmsg->cmsg_level = SOL_IP;
518 cmsg->cmsg_type = IP_PKTINFO;
519 cmsg->cmsg_len = CMSG_LEN(sizeof(*pkt));
520
521 pkt = (struct in_pktinfo *) CMSG_DATA(cmsg);
522 memset(pkt, 0, sizeof(*pkt));
523 pkt->ipi_spec_dst = addr->socket.inet.src_ipaddr.addr.v4;
524 pkt->ipi_ifindex = addr->socket.inet.ifindex;
525
526#elif defined(IP_SENDSRCADDR)
527 struct in_addr *in;
528
529 my->msgh.msg_controllen = CMSG_SPACE(sizeof(*in));
530
531 cmsg = CMSG_FIRSTHDR(&my->msgh);
532 cmsg->cmsg_level = IPPROTO_IP;
533 cmsg->cmsg_type = IP_SENDSRCADDR;
534 cmsg->cmsg_len = CMSG_LEN(sizeof(*in));
535
536 in = (struct in_addr *) CMSG_DATA(cmsg);
537 *in = addr->socket.inet.src_ipaddr.addr.v4;
538#endif
539 }
540
541 do {
542 rcode = sendmsg(my->info.socket.fd, &my->msgh, 0);
543 } while (fr_bio_fd_write_retry(my, &rcode, &tries, size));
544
546
547 return rcode;
548}
549
550static inline int fr_bio_fd_udpfromto_init4(int fd)
551{
552 int proto = 0, flag = 0, opt = 1;
553
554#ifdef HAVE_IP_PKTINFO
555 /*
556 * Linux
557 */
558 proto = SOL_IP;
559 flag = IP_PKTINFO;
560
561#elif defined(IP_RECVDSTADDR)
562 /*
563 * Set the IP_RECVDSTADDR option (BSD). Note:
564 * IP_RECVDSTADDR == IP_SENDSRCADDR
565 */
566 proto = IPPROTO_IP;
567 flag = IP_RECVDSTADDR;
568#endif
569
570 return setsockopt(fd, proto, flag, &opt, sizeof(opt));
571}
572#endif
573
574#if defined(IPV6_PKTINFO)
575/** Read from a UDP socket where we can change our IP, IPv4 version.
576 */
577static ssize_t fr_bio_fd_recvfromto6(fr_bio_t *bio, void *packet_ctx, void *buffer, size_t size)
578{
579 ssize_t rcode;
580 struct cmsghdr *cmsg;
581 fr_time_t when = fr_time_wrap(0);
582 fr_bio_fd_t *my = talloc_get_type_abort(bio, fr_bio_fd_t);
584
585 rcode = fd_fd_recvfromto_common(my, packet_ctx, buffer, size);
586 if (rcode <= 0) return rcode;
587
588DIAG_OFF(sign-compare)
589 /* Process auxiliary received data in msgh */
590 for (cmsg = CMSG_FIRSTHDR(&my->msgh);
591 cmsg != NULL;
592 cmsg = CMSG_NXTHDR(&my->msgh, cmsg)) {
593DIAG_ON(sign-compare)
594
595 if ((cmsg->cmsg_level == IPPROTO_IPV6) &&
596 (cmsg->cmsg_type == IPV6_PKTINFO)) {
597 struct in6_pktinfo *i = (struct in6_pktinfo *) CMSG_DATA(cmsg);
598 struct sockaddr_in6 to = {
599 .sin6_family = AF_INET6,
600 .sin6_addr = i->ipi6_addr,
601 .sin6_port = htons(my->info.socket.inet.src_port),
602 .sin6_scope_id = my->info.socket.inet.src_ipaddr.scope_id,
603 };
604
605 (void) fr_ipaddr_from_sockaddr(&addr->socket.inet.dst_ipaddr, &addr->socket.inet.dst_port,
606 (struct sockaddr_storage *) &to, sizeof(struct sockaddr_in6));
607 addr->socket.inet.ifindex = i->ipi6_ifindex;
608 break;
609 }
610
611#ifdef SO_TIMESTAMPNS
612 if ((cmsg->cmsg_level == SOL_SOCKET) && (cmsg->cmsg_type == SO_TIMESTAMPNS)) {
613 when = fr_time_from_timespec((struct timespec *)CMSG_DATA(cmsg));
614 }
615
616#elif defined(SO_TIMESTAMP)
617 if ((cmsg->cmsg_level == SOL_SOCKET) && (cmsg->cmsg_type == SO_TIMESTAMP)) {
618 when = fr_time_from_timeval((struct timeval *)CMSG_DATA(cmsg));
619 }
620#endif
621 }
622
623 if fr_time_eq(when, fr_time_wrap(0)) when = fr_time();
624
625 addr->when = when;
626
627 return rcode;
628}
629
630/** Send to UDP socket where we can change our IP, IPv6 version.
631 */
632static ssize_t fr_bio_fd_sendfromto6(fr_bio_t *bio, void *packet_ctx, const void *buffer, size_t size)
633{
634 int tries = 0;
635 ssize_t rcode;
636 struct cmsghdr *cmsg;
637 struct sockaddr_storage to;
638 socklen_t to_len;
639 fr_bio_fd_t *my = talloc_get_type_abort(bio, fr_bio_fd_t);
641
642 memset(&my->cbuf, 0, sizeof(my->cbuf));
643 memset(&my->msgh, 0, sizeof(struct msghdr));
644
645 (void) fr_ipaddr_to_sockaddr(&to, &to_len, &addr->socket.inet.dst_ipaddr, addr->socket.inet.dst_port);
646
647 my->iov = (struct iovec) {
648 .iov_base = UNCONST(void *, buffer),
649 .iov_len = size,
650 };
651
652 my->msgh = (struct msghdr) {
653 .msg_control = my->cbuf,
654 // controllen is set below
655 .msg_name = &to,
656 .msg_namelen = to_len,
657 .msg_iov = &my->iov,
658 .msg_iovlen = 1,
659 .msg_flags = 0,
660 };
661
662 {
663 struct in6_pktinfo *pkt;
664
665 my->msgh.msg_controllen = CMSG_SPACE(sizeof(*pkt));
666
667 cmsg = CMSG_FIRSTHDR(&my->msgh);
668 cmsg->cmsg_level = IPPROTO_IPV6;
669 cmsg->cmsg_type = IPV6_PKTINFO;
670 cmsg->cmsg_len = CMSG_LEN(sizeof(*pkt));
671
672 pkt = (struct in6_pktinfo *) CMSG_DATA(cmsg);
673 memset(pkt, 0, sizeof(*pkt));
674 pkt->ipi6_addr = addr->socket.inet.src_ipaddr.addr.v6;
675 pkt->ipi6_ifindex = addr->socket.inet.ifindex;
676 }
677
678 do {
679 rcode = sendmsg(my->info.socket.fd, &my->msgh, 0);
680 } while (fr_bio_fd_write_retry(my, &rcode, &tries, size));
681
683
684 return rcode;
685}
686
687
688static inline int fr_bio_fd_udpfromto_init6(int fd)
689{
690 int opt = 1;
691
692 return setsockopt(fd, IPPROTO_IPV6, IPV6_RECVPKTINFO, &opt, sizeof(opt));
693}
694#endif
695
696int fr_filename_to_sockaddr(struct sockaddr_un *sun, socklen_t *sunlen, char const *filename)
697{
698 size_t len;
699
700 len = strlen(filename);
701 if (len >= sizeof(sun->sun_path)) {
702 fr_strerror_const("Failed parsing unix domain socket filename: Name is too long");
703 return -1;
704 }
705
706 sun->sun_family = AF_LOCAL;
707 memcpy(sun->sun_path, filename, len + 1); /* SUN_LEN will do strlen */
708
709 *sunlen = SUN_LEN(sun);
710
711 return 0;
712}
713
715{
716 socklen_t salen;
717 struct sockaddr_storage salocal;
718
719 /*
720 * Already set: do nothing.
721 */
722 if (!fr_ipaddr_is_inaddr_any(&my->info.socket.inet.src_ipaddr) &&
723 (my->info.socket.inet.src_port != 0)) {
724 return 0;
725 }
726
727 /*
728 * FreeBSD jail issues. We bind to 0.0.0.0, but the
729 * kernel instead binds us to a 1.2.3.4. So once the
730 * socket is bound, ask it what it's IP address is.
731 */
732 salen = sizeof(salocal);
733 memset(&salocal, 0, salen);
734 if (getsockname(my->info.socket.fd, (struct sockaddr *) &salocal, &salen) < 0) {
735 fr_strerror_printf("Failed getting socket name: %s", fr_syserror(errno));
736 return -1;
737 }
738
739 if (fr_ipaddr_from_sockaddr(&my->info.socket.inet.src_ipaddr, &my->info.socket.inet.src_port, &salocal, salen) < 0) return -1;
740
741 fr_ipaddr_get_scope_id(&my->info.socket.inet.src_ipaddr);
742 my->info.socket.inet.ifindex = my->info.socket.inet.src_ipaddr.scope_id;
743
744 return 0;
745}
746
748{
750 my->info.eof = false;
751 my->info.read_blocked = false;
752 my->info.write_blocked = false;
753
754 if (my->connect.el) (void) fr_event_fd_delete(my->connect.el, my->info.socket.fd, FR_EVENT_FILTER_IO);
755
756 /*
757 * Run the connect success callback if defined.
758 */
759 if (my->connect.success) my->connect.success(&my->bio);
760
761 /*
762 * Tell the caller that the socket is ready for application data.
763 */
764 if (my->cb.connected) my->cb.connected(&my->bio);
765}
766
767
768/** Try to connect().
769 *
770 * If connect is blocking, we either succeed or error immediately. Otherwise, the caller has to select the
771 * socket for writeability, and then call fr_bio_fd_connect() as soon as the socket is writeable.
772 */
774{
775 int tries = 0;
776 int rcode;
777
778 /*
779 * Save a "sockaddr" version of the address of the other end.
780 */
781 if (my->info.socket.af != AF_LOCAL) {
783 &my->info.socket.inet.dst_ipaddr, my->info.socket.inet.dst_port);
784 } else {
785 rcode = fr_filename_to_sockaddr((struct sockaddr_un *) &my->remote_sockaddr, &my->remote_sockaddr_len,
786 my->info.socket.unix.path);
787 }
788
789 if (rcode < 0) {
790 my->info.connect_errno = errno;
791 (void) fr_bio_shutdown(&my->bio);
792 return fr_bio_error(GENERIC);
793 }
794
796
797retry:
798 if (connect(my->info.socket.fd, (struct sockaddr *) &my->remote_sockaddr, my->remote_sockaddr_len) == 0) {
799 connected:
800 /*
801 * The source IP may have changed, so get the new one.
802 */
803 if (fr_bio_fd_socket_name(my) < 0) goto fail;
804
805 /*
806 * Install the read / write routines, and then call fr_bio_fd_set_open().
807 */
808 if (fr_bio_fd_init_common(my) < 0) goto fail;
809
810 return 0;
811 }
812
813 switch (errno) {
814 /*
815 * When a connect is deferred, the event loop eventually calls us again when the socket
816 * is writable. If the handshake has finished, the second connect() returns EISCONN,
817 * which means that the socket is already connected. That indicates a success.
818 */
819 case EISCONN:
820 goto connected;
821
822 case EINTR:
823 tries++;
824 if (tries <= my->max_tries) goto retry;
826
827 /*
828 * This shouldn't happen, but we'll allow it
829 */
830 case EALREADY:
832
833 /*
834 * Once the socket is writable, it will be active, or in an error state. The caller has
835 * to call fr_bio_fd_connect() before calling write()
836 */
837 case EINPROGRESS:
838 my->info.connect_errno = errno;
839
840 if (!my->info.write_blocked) {
841 my->info.write_blocked = true;
842
843 rcode = fr_bio_write_blocked((fr_bio_t *) my);
844 if (rcode < 0) return rcode;
845 }
846
847 return fr_bio_error(IO_WOULD_BLOCK);
848
849 default:
850 break;
851 }
852
853 /*
854 * There was a fatal error in connect().
855 */
856 my->info.connect_errno = errno;
857 fr_strerror_printf("Failed connecting socket: %s", fr_syserror(errno));
858
859fail:
860 (void) fr_bio_shutdown(&my->bio);
861 return fr_bio_error(IO);
862}
863
864
865/** Files are a special case of connected sockets.
866 *
867 */
869{
870 /*
871 * Other flags may be O_CREAT, etc.
872 */
873 switch (my->info.cfg->flags & (O_RDONLY | O_WRONLY | O_RDWR)) {
874 case O_RDONLY:
875 my->bio.read = fr_bio_fd_read_stream;
876 my->bio.write = fr_bio_fail_write;
877 break;
878
879 case O_WRONLY:
880 my->bio.read = fr_bio_fail_read;
881 my->bio.write = fr_bio_fd_write;
882 break;
883
884 case O_RDWR:
885 my->bio.read = fr_bio_fd_read_stream;
886 my->bio.write = fr_bio_fd_write;
887 break;
888
889 default:
890 fr_strerror_const("Invalid flag for opening file");
891 return -1;
892 }
893
895
896 return 0;
897}
898
899/** This FD isn't connected.
900 *
901 */
903{
904 errno = ENOTCONN;
905
906 return fr_bio_error(IO);
907}
908
909#ifdef SO_NOSIGPIPE
910/** Stop the kernel raising SIGPIPE when a write finds that the peer closed the socket
911 *
912 * Although the server ignores SIGPIPE, some operating systems like BSD and OSX ignore the ignoring.
913 *
914 * Fortunately, those operating systems usually support SO_NOSIGPIPE. We set that to prevent them
915 * raising the signal in the first place.
916 *
917 * Every stream socket needs this, including a socket which the BIO accepted. A TLS BIO can write a
918 * close_notify alert to a peer which has already closed the socket.
919 */
920static void fr_bio_fd_no_sigpipe(int fd)
921{
922 int on = 1;
923
924 (void) setsockopt(fd, SOL_SOCKET, SO_NOSIGPIPE, &on, sizeof(on));
925}
926#else
927# define fr_bio_fd_no_sigpipe(_x)
928#endif
929
931{
932 int rcode;
933
934 if (my->info.socket.af == AF_FR_FILENAME) return fr_bio_fd_init_file(my);
935
936 /*
937 * The source IP can be unspecified. It will get updated after we call connect().
938 */
939
940 /*
941 * All connected sockets must have a destination IP.
942 */
943 if (((my->info.socket.af == AF_INET) || (my->info.socket.af == AF_INET6)) &&
944 fr_ipaddr_is_inaddr_any(&my->info.socket.inet.dst_ipaddr)) {
945 fr_strerror_const("Destination IP address cannot be wildcard");
946 return -1;
947 }
948
949 /*
950 * Don't do any reads until we're connected.
951 */
952 my->bio.read = fr_bio_fd_notconn_read;
953 my->bio.write = fr_bio_null_write;
954
955 my->info.eof = false;
956
957 my->info.read_blocked = false;
958 my->info.write_blocked = false;
959
961
962 /*
963 * Call connect() for both synchronous and asynchronous sockets.
964 *
965 * A synchronous socket blocks until the connection succeeds or fails.
966 *
967 * An asynchronous socket kicks off the TCP side of connect(), and the answer will eventually
968 * come back.
969 */
970 rcode = fr_bio_fd_try_connect(my);
971 if (rcode == 0) return 0;
972
973 if (rcode != fr_bio_error(IO_WOULD_BLOCK)) return rcode;
974
975 /*
976 * We got here via EINPROGRESS, so we must be blocked, and in the connecting state.
977 */
978 fr_assert(my->info.cfg->async);
981
982 return 0;
983}
984
986{
987 if (my->info.socket.type == SOCK_STREAM) { //!< stream socket
988 my->bio.read = fr_bio_fd_read_stream;
989 my->bio.write = fr_bio_fd_write;
990
991 } else if (my->info.type == FR_BIO_FD_CONNECTED) { //!< connected datagram
993 my->bio.write = fr_bio_fd_write;
994
995 } else if (!fr_ipaddr_is_inaddr_any(&my->info.socket.inet.src_ipaddr)) { //!< we know our IP address
996 my->bio.read = fr_bio_fd_recvfrom;
997 my->bio.write = fr_bio_fd_sendto;
998
999#if defined(IP_PKTINFO) || defined(IP_RECVDSTADDR)
1000 } else if (my->info.socket.inet.src_ipaddr.af == AF_INET) { //!< we don't know our IPv4
1001 if (fr_bio_fd_udpfromto_init4(my->info.socket.fd) < 0) return -1;
1002
1003 my->bio.read = fr_bio_fd_recvfromto4;
1004 my->bio.write = fr_bio_fd_sendfromto4;
1005#endif
1006
1007#if defined(IPV6_PKTINFO)
1008 } else if (my->info.socket.inet.src_ipaddr.af == AF_INET6) { //!< we don't know our IPv6
1009
1010 if (fr_bio_fd_udpfromto_init6(my->info.socket.fd) < 0) return -1;
1011
1012 my->bio.read = fr_bio_fd_recvfromto6;
1013 my->bio.write = fr_bio_fd_sendfromto6;
1014#endif
1015
1016 } else {
1017 fr_strerror_const("Failed initializing socket: cannot determine what to do");
1018 return -1;
1019 }
1020
1022
1023 return 0;
1024}
1025
1027{
1028 /*
1029 * A listening socket supports neither read nor write, so both routines return an error. The
1030 * caller calls fr_bio_fd_accept() to get each new connection.
1031 */
1032 my->bio.read = fr_bio_fail_read;
1033 my->bio.write = fr_bio_fail_write;
1034
1035 /*
1036 * A datagram socket has no queue of connections, so there is nothing to listen for.
1037 * fr_bio_fd_accept_datagram() reads the datagrams.
1038 */
1039 /*
1040 * fr_bio_fd_accept_datagram() reads each datagram into this buffer, which is allocated once.
1041 */
1042 if ((my->info.socket.type == SOCK_DGRAM) && !my->accept_buffer) {
1043 my->accept_buffer = talloc_array(my, uint8_t, FR_BIO_FD_MAX_DATAGRAM);
1044 if (!my->accept_buffer) return fr_bio_error(OOM);
1045 }
1046
1047 /*
1048 * A datagram listener on a wildcard address needs the destination address of each datagram,
1049 * so that fr_bio_fd_accept_datagram() can bind the new socket to that address.
1050 */
1051 if ((my->info.socket.type == SOCK_DGRAM) && fr_ipaddr_is_inaddr_any(&my->info.socket.inet.src_ipaddr)) {
1052#if defined(IP_PKTINFO) || defined(IP_RECVDSTADDR)
1053 if ((my->info.socket.inet.src_ipaddr.af == AF_INET) &&
1054 (fr_bio_fd_udpfromto_init4(my->info.socket.fd) < 0)) {
1055 fr_strerror_printf("Failed enabling destination addresses: %s", fr_syserror(errno));
1056 return fr_bio_error(IO);
1057 }
1058#endif
1059
1060#if defined(IPV6_PKTINFO)
1061 if ((my->info.socket.inet.src_ipaddr.af == AF_INET6) &&
1062 (fr_bio_fd_udpfromto_init6(my->info.socket.fd) < 0)) {
1063 fr_strerror_printf("Failed enabling destination addresses: %s", fr_syserror(errno));
1064 return fr_bio_error(IO);
1065 }
1066#endif
1067 }
1068
1069 if ((my->info.socket.type == SOCK_STREAM) &&
1070 (listen(my->info.socket.fd, my->info.cfg->backlog_is_set ? my->info.cfg->backlog : 8) < 0)) {
1071 fr_strerror_printf("Failed calling listen() %s", fr_syserror(errno));
1072 return fr_bio_error(IO);
1073 }
1074
1076
1077 return 0;
1078}
1079
1080/** Allocate a FD bio
1081 *
1082 * The caller is responsible for tracking the FD, and all associated management of it. The bio API is
1083 * intended to be simple, and does not provide wrapper functions for various ioctls. The caller should
1084 * instead do that work.
1085 *
1086 * Once the FD is give to the bio, its lifetime is "owned" by the bio. Calling talloc_free(bio) will close
1087 * the FD.
1088 *
1089 * The caller can still manage the FD for being readable / writeable. However, the caller should not call
1090 * this bio directly (unless it is the only one). Instead, the caller should read from / write to the
1091 * previous bio which will then eventually call this one.
1092 *
1093 * Before updating any event handler readable / writeable callbacks, the caller should check
1094 * fr_bio_fd_at_eof(). If true, then the handlers should not be inserted. The previous bios should still be
1095 * called to process any pending data, until they return EOF.
1096 *
1097 * The main purpose of an FD bio is to wrap the FD in a bio container. That, and handling retries on read /
1098 * write, along with returning EOF as an error instead of zero.
1099 *
1100 * Note that the read / write functions can return partial data. It is the callers responsibility to ensure
1101 * that any writes continue from where they left off (otherwise dat awill be missing). And any partial reads
1102 * should go to a memory bio.
1103 *
1104 * If a read returns EOF, then the FD remains open until talloc_free(bio) or fr_bio_fd_close() is called.
1105 *
1106 * The bio caches the cfg pointer, so the configuration has to live at least as long as the bio does.
1107 * See fr_bio_fd_open().
1108 *
1109 * @param ctx the talloc ctx
1110 * @param cfg structure holding the configuration information
1111 * @param offset only for unconnected datagram sockets, where #fr_bio_fd_packet_ctx_t is stored
1112 * @return
1113 * - NULL on error, memory allocation failed
1114 * - !NULL the bio
1115 */
1116fr_bio_t *fr_bio_fd_alloc(TALLOC_CTX *ctx, fr_bio_fd_config_t const *cfg, size_t offset)
1117{
1118 fr_bio_fd_t *my;
1119
1120 my = talloc_zero(ctx, fr_bio_fd_t);
1121 if (!my) return NULL;
1122
1123 my->max_tries = 4;
1124 my->offset = offset;
1125
1126 if (!cfg) {
1127 /*
1128 * Add place-holder information.
1129 */
1130 my->info = (fr_bio_fd_info_t) {
1131 .socket = {
1132 .af = AF_UNSPEC,
1133 .fd = -1,
1134 },
1135 .type = FR_BIO_FD_UNCONNECTED,
1136 .read_blocked = false,
1137 .write_blocked = false,
1138 .eof = false,
1139 .state = FR_BIO_FD_STATE_CLOSED,
1140 };
1141
1142 my->bio.read = fr_bio_null_read;
1143 my->bio.write = fr_bio_null_write;
1144 } else {
1146
1147 if (fr_bio_fd_open(&my->bio, cfg) < 0) {
1148 talloc_free(my);
1149 return NULL;
1150 }
1151 }
1152
1153 my->priv_cb.eof = fr_bio_fd_eof;
1154 my->priv_cb.write_resume = fr_bio_fd_write_resume;
1155 my->priv_cb.shutdown = fr_bio_fd_shutdown;
1156
1157 talloc_set_destructor((fr_bio_t *) my, fr_bio_destructor); /* always use a common destructor */
1158 return (fr_bio_t *) my;
1159}
1160
1161/** Close the FD, but leave the bio allocated and alive.
1162 *
1163 */
1165{
1166 fr_bio_fd_t *my = talloc_get_type_abort(bio, fr_bio_fd_t);
1167
1168 if (my->info.state == FR_BIO_FD_STATE_CLOSED) return 0;
1169
1170 my->bio.read = fr_bio_shutdown_read;
1171 my->bio.write = fr_bio_shutdown_write;
1172
1173 /*
1174 * Shut down the connected socket. The only errors possible here are things we can't do anything
1175 * about.
1176 *
1177 * shutdown() will close ALL versions of this file descriptor, even if it's (somehow) used in
1178 * another process. shutdown() will also tell the kernel to gracefully close the connected
1179 * socket, so that it can signal the other end, instead of having the connection disappear.
1180 *
1181 * This shouldn't strictly be necessary, as no other processes should be sharing this file
1182 * descriptor. But it's the safe (and polite) thing to do.
1183 */
1185 (void) shutdown(my->info.socket.fd, SHUT_RDWR);
1186 }
1187
1188 if (my->info.socket.fd >= 0) (void) close(my->info.socket.fd);
1189
1191 my->info.read_blocked = true;
1192 my->info.write_blocked = true;
1193 my->info.eof = true;
1194 my->info.socket.fd = -1;
1195
1196 return 0;
1197}
1198
1199/** FD error when trying to connect, give up on the BIO.
1200 *
1201 */
1202static void fr_bio_fd_el_error(UNUSED fr_event_list_t *el, UNUSED int fd, UNUSED int flags, int fd_errno, void *uctx)
1203{
1204 fr_bio_fd_t *my = talloc_get_type_abort(uctx, fr_bio_fd_t);
1205
1206 my->info.connect_errno = fd_errno;
1207
1208 /*
1209 * The entire bio is unusable.
1210 */
1212 (void) fr_bio_shutdown(&my->bio);
1213 }
1214
1215 /*
1216 * It's possible that the bio may be freed in the error callback,
1217 * especially if it signals a connection to reconnect, potentially
1218 * feeing the original connection handle.
1219 */
1220 if (my->connect.error) {
1221 my->connect.error(&my->bio);
1222 }
1223}
1224
1225/** Connect callback for when the socket is writable.
1226 *
1227 * We try to connect the socket, and if so, call the application which should update the BIO status.
1228 */
1230{
1231 int rcode;
1232 fr_bio_fd_t *my = talloc_get_type_abort(uctx, fr_bio_fd_t);
1233
1236 fr_assert(my->connect.el == el); /* and not NULL */
1237 fr_assert(my->connect.success != NULL);
1238 fr_assert(my->info.socket.fd == fd);
1239
1240#ifndef NDEBUG
1241 /*
1242 * This check shouldn't be necessary, as we have a kqeueue error callback. That should be called
1243 * when there's a connect error.
1244 */
1245 {
1246 int error;
1247 socklen_t socklen = sizeof(error);
1248
1249 /*
1250 * The socket is writeable. Let's see if there's an error.
1251 *
1252 * Unix Network Programming says:
1253 *
1254 * ""If so_error is nonzero when the process calls write, -1 is returned with errno set to the
1255 * value of SO_ERROR (p. 495 of TCPv2) and SO_ERROR is reset to 0. We have to check for the
1256 * error, and if there's no error, set the state to "open". ""
1257 *
1258 * The same applies to connect(). If a non-blocking connect returns INPROGRESS, it may later
1259 * become writable. It will be writable even if the connection fails. Rather than writing some
1260 * random application data, we call SO_ERROR, and get the underlying error.
1261 */
1262 if (getsockopt(my->info.socket.fd, SOL_SOCKET, SO_ERROR, (void *)&error, &socklen) < 0) {
1263 fr_bio_fd_el_error(el, fd, flags, errno, uctx);
1264 return;
1265 }
1266
1267 /*
1268 * There was an error, we call the error handler.
1269 */
1270 if (error) {
1271 fr_bio_fd_el_error(el, fd, flags, error, uctx);
1272 return;
1273 }
1274 }
1275#endif
1276
1277 /*
1278 * Try to connect it. Any magic handling is done in the callbacks.
1279 *
1280 * On WOULD_BLOCK, leave the timers, etc. open.
1281 *
1282 * Otherwise the try_connect() function has shut down the BIO.
1283 */
1284 rcode = fr_bio_fd_try_connect(my);
1285 if (rcode == fr_bio_error(IO_WOULD_BLOCK)) return;
1286
1287 if (rcode < 0) {
1288 FR_TIMER_DELETE(&my->connect.ev);
1289 my->connect.el = NULL;
1290
1291 /*
1292 * Tell the application that the connect failed.
1293 *
1294 * fr_bio_fd_try_connect() has already recorded connect_errno and shut the bio down,
1295 * and the shutdown deleted the timer and the FD event. Reporting the failure is all
1296 * that is left, and without it a failed connect here is silent: the synchronous path
1297 * in fr_bio_fd_connect_full() reports it, and this path did not.
1298 *
1299 * Whether this runs depends on which event the event loop delivers. A connect which
1300 * fails usually arrives as EV_EOF, which event.c turns into the error callback, and
1301 * fr_bio_fd_el_error() reports it. This function runs when the socket is merely
1302 * writeable, and nothing else reports the failure for us.
1303 *
1304 * The callback may free the bio, so nothing below touches `my`.
1305 */
1306 if (my->connect.error) my->connect.error(&my->bio);
1307 return;
1308 }
1309
1310 /*
1311 * my->connect.success was already called from fr_bio_fd_set_open().
1312 */
1313
1314 FR_TIMER_DELETE(&my->connect.ev);
1315 my->connect.el = NULL;
1316}
1317
1318/** We have a timeout on the conenction
1319 *
1320 */
1322{
1323 fr_bio_fd_t *my = talloc_get_type_abort(uctx, fr_bio_fd_t);
1324
1325 fr_assert(my->connect.timeout);
1326
1327 my->connect.timeout(&my->bio);
1328
1329 (void) fr_bio_shutdown(&my->bio);
1330}
1331
1332
1333/** Finalize a connect()
1334 *
1335 * connect() said "come back when the socket is writeable". It's now writeable, so we check if there was a
1336 * connection error.
1337 *
1338 * @param bio the binary IO handler
1339 * @param el the event list
1340 * @param connected_cb callback to run when the BIO is connected
1341 * @param error_cb callback to run when the FD has an error
1342 * @param timeout when to time out the connect() attempt
1343 * @param timeout_cb to call when the timeout runs.
1344 * @return
1345 * - <0 on error
1346 * - 0 for "try again later". If callbacks are set, the callbacks will try again. Otherwise the application has to try again.
1347 * - 1 for "we are now connected".
1348 */
1350 fr_bio_callback_t error_cb,
1351 fr_time_delta_t *timeout, fr_bio_callback_t timeout_cb)
1352{
1353 fr_bio_fd_t *my = talloc_get_type_abort(bio, fr_bio_fd_t);
1354
1355 /*
1356 * We shouldn't be connected an unconnected socket.
1357 */
1358 if (my->info.type == FR_BIO_FD_UNCONNECTED) {
1359 error:
1360#ifdef ECONNABORTED
1361 my->info.connect_errno = ECONNABORTED;
1362#else
1363 my->info.connect_errno = ECONNREFUSED;
1364#endif
1365 if (error_cb) error_cb(bio);
1366 (void) fr_bio_shutdown(&my->bio);
1367 return fr_bio_error(GENERIC);
1368 }
1369
1370 /*
1371 * The initial open may have succeeded in connecting the socket. In which case we just run the
1372 * callbacks and return.
1373 */
1374 if (my->info.state == FR_BIO_FD_STATE_OPEN) {
1375 connected:
1376 if (connected_cb) connected_cb(bio);
1377
1378 return 1;
1379 }
1380
1381 /*
1382 * The caller may just call us without caring about what the underlying BIO is. In which case we
1383 * need to be safe.
1384 */
1385 if ((my->info.socket.af == AF_FR_FILENAME) || (my->info.type == FR_BIO_FD_LISTEN)) {
1387 goto connected;
1388 }
1389
1390 /*
1391 * It must be in the connecting state, i.e. not INVALID or CLOSED.
1392 */
1393 if (my->info.state != FR_BIO_FD_STATE_CONNECTING) goto error;
1394
1395 /*
1396 * No callback
1397 */
1398 if (!connected_cb) {
1399 int rcode;
1400
1401 rcode = fr_bio_fd_try_connect(my);
1402 if (rcode < 0) {
1403 if (error_cb) error_cb(bio);
1404 return rcode; /* it already called shutdown */
1405 }
1406
1407 return 1;
1408 }
1409
1410 /*
1411 * It's not connected, the caller has to try again.
1412 */
1413 if (!el) return 0;
1414
1415 /*
1416 * Set the callbacks to run when something happens.
1417 */
1418 my->connect.success = connected_cb;
1419 my->connect.error = error_cb;
1420 my->connect.timeout = timeout_cb;
1421
1422 /*
1423 * Set the timeout callback if asked.
1424 */
1425 if (timeout_cb) {
1426 if (fr_timer_in(my, el->tl, &my->connect.ev, *timeout, false, fr_bio_fd_el_timeout, my) < 0) {
1427 goto error;
1428 }
1429 }
1430
1431 /*
1432 * Set the FD callbacks, and tell the caller that we're not connected.
1433 */
1434 if (fr_event_fd_insert(my, NULL, el, my->info.socket.fd, NULL,
1436 goto error;
1437 }
1438 my->connect.el = el;
1439
1440 return 0;
1441}
1442
1443/** Returns a pointer to the bio-specific information.
1444 *
1445 */
1447{
1448 fr_bio_fd_t *my = talloc_get_type_abort(bio, fr_bio_fd_t);
1449
1450 return &my->info;
1451}
1452
1453
1454/** Discard all reads from a UDP socket.
1455 */
1457{
1458 int tries = 0;
1459 ssize_t rcode;
1460 fr_bio_fd_t *my = talloc_get_type_abort(bio, fr_bio_fd_t);
1461
1462 do {
1463 rcode = read(my->info.socket.fd, buffer, size);
1464 if (rcode >= 0) return 0; /* always return that we read no data */
1465 } while (fr_bio_fd_errno_retry(my, &rcode, &tries, false));
1466
1467 return rcode;
1468}
1469
1470/** Discard all reads from a TCP socket.
1471 */
1473{
1474 int tries = 0;
1475 ssize_t rcode;
1476 fr_bio_fd_t *my = talloc_get_type_abort(bio, fr_bio_fd_t);
1477
1478 do {
1479 rcode = read(my->info.socket.fd, buffer, size);
1480 if (rcode > 0 ) return 0; /* always return that we read no data */
1481 if (rcode == 0) {
1482 fr_bio_eof(bio);
1483 return 0;
1484 }
1485 } while (fr_bio_fd_errno_retry(my, &rcode, &tries, false));
1486
1487 return rcode;
1488}
1489
1490/** Mark up a bio as write-only
1491 *
1492 */
1494{
1495 fr_bio_fd_t *my = talloc_get_type_abort(bio, fr_bio_fd_t);
1496
1497 switch (my->info.type) {
1498 case FR_BIO_FD_INVALID:
1499 return -1;
1500
1502 if (my->info.socket.type != SOCK_DGRAM) {
1503 fr_strerror_const("Only datagram sockets can be marked 'write-only'");
1504 return -1;
1505 }
1506 goto set_recv_buff_zero;
1507
1509 /*
1510 * Further reads are disallowed. However, this likely has no effect for UDP sockets.
1511 */
1513
1514 if (shutdown(my->info.socket.fd, SHUT_RD) < 0) {
1515 fr_strerror_printf("Failed shutting down connected socket - %s", fr_syserror(errno));
1516 return -1;
1517 }
1518
1519 set_recv_buff_zero:
1520#ifdef __linux__
1521#ifdef SO_RCVBUF
1522 /*
1523 * On Linux setting the receive buffer to zero has the effect of discarding all incoming
1524 * data in the kernel. With macOS and others it's an invalid value.
1525 */
1526 {
1527 int opt = 0;
1528
1529 if (setsockopt(my->info.socket.fd, SOL_SOCKET, SO_RCVBUF, &opt, sizeof(opt)) < 0) {
1530 fr_strerror_printf("Failed setting SO_RCVBUF: %s", fr_syserror(errno));
1531 return -1;
1532 }
1533 }
1534#endif
1535#endif
1536 break;
1537
1538 case FR_BIO_FD_LISTEN:
1539 fr_strerror_const("Only unconnected sockets can be marked 'write-only'");
1540 return -1;
1541 }
1542
1543 /*
1544 * No matter what the possibilities above, we replace the read function with a "discard"
1545 * function.
1546 */
1547 my->bio.read = (my->info.socket.type == SOCK_DGRAM) ? fr_bio_fd_read_discard_datagram : fr_bio_fd_read_discard_stream;
1548 return 0;
1549}
1550
1551#if !defined(__linux__) && !defined(__FreeBSD__)
1552static int inline accept4(int fd, struct sockaddr *sockaddr, socklen_t *salen, UNUSED int flags)
1553{
1554 fd = accept(fd, sockaddr, salen);
1555 if (fd >= 0) {
1556 if ((fr_nonblock(fd) < 0) || (fr_cloexec(fd) < 0)) {
1557 int our_errno = errno;
1558
1559 /*
1560 * The caller reads errno to decide whether to
1561 * retry, and close() may overwrite it.
1562 */
1563 close(fd);
1564 errno = our_errno;
1565 return -1;
1566 }
1567 }
1568
1569 return fd;
1570}
1571#ifndef SOCK_NONBLOCK
1572#define SOCK_NONBLOCK 0
1573#endif
1574
1575#ifndef SOCK_CLOEXEC
1576#define SOCK_CLOEXEC 0
1577#endif
1578#endif
1579
1580/** Accept a stream socket and initialize its flags.
1581 *
1582 */
1584{
1585 int fd, tries = 0;
1586
1587 my->remote_sockaddr_len = sizeof(my->remote_sockaddr);
1588
1589retry:
1590 /*
1591 * Set these flags immediately on the new socket.
1592 */
1593 fd = accept4(parent->info.socket.fd, (struct sockaddr *) &my->remote_sockaddr, &my->remote_sockaddr_len,
1595 if (fd < 0) {
1596 switch (errno) {
1597#if defined(EWOULDBLOCK) && (EWOULDBLOCK != EAGAIN)
1598 case EWOULDBLOCK:
1599#endif
1600 case EAGAIN:
1601 return 0;
1602
1603 /*
1604 * Try a few times before giving up.
1605 */
1606 case EINTR:
1607 tries++;
1608 if (tries <= my->max_tries) goto retry;
1609 break;
1610
1611 default:
1612 break;
1613 }
1614
1615 return fr_bio_error(IO);
1616 }
1617
1618 /*
1619 * The socket is now open. Save the new state.
1620 */
1621 my->info.socket.fd = fd;
1622
1623 return 1;
1624}
1625
1626
1627/** Receive a datagram, and find the address which the datagram was sent to
1628 *
1629 * A wildcard listener asks the kernel for the destination address of each datagram, which arrives as a
1630 * control message. A listener bound to one address has no need of the control message, as every datagram
1631 * was sent to that address.
1632 *
1633 * @param[in] parent the listening bio.
1634 * @param[in] buffer of #FR_BIO_FD_MAX_DATAGRAM octets.
1635 * @param[in] flags for recvmsg().
1636 * @param[out] from the source of the datagram.
1637 * @param[out] from_len length of the source.
1638 * @param[out] dst the destination of the datagram. `af` is AF_UNSPEC when the kernel did not
1639 * say.
1640 * @return
1641 * - >=0 size of the datagram.
1642 * - <0 on error, with `errno` set.
1643 */
1645 struct sockaddr_storage *from, socklen_t *from_len, fr_ipaddr_t *dst)
1646{
1647 ssize_t slen;
1648 struct iovec iov = { .iov_base = buffer, .iov_len = FR_BIO_FD_MAX_DATAGRAM };
1649 uint8_t cbuf[CMSG_SPACE(sizeof(struct in6_pktinfo)) + CMSG_SPACE(sizeof(struct timespec))];
1650 struct msghdr msgh = {
1651 .msg_control = cbuf,
1652 .msg_controllen = sizeof(cbuf),
1653 .msg_name = from,
1654 .msg_namelen = sizeof(*from),
1655 .msg_iov = &iov,
1656 .msg_iovlen = 1,
1657 };
1658 struct cmsghdr *cmsg;
1659
1660 *dst = (fr_ipaddr_t) { .af = AF_UNSPEC };
1661
1662 slen = recvmsg(parent->info.socket.fd, &msgh, flags);
1663 if (slen < 0) return slen;
1664
1665 *from_len = msgh.msg_namelen;
1666
1667 /*
1668 * A listener bound to one address.
1669 */
1670 if (!fr_ipaddr_is_inaddr_any(&parent->info.socket.inet.src_ipaddr)) {
1671 *dst = parent->info.socket.inet.src_ipaddr;
1672 return slen;
1673 }
1674
1675DIAG_OFF(sign-compare)
1676 for (cmsg = CMSG_FIRSTHDR(&msgh); cmsg != NULL; cmsg = CMSG_NXTHDR(&msgh, cmsg)) {
1677DIAG_ON(sign-compare)
1678 struct sockaddr_storage to;
1679
1680#ifdef IP_PKTINFO
1681 if ((cmsg->cmsg_level == SOL_IP) && (cmsg->cmsg_type == IP_PKTINFO)) {
1682 struct in_pktinfo *i = (struct in_pktinfo *) CMSG_DATA(cmsg);
1683
1684 memset(&to, 0, sizeof(to));
1685 ((struct sockaddr_in *) &to)->sin_family = AF_INET;
1686 ((struct sockaddr_in *) &to)->sin_addr = i->ipi_addr;
1687 if (fr_ipaddr_from_sockaddr(dst, NULL, &to, sizeof(struct sockaddr_in)) == 0) break;
1688 }
1689#endif
1690
1691#ifdef IP_RECVDSTADDR
1692 if ((cmsg->cmsg_level == IPPROTO_IP) && (cmsg->cmsg_type == IP_RECVDSTADDR)) {
1693 struct in_addr *i = (struct in_addr *) CMSG_DATA(cmsg);
1694
1695 memset(&to, 0, sizeof(to));
1696 ((struct sockaddr_in *) &to)->sin_family = AF_INET;
1697 ((struct sockaddr_in *) &to)->sin_addr = *i;
1698 if (fr_ipaddr_from_sockaddr(dst, NULL, &to, sizeof(struct sockaddr_in)) == 0) break;
1699 }
1700#endif
1701
1702#ifdef IPV6_PKTINFO
1703 if ((cmsg->cmsg_level == IPPROTO_IPV6) && (cmsg->cmsg_type == IPV6_PKTINFO)) {
1704 struct in6_pktinfo *i = (struct in6_pktinfo *) CMSG_DATA(cmsg);
1705
1706 memset(&to, 0, sizeof(to));
1707 ((struct sockaddr_in6 *) &to)->sin6_family = AF_INET6;
1708 ((struct sockaddr_in6 *) &to)->sin6_addr = i->ipi6_addr;
1709 ((struct sockaddr_in6 *) &to)->sin6_scope_id = i->ipi6_ifindex;
1710 if (fr_ipaddr_from_sockaddr(dst, NULL, &to, sizeof(struct sockaddr_in6)) == 0) break;
1711 }
1712#endif
1713 }
1714
1715 return slen;
1716}
1717
1718/** Accept a "connection" on a datagram listening socket
1719 *
1720 * This function is really only useful for DTLS. A datagram socket has no connections, so a connection is
1721 * made by taking the source IP and port of the first datagram, and opening a new socket which is connected
1722 * to that peer. The kernel then delivers the datagrams of that peer to the new socket in preference to the
1723 * listening socket. This only works when the peer sends one stream of datagrams. Other UDP applications
1724 * can have several datagrams from the same source IP waiting in the listening socket, and those datagrams
1725 * stay in the listening socket.
1726 *
1727 * The new bio is a copy of the listening bio, except that it is a connected socket. It has its own file
1728 * descriptor, as connect() is a property of the socket and not of the descriptor, so dup() would connect the
1729 * listening socket. The new socket needs SO_REUSEPORT, as the new socket is bound to the address which the
1730 * datagram was sent to, and the port of the listening socket. That address can be more specific than the
1731 * address of the listening socket, when the listening socket is bound to a wildcard.
1732 *
1733 * The datagram is read directly into a buffer which belongs to the listening bio, and which is allocated
1734 * once when the listening bio opens. The one read gives the datagram, the source, and the destination. The
1735 * datagram is out of the socket before the new socket exists, so if the new socket cannot be opened, the
1736 * datagram is lost. The peer retransmits, as a lost datagram looks like any other lost datagram.
1737 *
1738 * The datagram which named the peer is saved in the new bio. The first read of the new bio returns the
1739 * saved datagram. The datagram is no longer in the kernel, so no event loop will tell the application that
1740 * the new socket is readable. `info.read_blocked` is false, and the application MUST call fr_bio_read()
1741 * once after fr_bio_fd_accept() returns, and then it can wait for events as usual.
1742 *
1743 * @param[in] ctx to allocate the new bio in.
1744 * @param[out] out_p the new bio.
1745 * @param[in] parent the listening datagram bio.
1746 * @return
1747 * - <0 on error
1748 * - 0 for "no datagram is waiting"
1749 * - 1 for "the new bio is available"
1750 */
1751static int fr_bio_fd_accept_datagram(TALLOC_CTX *ctx, fr_bio_t **out_p, fr_bio_fd_t *parent)
1752{
1754 fr_bio_fd_config_t *cfg;
1755 struct sockaddr_storage peer;
1756 socklen_t peer_len;
1757 fr_ipaddr_t peer_ipaddr, dst_ipaddr;
1758 uint16_t peer_port;
1759 ssize_t slen;
1760 int tries = 0;
1761 int rcode;
1762
1763 fr_assert(parent->info.socket.type == SOCK_DGRAM);
1764 fr_assert(parent->accept_buffer != NULL);
1765
1766retry:
1767 /*
1768 * Read the datagram, with its source and destination. The buffer is big enough for any
1769 * datagram, so the return value is the real size.
1770 */
1771 slen = fr_bio_fd_recvmsg_dst(parent, parent->accept_buffer, 0, &peer, &peer_len, &dst_ipaddr);
1772 if (slen < 0) {
1773 switch (errno) {
1774#if defined(EWOULDBLOCK) && (EWOULDBLOCK != EAGAIN)
1775 case EWOULDBLOCK:
1776#endif
1777 case EAGAIN:
1778 return 0;
1779
1780 case EINTR:
1781 tries++;
1782 if (tries <= parent->max_tries) goto retry;
1783 break;
1784
1785 default:
1786 break;
1787 }
1788
1789 fr_strerror_printf("Failed reading the first datagram: %s", fr_syserror(errno));
1790 return fr_bio_error(IO);
1791 }
1792
1793 if (dst_ipaddr.af == AF_UNSPEC) {
1794 fr_strerror_const("Cannot find the address which the first datagram was sent to");
1795 return fr_bio_error(GENERIC);
1796 }
1797
1798 if (fr_ipaddr_from_sockaddr(&peer_ipaddr, &peer_port, &peer, peer_len) < 0) {
1799 fr_strerror_const("Failed getting the address of the peer");
1800 return fr_bio_error(GENERIC);
1801 }
1802
1803 out = (fr_bio_fd_t *) fr_bio_fd_alloc(ctx, NULL, parent->offset);
1804 if (!out) return fr_bio_error(OOM);
1805
1806 /*
1807 * The configuration of the new bio belongs to the new bio. It is the configuration of the
1808 * listening bio, except that the new bio is connected to the peer, and bound to the address
1809 * which the datagram was sent to.
1810 */
1811 cfg = talloc_zero(out, fr_bio_fd_config_t);
1812 if (!cfg) {
1814 return fr_bio_error(OOM);
1815 }
1816
1817 *cfg = *parent->info.cfg;
1819 cfg->server = false;
1820 cfg->reuse_port = true;
1821 cfg->src_ipaddr = dst_ipaddr;
1822 cfg->dst_ipaddr = peer_ipaddr;
1823 cfg->dst_port = peer_port;
1824
1825 /*
1826 * Open a new UDP socket with SO_REUSEPORT, bind it, and connect it to the peer.
1827 */
1828 rcode = fr_bio_fd_open(&out->bio, cfg);
1829 if (rcode < 0) {
1831 return rcode;
1832 }
1833
1834 /*
1835 * The buffer belongs to the listening bio, so the new bio gets a copy.
1836 */
1837 out->first_datagram = talloc_memdup(out, parent->accept_buffer, slen ? (size_t) slen : 1);
1838 if (!out->first_datagram) {
1840 return fr_bio_error(OOM);
1841 }
1842 out->first_datagram_len = (size_t) slen;
1843
1844 /*
1845 * The first read returns the saved datagram. The saved datagram is not in the socket, so the
1846 * application has to read the bio without waiting for an event.
1847 */
1849 out->info.read_blocked = false;
1850
1851 *out_p = (fr_bio_t *) out;
1852 return 1;
1853}
1854
1855/** Accept a new connection on a socket.
1856 *
1857 */
1858int fr_bio_fd_accept(TALLOC_CTX *ctx, fr_bio_t **out_p, fr_bio_t *bio)
1859{
1860 int rcode;
1861 fr_bio_fd_t *my = talloc_get_type_abort(bio, fr_bio_fd_t);
1863
1864 *out_p = NULL;
1865
1867
1868 if (my->info.socket.type == SOCK_DGRAM) return fr_bio_fd_accept_datagram(ctx, out_p, my);
1869
1870 /*
1871 * Allocate the base BIO and set it up.
1872 */
1873 out = (fr_bio_fd_t *) fr_bio_fd_alloc(ctx, NULL, my->offset);
1874 if (!out) return fr_bio_error(OOM);
1875
1876 /*
1877 * Initialize the new BIO information.
1878 */
1879 out->info.cfg = my->info.cfg;
1880
1881 /*
1882 * Copy all socket fields, including ones which will be over-written later.
1883 */
1884 out->info.socket = my->info.socket;
1885 out->info.socket.fd = -1;
1886 out->info.type = FR_BIO_FD_CONNECTED;
1887
1888 /*
1889 * Accept the socket:
1890 *
1891 * - <0 for error
1892 * - 0 for "nothing to do", typically because of EAGAIN.
1893 * - 1 for "we have a new socket"
1894 */
1895 fr_assert(my->info.socket.type == SOCK_STREAM);
1896 rcode = fr_bio_fd_accept_stream(out, my);
1897 if (rcode <= 0) {
1899 return rcode;
1900 }
1901
1902 /*
1903 * If it's an IP socket, update the remote_sockaddr.
1904 */
1905 if ((out->info.socket.af == AF_INET) || (out->info.socket.af == AF_INET6)) {
1906 fr_ipaddr_from_sockaddr(&out->info.socket.inet.dst_ipaddr, &out->info.socket.inet.dst_port,
1907 &out->remote_sockaddr, out->remote_sockaddr_len);
1908 }
1909
1910 rcode = fr_bio_fd_init_common(out);
1911 if (rcode < 0) {
1912 fail:
1913 talloc_free(out); /* the destructor closes the FD */
1914 return rcode;
1915 }
1916
1917 fr_bio_fd_no_sigpipe(out->info.socket.fd);
1918
1920 if (!out->info.name) {
1921 rcode = fr_bio_error(OOM);
1922 goto fail;
1923 }
1924
1925 *out_p = (fr_bio_t *) out;
1926 return 1;
1927}
static int const char char buffer[256]
Definition acutest.h:641
fr_bio_write_t _CONST write
write to the underlying bio
Definition base.h:117
fr_bio_read_t _CONST read
read from the underlying bio
Definition base.h:116
static ssize_t fr_bio_write(fr_bio_t *bio, void *packet_ctx, void const *buffer, size_t size)
Write raw data to a bio.
Definition base.h:184
static fr_bio_t * fr_bio_head(fr_bio_t *bio)
Definition base.h:140
void(* fr_bio_callback_t)(fr_bio_t *bio)
Definition base.h:86
#define fr_bio_error(_x)
Definition base.h:200
static int packet_ctx
the tests pass only the address of packet_ctx
#define UNCONST(_type, _ptr)
Remove const qualification from a pointer.
Definition build.h:203
#define NDEBUG_UNUSED
Definition build.h:426
#define FALL_THROUGH
clang 10 doesn't recognised the FALL-THROUGH comment anymore
Definition build.h:422
#define DIAG_ON(_x)
Definition build.h:576
#define UNUSED
Definition build.h:415
#define DIAG_OFF(_x)
Definition build.h:575
#define fr_event_fd_insert(...)
Definition event.h:247
@ FR_EVENT_FILTER_IO
Combined filter for read/write functions/.
Definition event.h:83
int fr_bio_fd_connect_full(fr_bio_t *bio, fr_event_list_t *el, fr_bio_callback_t connected_cb, fr_bio_callback_t error_cb, fr_time_delta_t *timeout, fr_bio_callback_t timeout_cb)
Finalize a connect()
Definition fd.c:1349
static ssize_t fr_bio_fd_notconn_read(UNUSED fr_bio_t *bio, UNUSED void *packet_ctx, UNUSED void *buffer, UNUSED size_t size)
This FD isn't connected.
Definition fd.c:902
static ssize_t fr_bio_fd_write(fr_bio_t *bio, UNUSED void *packet_ctx, const void *buffer, size_t size)
Write to fd.
Definition fd.c:293
static ssize_t fr_bio_fd_read_first_datagram(fr_bio_t *bio, UNUSED void *packet_ctx, void *buffer, size_t size)
Return the datagram which fr_bio_fd_accept() read from the listening socket.
Definition fd.c:237
int fr_bio_fd_socket_name(fr_bio_fd_t *my)
Definition fd.c:714
static int fr_bio_fd_try_connect(fr_bio_fd_t *my)
Try to connect().
Definition fd.c:773
static void fr_bio_fd_el_connect(NDEBUG_UNUSED fr_event_list_t *el, NDEBUG_UNUSED int fd, NDEBUG_UNUSED int flags, void *uctx)
Connect callback for when the socket is writable.
Definition fd.c:1229
#define ADDR_INIT
Definition fd.c:86
static int fr_bio_fd_write_resume(fr_bio_t *bio)
Definition fd.c:144
fr_bio_t * fr_bio_fd_alloc(TALLOC_CTX *ctx, fr_bio_fd_config_t const *cfg, size_t offset)
Allocate a FD bio.
Definition fd.c:1116
static ssize_t fr_bio_fd_read_discard_stream(fr_bio_t *bio, UNUSED void *packet_ctx, void *buffer, size_t size)
Discard all reads from a TCP socket.
Definition fd.c:1472
static int accept4(int fd, struct sockaddr *sockaddr, socklen_t *salen, UNUSED int flags)
Definition fd.c:1552
int fr_bio_fd_init_connected(fr_bio_fd_t *my)
Definition fd.c:930
static ssize_t fr_bio_fd_read_connected_datagram(fr_bio_t *bio, UNUSED void *packet_ctx, void *buffer, size_t size)
Connected datagram read.
Definition fd.c:198
static ssize_t fr_bio_fd_recvfrom(fr_bio_t *bio, void *packet_ctx, void *buffer, size_t size)
Read from a UDP socket where we know our IP.
Definition fd.c:259
#define fr_bio_fd_no_sigpipe(_x)
Definition fd.c:927
#define SOL_IP
Definition fd.c:35
static int fr_bio_fd_eof(fr_bio_t *bio)
Definition fd.c:123
static ssize_t fr_bio_fd_sendto(fr_bio_t *bio, void *packet_ctx, const void *buffer, size_t size)
Write to a UDP socket where we know our IP.
Definition fd.c:328
int fr_filename_to_sockaddr(struct sockaddr_un *sun, socklen_t *sunlen, char const *filename)
Definition fd.c:696
int fr_bio_fd_init_listen(fr_bio_fd_t *my)
Definition fd.c:1026
int fr_bio_fd_accept(TALLOC_CTX *ctx, fr_bio_t **out_p, fr_bio_t *bio)
Accept a new connection on a socket.
Definition fd.c:1858
fr_bio_fd_info_t const * fr_bio_fd_info(fr_bio_t *bio)
Returns a pointer to the bio-specific information.
Definition fd.c:1446
static int fr_bio_fd_accept_datagram(TALLOC_CTX *ctx, fr_bio_t **out_p, fr_bio_fd_t *parent)
Accept a "connection" on a datagram listening socket.
Definition fd.c:1751
static int fr_bio_fd_shutdown(fr_bio_t *bio)
Orderly shutdown.
Definition fd.c:96
static int fr_bio_fd_accept_stream(fr_bio_fd_t *my, fr_bio_fd_t const *parent)
Accept a stream socket and initialize its flags.
Definition fd.c:1583
static int fr_bio_fd_init_file(fr_bio_fd_t *my)
Files are a special case of connected sockets.
Definition fd.c:868
static void fr_bio_fd_el_timeout(UNUSED fr_timer_list_t *tl, UNUSED fr_time_t now, void *uctx)
We have a timeout on the conenction.
Definition fd.c:1321
#define SOCK_CLOEXEC
Definition fd.c:1576
int fr_bio_fd_init_common(fr_bio_fd_t *my)
Definition fd.c:985
static ssize_t fr_bio_fd_recvmsg_dst(fr_bio_fd_t *parent, uint8_t *buffer, int flags, struct sockaddr_storage *from, socklen_t *from_len, fr_ipaddr_t *dst)
Receive a datagram, and find the address which the datagram was sent to.
Definition fd.c:1644
int fr_bio_fd_write_only(fr_bio_t *bio)
Mark up a bio as write-only.
Definition fd.c:1493
static ssize_t fr_bio_fd_read_discard_datagram(fr_bio_t *bio, UNUSED void *packet_ctx, void *buffer, size_t size)
Discard all reads from a UDP socket.
Definition fd.c:1456
static void fr_bio_fd_el_error(UNUSED fr_event_list_t *el, UNUSED int fd, UNUSED int flags, int fd_errno, void *uctx)
FD error when trying to connect, give up on the BIO.
Definition fd.c:1202
#define SOCK_NONBLOCK
Definition fd.c:1572
int fr_bio_fd_close(fr_bio_t *bio)
Close the FD, but leave the bio allocated and alive.
Definition fd.c:1164
static void fr_bio_fd_set_open(fr_bio_fd_t *my)
Definition fd.c:747
static ssize_t fr_bio_fd_read_stream(fr_bio_t *bio, UNUSED void *packet_ctx, void *buffer, size_t size)
Stream read.
Definition fd.c:158
fr_socket_t socket
as connected socket
Definition fd.h:145
bool eof
are we at EOF?
Definition fd.h:154
fr_bio_fd_type_t type
type of the socket
Definition fd.h:147
fr_bio_fd_state_t state
connecting, open, closed, etc.
Definition fd.h:148
int connect_errno
from connect() or other APIs
Definition fd.h:156
fr_ipaddr_t dst_ipaddr
their IP address
Definition fd.h:102
fr_bio_fd_type_t type
accept, connected, unconnected, etc.
Definition fd.h:93
@ FR_BIO_FD_CONNECTED
connected client sockets (UDP or TCP)
Definition fd.h:63
@ FR_BIO_FD_INVALID
not set
Definition fd.h:59
@ FR_BIO_FD_UNCONNECTED
unconnected UDP / datagram only
Definition fd.h:60
@ FR_BIO_FD_LISTEN
call fr_bio_fd_accept() for each new connection
Definition fd.h:64
fr_bio_fd_config_t const * cfg
so we know what was asked, vs what was granted.
Definition fd.h:158
bool read_blocked
did we block on read?
Definition fd.h:152
@ FR_BIO_FD_TRANSPORT_TCP
TCP over IPv4 or IPv6.
Definition fd.h:79
bool server
is this a client or a server?
Definition fd.h:98
uint32_t backlog
for listen()
Definition fd.h:112
uint16_t dst_port
their port
Definition fd.h:105
fr_bio_fd_transport_t transport_type
which transport, as a number instead of a name
Definition fd.h:97
int fr_bio_fd_open(fr_bio_t *bio, fr_bio_fd_config_t const *cfg)
Opens a socket and updates sock->fd.
Definition fd_open.c:1293
@ FR_BIO_FD_STATE_CLOSED
Definition fd.h:53
@ FR_BIO_FD_STATE_CONNECTING
Definition fd.h:55
@ FR_BIO_FD_STATE_OPEN
error states must be before this
Definition fd.h:54
bool reuse_port
whether or not we re-use the same destination port for datagram sockets
Definition fd.h:99
bool backlog_is_set
Whether we were provided with a backlog.
Definition fd.h:135
fr_socket_t socket
socket information, including FD.
Definition fd.h:47
bool async
is it async
Definition fd.h:126
bool write_blocked
did we block on write?
Definition fd.h:153
int flags
O_RDONLY, etc.
Definition fd.h:124
fr_ipaddr_t src_ipaddr
our IP address
Definition fd.h:101
Configuration for sockets.
Definition fd.h:92
Run-time status of the socket.
Definition fd.h:144
Per-packet context.
Definition fd.h:46
static bool fr_bio_fd_errno_retry(fr_bio_fd_t *my, ssize_t *rcode_p, int *tries_p, bool is_write)
Turn a failed read / write into a bio return code.
Definition fd_errno.h:41
#define FD_ENET_SUPPRESS
Definition fd_errno.h:157
int fr_bio_fd_unix_shutdown(fr_bio_t *bio)
Remove the Unix domain socket which this bio created.
Definition fd_open.c:499
void fr_bio_fd_name(fr_bio_fd_t *my)
Set the name of an FD BIO.
Definition fd_open.c:897
socklen_t remote_sockaddr_len
Definition fd_priv.h:46
struct fr_bio_fd_s::@18 connect
size_t offset
where fr_bio_fd_packet_ctx_t is stored
Definition fd_priv.h:63
fr_bio_fd_info_t info
Definition fd_priv.h:43
int max_tries
how many times we retry on EINTR
Definition fd_priv.h:62
uint8_t * first_datagram
The datagram which fr_bio_fd_accept() read to name the peer.
Definition fd_priv.h:58
uint8_t * accept_buffer
A LISTEN datagram bio reads datagrams into this buffer, which is allocated once by fr_bio_fd_init_lis...
Definition fd_priv.h:56
#define fr_bio_fd_packet_ctx(_my, _packet_ctx)
Definition fd_priv.h:80
#define FR_BIO_FD_MAX_DATAGRAM
The largest payload of a UDP datagram.
Definition fd_priv.h:35
size_t first_datagram_len
Length of first_datagram.
Definition fd_priv.h:60
struct sockaddr_storage remote_sockaddr
for connected UDP sockets.
Definition fd_priv.h:45
Our FD bio structure.
Definition fd_priv.h:40
static bool fr_bio_fd_read_retry(fr_bio_fd_t *my, ssize_t *rcode_p, int *tries_p)
Common finalization code for the read functions.
Definition fd_read.h:44
static bool fr_bio_fd_write_retry(fr_bio_fd_t *my, ssize_t *rcode_p, int *tries_p, size_t size)
Common finalization code for the write functions.
Definition fd_write.h:42
talloc_free(hp)
void fr_ipaddr_get_scope_id(fr_ipaddr_t *ipaddr)
Definition inet.c:1529
int fr_ipaddr_from_sockaddr(fr_ipaddr_t *ipaddr, uint16_t *port, struct sockaddr_storage const *sa, socklen_t salen)
Convert sockaddr to our internal ip address representation.
Definition inet.c:1448
int fr_ipaddr_is_inaddr_any(fr_ipaddr_t const *ipaddr)
Determine if an address is the INADDR_ANY address for its address family.
Definition inet.c:62
int fr_ipaddr_to_sockaddr(struct sockaddr_storage *sa, socklen_t *salen, fr_ipaddr_t const *ipaddr, uint16_t port)
Convert our internal ip address representation to a sockaddr.
Definition inet.c:1399
int af
Address family.
Definition inet.h:64
#define AF_FR_FILENAME
Definition inet.h:105
IPv4/6 prefix.
int fr_bio_write_blocked(fr_bio_t *bio)
Internal BIO function to tell all BIOs that it's blocked.
Definition base.c:354
ssize_t fr_bio_shutdown_read(UNUSED fr_bio_t *bio, UNUSED void *packet_ctx, UNUSED void *buffer, UNUSED size_t size)
Definition base.c:74
int fr_bio_destructor(fr_bio_t *bio)
Free this bio.
Definition base.c:35
ssize_t fr_bio_shutdown_write(UNUSED fr_bio_t *bio, UNUSED void *packet_ctx, UNUSED void const *buffer, UNUSED size_t size)
Definition base.c:79
fr_bio_t * fr_bio_eof(fr_bio_t *bio)
Internal BIO function to run EOF callbacks.
Definition base.c:280
int fr_bio_shutdown(fr_bio_t *bio)
Shut down a set of BIOs.
Definition base.c:158
#define fr_time()
Definition event.c:58
int fr_event_fd_delete(fr_event_list_t *el, int fd, fr_event_filter_t filter)
Remove a file descriptor from the event loop.
Definition event.c:1204
Stores all information relating to an event list.
Definition event.c:375
unsigned short uint16_t
long int ssize_t
unsigned char uint8_t
unsigned long int size_t
int fr_nonblock(UNUSED int fd)
Definition misc.c:293
int fr_cloexec(UNUSED int fd)
Definition misc.c:331
ssize_t fr_bio_null_write(UNUSED fr_bio_t *bio, UNUSED void *packet_ctx, UNUSED void const *buffer, UNUSED size_t size)
Always return 0 on write.
Definition null.c:39
ssize_t fr_bio_null_read(UNUSED fr_bio_t *bio, UNUSED void *packet_ctx, UNUSED void *buffer, UNUSED size_t size)
Always return 0 on read.
Definition null.c:31
ssize_t fr_bio_fail_read(UNUSED fr_bio_t *bio, UNUSED void *packet_ctx, UNUSED void *buffer, UNUSED size_t size)
Always return error on read.
Definition null.c:47
ssize_t fr_bio_fail_write(UNUSED fr_bio_t *bio, UNUSED void *packet_ctx, UNUSED void const *buffer, UNUSED size_t size)
Always return an error on write.
Definition null.c:56
#define fr_assert(_expr)
Definition rad_assert.h:37
char const * fr_syserror(int num)
Guaranteed to be thread-safe version of strerror.
Definition syserror.c:243
static fr_time_t fr_time_from_timeval(struct timeval const *when_tv)
Convert a timeval (wallclock time) to a fr_time_t (internal time)
Definition time.h:914
#define fr_time_wrap(_time)
Definition time.h:145
#define fr_time_eq(_a, _b)
Definition time.h:241
static fr_time_t fr_time_from_timespec(struct timespec const *when_ts)
Convert a timespec (wallclock time) to a fr_time_t (internal time)
Definition time.h:896
A time delta, a difference in time measured in nanoseconds.
Definition time.h:80
"server local" time.
Definition time.h:69
An event timer list.
Definition timer.c:49
#define FR_TIMER_DELETE(_ev_p)
Definition timer.h:105
#define fr_timer_in(...)
Definition timer.h:87
static fr_event_list_t * el
static fr_slen_t head
Definition xlat.h:410
static fr_slen_t parent
Definition pair.h:864
int af
AF_INET, AF_INET6, or AF_UNIX.
Definition socket.h:83
int fd
File descriptor if this is a live socket.
Definition socket.h:86
int type
SOCK_STREAM, SOCK_DGRAM, etc.
Definition socket.h:84
#define fr_strerror_printf(_fmt,...)
Log to thread local error buffer.
Definition strerror.h:64
#define fr_strerror_const(_msg)
Definition strerror.h:223
static fr_sbuff_err_t char size_t fr_sbuff_t * in
Definition value.h:1061
static fr_sbuff_err_t char ** out
Definition value.h:1061
static fr_sbuff_err_t char size_t * len
Definition value.h:1061