The FreeRADIUS server  $Id: 15bac2a4c627c01d1aa2047687b3418955ac7f00 $
fd.c
Go to the documentation of this file.
1 /*
2  * This program is 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: fe298d4430a53eb33a97ae310ff7bfb5b9b5891c $
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/null.h>
27 
28 /*
29  * More portability idiocy
30  * Mac OSX Lion doesn't define SOL_IP. But IPPROTO_IP works.
31  */
32 #ifndef SOL_IP
33 # define SOL_IP IPPROTO_IP
34 #endif
35 
36 /*
37  * glibc 2.4 and uClibc 0.9.29 introduce IPV6_RECVPKTINFO etc. and
38  * change IPV6_PKTINFO This is only supported in Linux kernel >=
39  * 2.6.14
40  *
41  * This is only an approximation because the kernel version that libc
42  * was compiled against could be older or newer than the one being
43  * run. But this should not be a problem -- we just keep using the
44  * old kernel interface.
45  */
46 #ifdef __linux__
47 # ifdef IPV6_RECVPKTINFO
48 # include <linux/version.h>
49 # if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,14)
50 # ifdef IPV6_2292PKTINFO
51 # undef IPV6_RECVPKTINFO
52 # undef IPV6_PKTINFO
53 # define IPV6_RECVPKTINFO IPV6_2292PKTINFO
54 # define IPV6_PKTINFO IPV6_2292PKTINFO
55 # endif
56 # endif
57 /* Fall back to the legacy socket option if IPV6_RECVPKTINFO isn't defined */
58 # elif defined(IPV6_2292PKTINFO)
59 # define IPV6_RECVPKTINFO IPV6_2292PKTINFO
60 # endif
61 #else
62 
63 /*
64  * For everything that's not Linux we assume RFC 3542 compliance
65  * - setsockopt() takes IPV6_RECVPKTINFO
66  * - cmsg_type is IPV6_PKTINFO (in sendmsg, recvmsg)
67  *
68  * If we don't have IPV6_RECVPKTINFO defined but do have IPV6_PKTINFO
69  * defined, chances are the API is RFC2292 compliant and we need to use
70  * IPV6_PKTINFO for both.
71  */
72 # if !defined(IPV6_RECVPKTINFO) && defined(IPV6_PKTINFO)
73 # define IPV6_RECVPKTINFO IPV6_PKTINFO
74 
75 /*
76  * Ensure IPV6_RECVPKTINFO is not defined somehow if we have we
77  * don't have IPV6_PKTINFO.
78  */
79 # elif !defined(IPV6_PKTINFO)
80 # undef IPV6_RECVPKTINFO
81 # endif
82 #endif
83 
84 #define ADDR_INIT do { \
85  addr->when = fr_time(); \
86  addr->socket.type = my->info.socket.type; \
87  addr->socket.fd = -1; \
88  addr->socket.inet.ifindex = my->info.socket.inet.ifindex; \
89  } while (0)
90 
91 /*
92  * Close the descriptor and free the bio.
93  */
95 {
96  /*
97  * The upstream bio must have unlinked it from the chain before calling talloc_free() on this
98  * bio.
99  */
100  fr_assert(!fr_bio_prev(&my->bio));
101  fr_assert(!fr_bio_next(&my->bio));
102 
103  if (my->connect.ev) {
104  talloc_const_free(my->connect.ev);
105  my->connect.ev = NULL;
106  }
107 
108  if (my->connect.el) {
109  (void) fr_event_fd_delete(my->connect.el, my->info.socket.fd, FR_EVENT_FILTER_IO);
110  my->connect.el = NULL;
111  }
112 
113  if (my->cb.shutdown) my->cb.shutdown(&my->bio);
114 
115  return fr_bio_fd_close(&my->bio);
116 }
117 
118 static int fr_bio_fd_eof(fr_bio_t *bio)
119 {
120  bio->read = fr_bio_null_read;
121  bio->write = fr_bio_null_write;
122 
123  /*
124  * Nothing more for us to do, tell fr_bio_eof() that it can continue with poking other BIOs.
125  */
126  return 1;
127 }
128 
130 {
131  fr_bio_fd_t *my = talloc_get_type_abort(bio, fr_bio_fd_t);
132 
133  my->info.write_blocked = false;
134  return 1;
135 }
136 
137 /** Stream read.
138  *
139  * Stream sockets return 0 at EOF. However, we want to distinguish that from the case of datagram
140  * sockets, which return 0 when there's no data. So we return 0 to the caller for "no data", but also
141  * call the EOF function to tell all of the related BIOs that we're at EOF.
142  */
143 static ssize_t fr_bio_fd_read_stream(fr_bio_t *bio, UNUSED void *packet_ctx, void *buffer, size_t size)
144 {
145  int tries = 0;
146  ssize_t rcode;
147  fr_bio_fd_t *my = talloc_get_type_abort(bio, fr_bio_fd_t);
148 
149 retry:
150  rcode = read(my->info.socket.fd, buffer, size);
151  if (rcode == 0) {
152  fr_bio_eof(bio);
153  return 0;
154  }
155 
156 #include "fd_read.h"
157 
158  return fr_bio_error(IO);
159 }
160 
161 /** Connected datagram read.
162  *
163  * The difference between this and stream protocols is that for datagrams. a read of zero means "no packets",
164  * where a read of zero on a steam socket means "EOF".
165  *
166  * Connected sockets do _not_ update per-packet contexts.
167  */
168 static ssize_t fr_bio_fd_read_connected_datagram(fr_bio_t *bio, UNUSED void *packet_ctx, void *buffer, size_t size)
169 {
170  int tries = 0;
171  ssize_t rcode;
172  fr_bio_fd_t *my = talloc_get_type_abort(bio, fr_bio_fd_t);
173 
174 retry:
175  rcode = read(my->info.socket.fd, buffer, size);
176  if (rcode == 0) return rcode;
177 
178 #include "fd_read.h"
179 
180  return fr_bio_error(IO);
181 }
182 
183 /** Read from a UDP socket where we know our IP
184  */
185 static ssize_t fr_bio_fd_recvfrom(fr_bio_t *bio, void *packet_ctx, void *buffer, size_t size)
186 {
187  int tries = 0;
188  ssize_t rcode;
189  fr_bio_fd_t *my = talloc_get_type_abort(bio, fr_bio_fd_t);
190  socklen_t salen;
191  struct sockaddr_storage sockaddr;
192 
193 retry:
194  salen = sizeof(sockaddr);
195 
196  rcode = recvfrom(my->info.socket.fd, buffer, size, 0, (struct sockaddr *) &sockaddr, &salen);
197  if (rcode > 0) {
198  fr_bio_fd_packet_ctx_t *addr = fr_bio_fd_packet_ctx(my, packet_ctx);
199 
200  ADDR_INIT;
201 
202  addr->socket.inet.dst_ipaddr = my->info.socket.inet.src_ipaddr;
203  addr->socket.inet.dst_port = my->info.socket.inet.src_port;
204 
205  (void) fr_ipaddr_from_sockaddr(&addr->socket.inet.src_ipaddr, &addr->socket.inet.src_port,
206  &sockaddr, salen);
207  }
208 
209  if (rcode == 0) return rcode;
210 
211 #include "fd_read.h"
212 
213  return fr_bio_error(IO);
214 }
215 
216 /** Write to fd.
217  *
218  * This function is used for connected sockets, where we ignore the packet_ctx.
219  */
220 static ssize_t fr_bio_fd_write(fr_bio_t *bio, UNUSED void *packet_ctx, const void *buffer, size_t size)
221 {
222  int tries = 0;
223  ssize_t rcode;
224  fr_bio_fd_t *my = talloc_get_type_abort(bio, fr_bio_fd_t);
225 
226  /*
227  * FD bios do nothing on flush.
228  */
229  if (!buffer) return 0;
230 
231 retry:
232  /*
233  * We could call send() instead of write()! Posix says:
234  *
235  * "A write was attempted on a socket that is shut down for writing, or is no longer
236  * connected. In the latter case, if the socket is of type SOCK_STREAM, a SIGPIPE signal shall
237  * also be sent to the thread."
238  *
239  * We can override this behavior by calling send(), and passing the special flag which says
240  * "don't do that!". The system call will then return EPIPE, which indicates that the socket is
241  * no longer usable.
242  *
243  * However, we also set the SO_NOSIGPIPE socket option, which means that we can just call write()
244  * here.
245  */
246  rcode = write(my->info.socket.fd, buffer, size);
247 
248 #include "fd_write.h"
249 
250  return fr_bio_error(IO);
251 }
252 
253 /** Write to a UDP socket where we know our IP
254  *
255  */
256 static ssize_t fr_bio_fd_sendto(fr_bio_t *bio, void *packet_ctx, const void *buffer, size_t size)
257 {
258  int tries = 0;
259  ssize_t rcode;
260  fr_bio_fd_t *my = talloc_get_type_abort(bio, fr_bio_fd_t);
261  fr_bio_fd_packet_ctx_t *addr = fr_bio_fd_packet_ctx(my, packet_ctx);
262  socklen_t salen;
263  struct sockaddr_storage sockaddr;
264 
265  /*
266  * FD bios do nothing on flush.
267  */
268  if (!buffer) return 0;
269 
270  // get destination IP
271  (void) fr_ipaddr_to_sockaddr(&sockaddr, &salen, &addr->socket.inet.dst_ipaddr, addr->socket.inet.dst_port);
272 
273 retry:
274  rcode = sendto(my->info.socket.fd, buffer, size, 0, (struct sockaddr *) &sockaddr, salen);
275 
276 #include "fd_write.h"
277 
278  return fr_bio_error(IO);
279 }
280 
281 
282 #if defined(IP_PKTINFO) || defined(IP_RECVDSTADDR) || defined(IPV6_PKTINFO)
283 static ssize_t fd_fd_recvfromto_common(fr_bio_fd_t *my, void *packet_ctx, void *buffer, size_t size)
284 {
285  int tries = 0;
286  ssize_t rcode;
287  struct sockaddr_storage from;
288  fr_bio_fd_packet_ctx_t *addr = fr_bio_fd_packet_ctx(my, packet_ctx);
289 
290 #ifdef STATIC_ANALYZER
291  from.ss_family = AF_UNSPEC;
292 #endif
293 
294  memset(&my->cbuf, 0, sizeof(my->cbuf));
295  memset(&my->msgh, 0, sizeof(struct msghdr));
296 
297  my->iov = (struct iovec) {
298  .iov_base = buffer,
299  .iov_len = size,
300  };
301 
302  my->msgh = (struct msghdr) {
303  .msg_control = my->cbuf,
304  .msg_controllen = sizeof(my->cbuf),
305  .msg_name = &from,
306  .msg_namelen = sizeof(from),
307  .msg_iov = &my->iov,
308  .msg_iovlen = 1,
309  .msg_flags = 0,
310  };
311 
312 retry:
313  rcode = recvmsg(my->info.socket.fd, &my->msgh, 0);
314  if (rcode > 0) {
315  ADDR_INIT;
316 
317  (void) fr_ipaddr_from_sockaddr(&addr->socket.inet.src_ipaddr, &addr->socket.inet.src_port,
318  &from, my->msgh.msg_namelen);
319  }
320 
321  if (rcode == 0) return rcode;
322 
323 #include "fd_read.h"
324 
325  return fr_bio_error(IO);
326 }
327 #endif
328 
329 #if defined(IP_PKTINFO) || defined(IP_RECVDSTADDR)
330 
331 /** Read from a UDP socket where we can change our IP, IPv4 version.
332  */
333 static ssize_t fr_bio_fd_recvfromto4(fr_bio_t *bio, void *packet_ctx, void *buffer, size_t size)
334 {
335  ssize_t rcode;
336  struct cmsghdr *cmsg;
337  fr_time_t when = fr_time_wrap(0);
338  fr_bio_fd_t *my = talloc_get_type_abort(bio, fr_bio_fd_t);
339  fr_bio_fd_packet_ctx_t *addr = fr_bio_fd_packet_ctx(my, packet_ctx);
340 
341  rcode = fd_fd_recvfromto_common(my, packet_ctx, buffer, size);
342  if (rcode <= 0) return rcode;
343 
344 DIAG_OFF(sign-compare)
345  /* Process auxiliary received data in msgh */
346  for (cmsg = CMSG_FIRSTHDR(&my->msgh);
347  cmsg != NULL;
348  cmsg = CMSG_NXTHDR(&my->msgh, cmsg)) {
349 DIAG_ON(sign-compare)
350 
351 #ifdef IP_PKTINFO
352  if ((cmsg->cmsg_level == SOL_IP) &&
353  (cmsg->cmsg_type == IP_PKTINFO)) {
354  struct in_pktinfo *i = (struct in_pktinfo *) CMSG_DATA(cmsg);
355  struct sockaddr_in to;
356 
357  to.sin_addr = i->ipi_addr;
358 
359  (void) fr_ipaddr_from_sockaddr(&addr->socket.inet.dst_ipaddr, &addr->socket.inet.dst_port,
360  (struct sockaddr_storage *) &to, sizeof(struct sockaddr_in));
361  addr->socket.inet.ifindex = i->ipi_ifindex;
362  break;
363  }
364 #endif
365 
366 #ifdef IP_RECVDSTADDR
367  if ((cmsg->cmsg_level == IPPROTO_IP) &&
368  (cmsg->cmsg_type == IP_RECVDSTADDR)) {
369  struct in_addr *i = (struct in_addr *) CMSG_DATA(cmsg);
370  struct sockaddr_in to;
371 
372  to.sin_addr = *i;
373  (void) fr_ipaddr_from_sockaddr(&addr->socket.inet.dst_ipaddr, &addr->socket.inet.dst_port,
374  (struct sockaddr_storage *) &to, sizeof(struct sockaddr_in));
375  break;
376  }
377 #endif
378 
379 #ifdef SO_TIMESTAMPNS
380  if ((cmsg->cmsg_level == SOL_IP) && (cmsg->cmsg_type == SO_TIMESTAMPNS)) {
381  when = fr_time_from_timespec((struct timespec *)CMSG_DATA(cmsg));
382  }
383 
384 #elif defined(SO_TIMESTAMP)
385  if ((cmsg->cmsg_level == SOL_IP) && (cmsg->cmsg_type == SO_TIMESTAMP)) {
386  when = fr_time_from_timeval((struct timeval *)CMSG_DATA(cmsg));
387  }
388 #endif
389  }
390 
391  if fr_time_eq(when, fr_time_wrap(0)) when = fr_time();
392 
393  addr->when = when;
394 
395  return rcode;
396 }
397 
398 /** Send to UDP socket where we can change our IP, IPv4 version.
399  */
400 static ssize_t fr_bio_fd_sendfromto4(fr_bio_t *bio, void *packet_ctx, const void *buffer, size_t size)
401 {
402  int tries = 0;
403  ssize_t rcode;
404  struct cmsghdr *cmsg;
405  struct sockaddr_storage to;
406  socklen_t to_len;
407  fr_bio_fd_t *my = talloc_get_type_abort(bio, fr_bio_fd_t);
408  fr_bio_fd_packet_ctx_t *addr = fr_bio_fd_packet_ctx(my, packet_ctx);
409 
410  memset(&my->cbuf, 0, sizeof(my->cbuf));
411  memset(&my->msgh, 0, sizeof(struct msghdr));
412 
413  (void) fr_ipaddr_to_sockaddr(&to, &to_len, &addr->socket.inet.dst_ipaddr, addr->socket.inet.dst_port);
414 
415  my->iov = (struct iovec) {
416  .iov_base = UNCONST(void *, buffer),
417  .iov_len = size,
418  };
419 
420  my->msgh = (struct msghdr) {
421  .msg_control = my->cbuf,
422  // controllen is set below
423  .msg_name = &to,
424  .msg_namelen = to_len,
425  .msg_iov = &my->iov,
426  .msg_iovlen = 1,
427  .msg_flags = 0,
428  };
429 
430  cmsg = CMSG_FIRSTHDR(&my->msgh);
431 
432  {
433 #ifdef IP_PKTINFO
434  struct in_pktinfo *pkt;
435 
436  my->msgh.msg_controllen = CMSG_SPACE(sizeof(*pkt));
437 
438  cmsg->cmsg_level = SOL_IP;
439  cmsg->cmsg_type = IP_PKTINFO;
440  cmsg->cmsg_len = CMSG_LEN(sizeof(*pkt));
441 
442  pkt = (struct in_pktinfo *) CMSG_DATA(cmsg);
443  memset(pkt, 0, sizeof(*pkt));
444  pkt->ipi_spec_dst = addr->socket.inet.src_ipaddr.addr.v4;
445  pkt->ipi_ifindex = addr->socket.inet.ifindex;
446 
447 #elif defined(IP_SENDSRCADDR)
448  struct in_addr *in;
449 
450  my->msgh.msg_controllen = CMSG_SPACE(sizeof(*in));
451 
452  cmsg->cmsg_level = IPPROTO_IP;
453  cmsg->cmsg_type = IP_SENDSRCADDR;
454  cmsg->cmsg_len = CMSG_LEN(sizeof(*in));
455 
456  in = (struct in_addr *) CMSG_DATA(cmsg);
457  *in = addr->socket.inet.src_ipaddr.addr.v4;
458 #endif
459  }
460 
461 retry:
462  rcode = sendmsg(my->info.socket.fd, &my->msgh, 0);
463 
464 #include "fd_write.h"
465 
466  return fr_bio_error(IO);
467 }
468 
469 static inline int fr_bio_fd_udpfromto_init4(int fd)
470 {
471  int proto = 0, flag = 0, opt = 1;
472 
473 #ifdef HAVE_IP_PKTINFO
474  /*
475  * Linux
476  */
477  proto = SOL_IP;
478  flag = IP_PKTINFO;
479 
480 #elif defined(IP_RECVDSTADDR)
481  /*
482  * Set the IP_RECVDSTADDR option (BSD). Note:
483  * IP_RECVDSTADDR == IP_SENDSRCADDR
484  */
485  proto = IPPROTO_IP;
486  flag = IP_RECVDSTADDR;
487 #endif
488 
489  return setsockopt(fd, proto, flag, &opt, sizeof(opt));
490 }
491 #endif
492 
493 #if defined(IPV6_PKTINFO)
494 /** Read from a UDP socket where we can change our IP, IPv4 version.
495  */
496 static ssize_t fr_bio_fd_recvfromto6(fr_bio_t *bio, void *packet_ctx, void *buffer, size_t size)
497 {
498  ssize_t rcode;
499  struct cmsghdr *cmsg;
500  fr_time_t when = fr_time_wrap(0);
501  fr_bio_fd_t *my = talloc_get_type_abort(bio, fr_bio_fd_t);
502  fr_bio_fd_packet_ctx_t *addr = fr_bio_fd_packet_ctx(my, packet_ctx);
503 
504  rcode = fd_fd_recvfromto_common(my, packet_ctx, buffer, size);
505  if (rcode <= 0) return rcode;
506 
507 DIAG_OFF(sign-compare)
508  /* Process auxiliary received data in msgh */
509  for (cmsg = CMSG_FIRSTHDR(&my->msgh);
510  cmsg != NULL;
511  cmsg = CMSG_NXTHDR(&my->msgh, cmsg)) {
512 DIAG_ON(sign-compare)
513 
514  if ((cmsg->cmsg_level == IPPROTO_IPV6) &&
515  (cmsg->cmsg_type == IPV6_PKTINFO)) {
516  struct in6_pktinfo *i = (struct in6_pktinfo *) CMSG_DATA(cmsg);
517  struct sockaddr_in6 to;
518 
519  to.sin6_addr = i->ipi6_addr;
520 
521  (void) fr_ipaddr_from_sockaddr(&addr->socket.inet.dst_ipaddr, &addr->socket.inet.dst_port,
522  (struct sockaddr_storage *) &to, sizeof(struct sockaddr_in6));
523  addr->socket.inet.ifindex = i->ipi6_ifindex;
524  break;
525  }
526 
527 #ifdef SO_TIMESTAMPNS
528  if ((cmsg->cmsg_level == SOL_IP) && (cmsg->cmsg_type == SO_TIMESTAMPNS)) {
529  when = fr_time_from_timespec((struct timespec *)CMSG_DATA(cmsg));
530  }
531 
532 #elif defined(SO_TIMESTAMP)
533  if ((cmsg->cmsg_level == SOL_IP) && (cmsg->cmsg_type == SO_TIMESTAMP)) {
534  when = fr_time_from_timeval((struct timeval *)CMSG_DATA(cmsg));
535  }
536 #endif
537  }
538 
539  if fr_time_eq(when, fr_time_wrap(0)) when = fr_time();
540 
541  addr->when = when;
542 
543  return rcode;
544 }
545 
546 /** Send to UDP socket where we can change our IP, IPv4 version.
547  */
548 static ssize_t fr_bio_fd_sendfromto6(fr_bio_t *bio, void *packet_ctx, const void *buffer, size_t size)
549 {
550  int tries = 0;
551  ssize_t rcode;
552  struct cmsghdr *cmsg;
553  struct sockaddr_storage to;
554  socklen_t to_len;
555  fr_bio_fd_t *my = talloc_get_type_abort(bio, fr_bio_fd_t);
556  fr_bio_fd_packet_ctx_t *addr = fr_bio_fd_packet_ctx(my, packet_ctx);
557 
558  memset(&my->cbuf, 0, sizeof(my->cbuf));
559  memset(&my->msgh, 0, sizeof(struct msghdr));
560 
561  (void) fr_ipaddr_to_sockaddr(&to, &to_len, &addr->socket.inet.dst_ipaddr, addr->socket.inet.dst_port);
562 
563  my->iov = (struct iovec) {
564  .iov_base = UNCONST(void *, buffer),
565  .iov_len = size,
566  };
567 
568  my->msgh = (struct msghdr) {
569  .msg_control = my->cbuf,
570  // controllen is set below
571  .msg_name = &to,
572  .msg_namelen = to_len,
573  .msg_iov = &my->iov,
574  .msg_iovlen = 1,
575  .msg_flags = 0,
576  };
577 
578  cmsg = CMSG_FIRSTHDR(&my->msgh);
579 
580  {
581  struct in6_pktinfo *pkt;
582 
583  my->msgh.msg_controllen = CMSG_SPACE(sizeof(*pkt));
584 
585  cmsg->cmsg_level = IPPROTO_IPV6;
586  cmsg->cmsg_type = IPV6_PKTINFO;
587  cmsg->cmsg_len = CMSG_LEN(sizeof(*pkt));
588 
589  pkt = (struct in6_pktinfo *) CMSG_DATA(cmsg);
590  memset(pkt, 0, sizeof(*pkt));
591  pkt->ipi6_addr = addr->socket.inet.src_ipaddr.addr.v6;
592  pkt->ipi6_ifindex = addr->socket.inet.ifindex;
593  }
594 
595 retry:
596  rcode = sendmsg(my->info.socket.fd, &my->msgh, 0);
597 
598 #include "fd_write.h"
599 
600  return fr_bio_error(IO);
601 }
602 
603 
604 static inline int fr_bio_fd_udpfromto_init6(int fd)
605 {
606  int opt = 1;
607 
608  return setsockopt(fd, IPPROTO_IPV6, IPV6_RECVPKTINFO, &opt, sizeof(opt));
609 }
610 #endif
611 
612 int fr_filename_to_sockaddr(struct sockaddr_un *sun, socklen_t *sunlen, char const *filename)
613 {
614  size_t len;
615 
616  len = strlen(filename);
617  if (len >= sizeof(sun->sun_path)) {
618  fr_strerror_const("Failed parsing unix domain socket filename: Name is too long");
619  return -1;
620  }
621 
622  sun->sun_family = AF_LOCAL;
623  memcpy(sun->sun_path, filename, len + 1); /* SUN_LEN will do strlen */
624 
625  *sunlen = SUN_LEN(sun);
626 
627  return 0;
628 }
629 
631 {
632  socklen_t salen;
633  struct sockaddr_storage salocal;
634 
635  /*
636  * Already set: do nothing.
637  */
638  if (!fr_ipaddr_is_inaddr_any(&my->info.socket.inet.src_ipaddr)) return 0;
639 
640  /*
641  * FreeBSD jail issues. We bind to 0.0.0.0, but the
642  * kernel instead binds us to a 1.2.3.4. So once the
643  * socket is bound, ask it what it's IP address is.
644  */
645  salen = sizeof(salocal);
646  memset(&salocal, 0, salen);
647  if (getsockname(my->info.socket.fd, (struct sockaddr *) &salocal, &salen) < 0) {
648  fr_strerror_printf("Failed getting socket name: %s", fr_syserror(errno));
649  return -1;
650  }
651 
652  if (fr_ipaddr_from_sockaddr(&my->info.socket.inet.src_ipaddr, &my->info.socket.inet.src_port, &salocal, salen) < 0) return -1;
653 
654  fr_ipaddr_get_scope_id(&my->info.socket.inet.src_ipaddr);
655  my->info.socket.inet.ifindex = my->info.socket.inet.src_ipaddr.scope_id;
656 
657  return 0;
658 }
659 
661 {
662  my->info.state = FR_BIO_FD_STATE_OPEN;
663  my->info.eof = false;
664  my->info.read_blocked = false;
665  my->info.write_blocked = false;
666 
667  /*
668  * Tell the caller that the socket is ready for application data.
669  */
670  if (my->cb.connected) my->cb.connected(&my->bio);
671 }
672 
673 
674 /** Try to connect().
675  *
676  * If connect is blocking, we either succeed or error immediately. Otherwise, the caller has to select the
677  * socket for writeability, and then call fr_bio_fd_connect() as soon as the socket is writeable.
678  */
680 {
681  int tries = 0;
682  int rcode;
683  socklen_t salen;
684  struct sockaddr_storage sockaddr;
685 
686  if (my->info.socket.af != AF_LOCAL) {
687  rcode = fr_ipaddr_to_sockaddr(&sockaddr, &salen, &my->info.socket.inet.dst_ipaddr, my->info.socket.inet.dst_port);
688  } else {
689  rcode = fr_filename_to_sockaddr((struct sockaddr_un *) &sockaddr, &salen, my->info.socket.unix.path);
690  }
691 
692  if (rcode < 0) {
693  fr_bio_shutdown(&my->bio);
694  return fr_bio_error(GENERIC);
695  }
696 
697  my->info.state = FR_BIO_FD_STATE_CONNECTING;
698 
699 retry:
700  if (connect(my->info.socket.fd, (struct sockaddr *) &sockaddr, salen) == 0) {
702 
703  /*
704  * The source IP may have changed, so get the new one.
705  */
706  if (fr_bio_fd_socket_name(my) < 0) goto fail;
707 
708  if (fr_bio_fd_init_common(my) < 0) goto fail;
709 
710  return 0;
711  }
712 
713  switch (errno) {
714  case EINTR:
715  tries++;
716  if (tries <= my->max_tries) goto retry;
717  FALL_THROUGH;
718 
719  /*
720  * This shouldn't happen, but we'll allow it
721  */
722  case EALREADY:
723  FALL_THROUGH;
724 
725  /*
726  * Once the socket is writable, it will be active, or in an error state. The caller has
727  * to call fr_bio_fd_connect() before calling write()
728  */
729  case EINPROGRESS:
730  if (!my->info.write_blocked) {
731  my->info.write_blocked = true;
732 
733  rcode = fr_bio_write_blocked((fr_bio_t *) my);
734  if (rcode < 0) return rcode;
735  }
736 
737  return fr_bio_error(IO_WOULD_BLOCK);
738 
739  default:
740  break;
741  }
742 
743 fail:
744  fr_bio_shutdown(&my->bio);
745  return fr_bio_error(IO);
746 }
747 
748 
749 /** Files are a special case of connected sockets.
750  *
751  */
753 {
755 
756  /*
757  * Other flags may be O_CREAT, etc.
758  */
759  switch (my->info.cfg->flags & (O_RDONLY | O_WRONLY | O_RDWR)) {
760  case O_RDONLY:
761  my->bio.read = fr_bio_fd_read_stream;
762  my->bio.write = fr_bio_fail_write;
763  break;
764 
765  case O_WRONLY:
766  my->bio.read = fr_bio_fail_read;
767  my->bio.write = fr_bio_fd_write;
768  break;
769 
770  case O_RDWR:
771  my->bio.read = fr_bio_fd_read_stream;
772  my->bio.write = fr_bio_fd_write;
773  break;
774 
775  default:
776  fr_strerror_const("Invalid flag for opening file");
777  return -1;
778  }
779 
780  return 0;
781 }
782 
784 {
785  int rcode;
786 
787  if (my->info.socket.af == AF_FILE_BIO) return fr_bio_fd_init_file(my);
788 
789  /*
790  * The source IP can be unspecified. It will get updated after we call connect().
791  */
792 
793  /*
794  * All connected sockets must have a destination IP.
795  */
796  if (fr_ipaddr_is_inaddr_any(&my->info.socket.inet.dst_ipaddr)) {
797  fr_strerror_const("Destination IP address cannot be wildcard");
798  return -1;
799  }
800 
801  /*
802  * Don't do any reads until we're connected.
803  */
804  my->bio.read = fr_bio_null_read;
805  my->bio.write = fr_bio_null_write;
806 
807  my->info.eof = false;
808 
809  my->info.read_blocked = false;
810  my->info.write_blocked = false;
811 
812 #ifdef SO_NOSIGPIPE
813  /*
814  * Although the server ignore SIGPIPE, some operating systems like BSD and OSX ignore the
815  * ignoring.
816  *
817  * Fortunately, those operating systems usually support SO_NOSIGPIPE. We set that to prevent
818  * them raising the signal in the first place.
819  */
820  {
821  int on = 1;
822 
823  setsockopt(my->info.socket.fd, SOL_SOCKET, SO_NOSIGPIPE, &on, sizeof(on));
824  }
825 #endif
826 
827  /*
828  * Don't call connect() if the socket is synchronous, it will block.
829  */
830  if (!my->info.cfg->async) return 0;
831 
832  rcode = fr_bio_fd_try_connect(my);
833  if (rcode == 0) return 0;
834 
835  if (rcode != fr_bio_error(IO_WOULD_BLOCK)) return rcode;
836 
837  /*
838  * The socket is blocked, and should be selected for writing.
839  */
840  fr_assert(my->info.write_blocked);
841  fr_assert(my->info.state == FR_BIO_FD_STATE_CONNECTING);
842 
843  return 0;
844 }
845 
847 {
848  if (my->info.socket.type == SOCK_STREAM) { //!< stream socket
849  my->bio.read = fr_bio_fd_read_stream;
850  my->bio.write = fr_bio_fd_write;
851 
852  } else if (my->info.type == FR_BIO_FD_CONNECTED) { //!< connected datagram
854  my->bio.write = fr_bio_fd_write;
855 
856  } else if (!fr_ipaddr_is_inaddr_any(&my->info.socket.inet.src_ipaddr)) { //!< we know our IP address
857  my->bio.read = fr_bio_fd_recvfrom;
858  my->bio.write = fr_bio_fd_sendto;
859 
860 #if defined(IP_PKTINFO) || defined(IP_RECVDSTADDR)
861  } else if (my->info.socket.inet.src_ipaddr.af == AF_INET) { //!< we don't know our IPv4
862  if (fr_bio_fd_udpfromto_init4(my->info.socket.fd) < 0) return -1;
863 
864  my->bio.read = fr_bio_fd_recvfromto4;
865  my->bio.write = fr_bio_fd_sendfromto4;
866 #endif
867 
868 #if defined(IPV6_PKTINFO)
869  } else if (my->info.socket.inet.src_ipaddr.af == AF_INET6) { //!< we don't know our IPv6
870 
871  if (fr_bio_fd_udpfromto_init6(my->info.socket.fd) < 0) return -1;
872 
873  my->bio.read = fr_bio_fd_recvfromto6;
874  my->bio.write = fr_bio_fd_sendfromto6;
875 #endif
876 
877  } else {
878  fr_strerror_const("Failed initializing socket: cannot determine what to do");
879  return -1;
880  }
881 
883 
884  return 0;
885 }
886 
887 /** Return an fd on read()
888  *
889  * With packet_ctx containing information about the socket.
890  */
891 static ssize_t fr_bio_fd_read_accept(fr_bio_t *bio, void *packet_ctx, void *buffer, size_t size)
892 {
893  int fd, tries = 0;
894  fr_bio_fd_t *my = talloc_get_type_abort(bio, fr_bio_fd_t);
895  socklen_t salen;
896  struct sockaddr_storage sockaddr;
897 
898  if (size < sizeof(int)) return fr_bio_error(BUFFER_TOO_SMALL);
899 
900  salen = sizeof(sockaddr);
901 
902 retry:
903 #ifdef __linux__
904  /*
905  * Set these flags immediately on the new socket.
906  */
907  fd = accept4(my->info.socket.fd, (struct sockaddr *) &sockaddr, &salen, SOCK_NONBLOCK | SOCK_CLOEXEC);
908 #else
909  fd = accept(my->info.socket.fd, (struct sockaddr *) &sockaddr, &salen);
910 #endif
911  if (fd >= 0) {
912  fr_bio_fd_packet_ctx_t *addr = fr_bio_fd_packet_ctx(my, packet_ctx);
913 
914  ADDR_INIT;
915 
916  (void) fr_ipaddr_from_sockaddr(&addr->socket.inet.src_ipaddr, &addr->socket.inet.src_port,
917  &sockaddr, salen);
918 
919  addr->socket.inet.dst_ipaddr = my->info.socket.inet.src_ipaddr;
920  addr->socket.inet.dst_port = my->info.socket.inet.src_port;
921  addr->socket.fd = fd; /* might as well! */
922 
923  *(int *) buffer = fd;
924  return sizeof(int);
925  }
926 
927  switch (errno) {
928  case EINTR:
929  /*
930  * Try a few times before giving up.
931  */
932  tries++;
933  if (tries <= my->max_tries) goto retry;
934  return 0;
935 
936  /*
937  * We can ignore these errors.
938  */
939  case ECONNABORTED:
940 #if defined(EWOULDBLOCK) && (EWOULDBLOCK != EAGAIN)
941  case EWOULDBLOCK:
942 #endif
943  case EAGAIN:
944 #ifdef EPERM
945  case EPERM:
946 #endif
947 #ifdef ETIMEDOUT
948  case ETIMEDOUT:
949 #endif
950  return 0;
951 
952  default:
953  /*
954  * Some other error, it's fatal.
955  */
956  fr_bio_shutdown(&my->bio);
957  break;
958  }
959 
960  return fr_bio_error(IO);
961 }
962 
963 
965 {
966  my->bio.read = fr_bio_fd_read_accept;
967  my->bio.write = fr_bio_null_write;
968 
969  if (listen(my->info.socket.fd, 8) < 0) {
970  fr_strerror_printf("Failed opening setting FD_CLOEXE: %s", fr_syserror(errno));
971  return -1;
972  }
973 
975 
976  return 0;
977 }
978 
979 /** Allocate a FD bio
980  *
981  * The caller is responsible for tracking the FD, and all associated management of it. The bio API is
982  * intended to be simple, and does not provide wrapper functions for various ioctls. The caller should
983  * instead do that work.
984  *
985  * Once the FD is give to the bio, its lifetime is "owned" by the bio. Calling talloc_free(bio) will close
986  * the FD.
987  *
988  * The caller can still manage the FD for being readable / writeable. However, the caller should not call
989  * this bio directly (unless it is the only one). Instead, the caller should read from / write to the
990  * previous bio which will then eventually call this one.
991  *
992  * Before updating any event handler readable / writeable callbacks, the caller should check
993  * fr_bio_fd_at_eof(). If true, then the handlers should not be inserted. The previous bios should still be
994  * called to process any pending data, until they return EOF.
995  *
996  * The main purpose of an FD bio is to wrap the FD in a bio container. That, and handling retries on read /
997  * write, along with returning EOF as an error instead of zero.
998  *
999  * Note that the read / write functions can return partial data. It is the callers responsibility to ensure
1000  * that any writes continue from where they left off (otherwise dat awill be missing). And any partial reads
1001  * should go to a memory bio.
1002  *
1003  * If a read returns EOF, then the FD remains open until talloc_free(bio) or fr_bio_fd_close() is called.
1004  *
1005  * @param ctx the talloc ctx
1006  * @param cfg structure holding configuration information
1007  * @param offset only for unconnected datagram sockets, where #fr_bio_fd_packet_ctx_t is stored
1008  * @return
1009  * - NULL on error, memory allocation failed
1010  * - !NULL the bio
1011  */
1012 fr_bio_t *fr_bio_fd_alloc(TALLOC_CTX *ctx, fr_bio_fd_config_t const *cfg, size_t offset)
1013 {
1014  fr_bio_fd_t *my;
1015 
1016  my = talloc_zero(ctx, fr_bio_fd_t);
1017  if (!my) return NULL;
1018 
1019  my->max_tries = 4;
1020  my->offset = offset;
1021 
1022  if (!cfg) {
1023  /*
1024  * Add place-holder information.
1025  */
1026  my->info = (fr_bio_fd_info_t) {
1027  .socket = {
1028  .af = AF_UNSPEC,
1029  },
1030  .type = FR_BIO_FD_UNCONNECTED,
1031  .read_blocked = false,
1032  .write_blocked = false,
1033  .eof = false,
1034  .state = FR_BIO_FD_STATE_CLOSED,
1035  };
1036 
1037  my->bio.read = fr_bio_null_read;
1038  my->bio.write = fr_bio_null_write;
1039  } else {
1040  my->info.state = FR_BIO_FD_STATE_CLOSED;
1041 
1042  if (fr_bio_fd_open(&my->bio, cfg) < 0) {
1043  talloc_free(my);
1044  return NULL;
1045  }
1046  }
1047 
1048  my->priv_cb.eof = fr_bio_fd_eof;
1049  my->priv_cb.write_resume = fr_bio_fd_write_resume;
1050 
1051  talloc_set_destructor(my, fr_bio_fd_destructor);
1052  return (fr_bio_t *) my;
1053 }
1054 
1055 /** Close the FD, but leave the bio allocated and alive.
1056  *
1057  */
1059 {
1060  int rcode;
1061  int tries = 0;
1062  fr_bio_fd_t *my = talloc_get_type_abort(bio, fr_bio_fd_t);
1063 
1064  if (my->info.state == FR_BIO_FD_STATE_CLOSED) return 0;
1065 
1066  /*
1067  * Shut the bio down cleanly.
1068  */
1069  rcode = fr_bio_shutdown(bio);
1070  if (rcode < 0) return rcode;
1071 
1072  my->bio.read = fr_bio_fail_read;
1073  my->bio.write = fr_bio_fail_write;
1074 
1075  /*
1076  * Shut down the connected socket. The only errors possible here are things we can't do anything
1077  * about.
1078  *
1079  * shutdown() will close ALL versions of this file descriptor, even if it's (somehow) used in
1080  * another process. shutdown() will also tell the kernel to gracefully close the connected
1081  * socket, so that it can signal the other end, instead of having the connection disappear.
1082  *
1083  * This shouldn't strictly be necessary, as no other processes should be sharing this file
1084  * descriptor. But it's the safe (and polite) thing to do.
1085  */
1086  if (my->info.type == FR_BIO_FD_CONNECTED) {
1087  (void) shutdown(my->info.socket.fd, SHUT_RDWR);
1088  }
1089 
1090 retry:
1091  rcode = close(my->info.socket.fd);
1092  if (rcode < 0) {
1093  switch (errno) {
1094  case EINTR:
1095  case EIO:
1096  tries++;
1097  if (tries < my->max_tries) goto retry;
1098  return -1;
1099 
1100  default:
1101  /*
1102  * EBADF, or other unrecoverable error. We just call it closed, and continue.
1103  */
1104  break;
1105  }
1106  }
1107 
1108  my->info.state = FR_BIO_FD_STATE_CLOSED;
1109  my->info.read_blocked = true;
1110  my->info.write_blocked = true;
1111  my->info.eof = true;
1112 
1113  return 0;
1114 }
1115 
1116 /** FD error when trying to connect, give up on the BIO.
1117  *
1118  */
1119 static void fr_bio_fd_el_error(UNUSED fr_event_list_t *el, UNUSED int fd, UNUSED int flags, int fd_errno, void *uctx)
1120 {
1121  fr_bio_fd_t *my = talloc_get_type_abort(uctx, fr_bio_fd_t);
1122 
1123  my->info.connect_errno = fd_errno;
1124 
1125  if (my->connect.error) {
1126  my->connect.error(&my->bio);
1127  }
1128 
1129  fr_bio_shutdown(&my->bio);
1130 }
1131 
1132 /** Connect callback for when the socket is writable.
1133  *
1134  * We try to connect the socket, and if so, call the application which should update the BIO status.
1135  */
1137 {
1138  fr_bio_fd_t *my = talloc_get_type_abort(uctx, fr_bio_fd_t);
1139 
1140  fr_assert(my->info.type == FR_BIO_FD_CONNECTED);
1141  fr_assert(my->info.state == FR_BIO_FD_STATE_CONNECTING);
1142  fr_assert(my->connect.el == el); /* and not NULL */
1143  fr_assert(my->connect.success != NULL);
1144  fr_assert(my->info.socket.fd == fd);
1145 
1146 #ifndef NDEBUG
1147  /*
1148  * This check shouldn't be necessary, as we have a kqeueue error callback. That should be called
1149  * when there's a connect error.
1150  */
1151  {
1152  int error;
1153  socklen_t socklen = sizeof(error);
1154 
1155  /*
1156  * The socket is writeable. Let's see if there's an error.
1157  *
1158  * Unix Network Programming says:
1159  *
1160  * ""If so_error is nonzero when the process calls write, -1 is returned with errno set to the
1161  * value of SO_ERROR (p. 495 of TCPv2) and SO_ERROR is reset to 0. We have to check for the
1162  * error, and if there's no error, set the state to "open". ""
1163  *
1164  * The same applies to connect(). If a non-blocking connect returns INPROGRESS, it may later
1165  * become writable. It will be writable even if the connection fails. Rather than writing some
1166  * random application data, we call SO_ERROR, and get the underlying error.
1167  */
1168  if (getsockopt(my->info.socket.fd, SOL_SOCKET, SO_ERROR, (void *)&error, &socklen) < 0) {
1169  fr_bio_fd_el_error(el, fd, flags, errno, uctx);
1170  return;
1171  }
1172 
1173  fr_assert(error == 0);
1174 
1175  /*
1176  * There was an error, we call the error handler.
1177  */
1178  if (error) {
1179  fr_bio_fd_el_error(el, fd, flags, error, uctx);
1180  return;
1181  }
1182  }
1183 #endif
1184 
1185  /*
1186  * Try to connect it. Any magic handling is done in the callbacks.
1187  */
1188  if (fr_bio_fd_try_connect(my) < 0) return;
1189 
1190  fr_assert(my->connect.success);
1191 
1192  if (my->connect.ev) {
1193  talloc_const_free(my->connect.ev);
1194  my->connect.ev = NULL;
1195  }
1196  my->connect.el = NULL;
1197 
1198  /*
1199  * This function MUST change the read/write/error callbacks for the FD.
1200  */
1201  my->connect.success(&my->bio);
1202 }
1203 
1204 /** We have a timeout on the conenction
1205  *
1206  */
1208 {
1209  fr_bio_fd_t *my = talloc_get_type_abort(uctx, fr_bio_fd_t);
1210 
1211  fr_assert(my->connect.timeout);
1212 
1213  my->connect.timeout(&my->bio);
1214 
1215  fr_bio_shutdown(&my->bio);
1216 }
1217 
1218 
1219 /** Finalize a connect()
1220  *
1221  * connect() said "come back when the socket is writeable". It's now writeable, so we check if there was a
1222  * connection error.
1223  *
1224  * @param bio the binary IO handler
1225  * @param el the event list
1226  * @param connected_cb callback to run when the BIO is connected
1227  * @param error_cb callback to run when the FD has an error
1228  * @param timeout when to time out the connect() attempt
1229  * @param timeout_cb to call when the timeout runs.
1230  * @return
1231  * - <0 on error
1232  * - 0 for "try again later". If callbacks are set, the callbacks will try again. Otherwise the application has to try again.
1233  * - 1 for "we are now connected".
1234  */
1236  fr_bio_callback_t error_cb,
1238 {
1239  fr_bio_fd_t *my = talloc_get_type_abort(bio, fr_bio_fd_t);
1240 
1241  /*
1242  * We shouldn't be connected an unconnected socket.
1243  */
1244  if (my->info.type == FR_BIO_FD_UNCONNECTED) {
1245  error:
1246  fr_bio_shutdown(&my->bio);
1247  return fr_bio_error(GENERIC);
1248  }
1249 
1250  /*
1251  * The initial open may have succeeded in connecting the socket. In which case we just run the
1252  * callbacks and return.
1253  */
1254  if (my->info.state == FR_BIO_FD_STATE_OPEN) {
1255  connected:
1256  if (connected_cb) connected_cb(bio);
1257 
1258  return 1;
1259  }
1260 
1261  /*
1262  * The caller may just call us without caring about what the underlying BIO is. In which case we
1263  * need to be safe.
1264  */
1265  if ((my->info.socket.af == AF_FILE_BIO) || (my->info.type == FR_BIO_FD_LISTEN)) {
1267  goto connected;
1268  }
1269 
1270  /*
1271  * It must be in the connecting state, i.e. not INVALID or CLOSED.
1272  */
1273  if (my->info.state != FR_BIO_FD_STATE_CONNECTING) goto error;
1274 
1275  /*
1276  * No callback
1277  */
1278  if (!connected_cb) {
1279  ssize_t rcode;
1280 
1281  rcode = fr_bio_fd_try_connect(my);
1282  if (rcode < 0) return rcode; /* it already called shutdown */
1283 
1284  return 1;
1285  }
1286 
1287  /*
1288  * It's not connected, the caller has to try again.
1289  */
1290  if (!el) return 0;
1291 
1292  /*
1293  * Set the callbacks to run when something happens.
1294  */
1295  my->connect.success = connected_cb;
1296  my->connect.error = error_cb;
1297  my->connect.timeout = timeout_cb;
1298 
1299  /*
1300  * Set the timeout callback if asked.
1301  */
1302  if (timeout_cb) {
1303  if (fr_event_timer_in(my, el, &my->connect.ev, *timeout, fr_bio_fd_el_timeout, my) < 0) {
1304  goto error;
1305  }
1306  }
1307 
1308  /*
1309  * Set the FD callbacks, and tell the caller that we're not connected.
1310  */
1311  if (fr_event_fd_insert(my, NULL, el, my->info.socket.fd, NULL,
1313  goto error;
1314  }
1315  my->connect.el = el;
1316 
1317  return 0;
1318 }
1319 
1320 /** Returns a pointer to the bio-specific information.
1321  *
1322  */
1324 {
1325  fr_bio_fd_t *my = talloc_get_type_abort(bio, fr_bio_fd_t);
1326 
1327  return &my->info;
1328 }
1329 
1330 
1331 /** Discard all reads from a UDP socket.
1332  */
1333 static ssize_t fr_bio_fd_read_discard(fr_bio_t *bio, UNUSED void *packet_ctx, void *buffer, size_t size)
1334 {
1335  int tries = 0;
1336  ssize_t rcode;
1337  fr_bio_fd_t *my = talloc_get_type_abort(bio, fr_bio_fd_t);
1338 
1339 retry:
1340  rcode = read(my->info.socket.fd, buffer, size);
1341  if (rcode >= 0) return 0; /* always return that we read no data */
1342 
1343 #undef flag_blocked
1344 #define flag_blocked read_blocked
1345 #include "fd_errno.h"
1346 
1347  return fr_bio_error(IO);
1348 }
1349 
1350 /** Mark up a bio as write-only
1351  *
1352  */
1354 {
1355  fr_bio_fd_t *my = talloc_get_type_abort(bio, fr_bio_fd_t);
1356 
1357  switch (my->info.type) {
1358  case FR_BIO_FD_UNCONNECTED:
1359  if (my->info.socket.type != SOCK_DGRAM) {
1360  fr_strerror_const("Only datagram sockets can be marked 'write-only'");
1361  return -1;
1362  }
1363  break;
1364 
1365  case FR_BIO_FD_CONNECTED:
1366  case FR_BIO_FD_ACCEPTED:
1367  /*
1368  * Further reads are disallowed.
1369  */
1370  if (shutdown(my->info.socket.fd, SHUT_RD) < 0) {
1371  fr_strerror_printf("Failed shutting down connected socket - %s", fr_syserror(errno));
1372  return -1;
1373  }
1374  break;
1375 
1376  case FR_BIO_FD_LISTEN:
1377  fr_strerror_const("Only unconnected sockets can be marked 'write-only'");
1378  return -1;
1379  }
1380 
1381  my->bio.read = fr_bio_fd_read_discard;
1382  return 0;
1383 }
1384 
1385 /** Alternative to calling fr_bio_read() on new socket.
1386  *
1387  */
1388 int fr_bio_fd_accept(TALLOC_CTX *ctx, fr_bio_t **out_p, fr_bio_t *bio)
1389 {
1390  int fd, tries = 0;
1391  int rcode;
1392  fr_bio_fd_t *my = talloc_get_type_abort(bio, fr_bio_fd_t);
1393  socklen_t salen;
1394  struct sockaddr_storage sockaddr;
1395  fr_bio_fd_t *out;
1396  fr_bio_fd_config_t *cfg;
1397 
1398  salen = sizeof(sockaddr);
1399  *out_p = NULL;
1400 
1401  fr_assert(my->info.type == FR_BIO_FD_LISTEN);
1402  fr_assert(my->info.socket.type == SOCK_STREAM);
1403 
1404 retry:
1405 #ifdef __linux__
1406  /*
1407  * Set these flags immediately on the new socket.
1408  */
1409  fd = accept4(my->info.socket.fd, (struct sockaddr *) &sockaddr, &salen, SOCK_NONBLOCK | SOCK_CLOEXEC);
1410 #else
1411  fd = accept(my->info.socket.fd, (struct sockaddr *) &sockaddr, &salen);
1412 #endif
1413  if (fd < 0) {
1414  switch (errno) {
1415  case EINTR:
1416  /*
1417  * Try a few times before giving up.
1418  */
1419  tries++;
1420  if (tries <= my->max_tries) goto retry;
1421  return 0;
1422 
1423  /*
1424  * We can ignore these errors.
1425  */
1426  case ECONNABORTED:
1427 #if defined(EWOULDBLOCK) && (EWOULDBLOCK != EAGAIN)
1428  case EWOULDBLOCK:
1429 #endif
1430  case EAGAIN:
1431 #ifdef EPERM
1432  case EPERM:
1433 #endif
1434 #ifdef ETIMEDOUT
1435  case ETIMEDOUT:
1436 #endif
1437  return 0;
1438 
1439  default:
1440  /*
1441  * Some other error, it's fatal.
1442  */
1443  fr_bio_shutdown(&my->bio);
1444  break;
1445  }
1446 
1447  return fr_bio_error(IO);
1448  }
1449 
1450  /*
1451  * Allocate the base BIO and set it up.
1452  */
1453  out = (fr_bio_fd_t *) fr_bio_fd_alloc(ctx, NULL, my->offset);
1454  if (!out) {
1455  close(fd);
1456  return fr_bio_error(GENERIC);
1457  }
1458 
1459  /*
1460  * We have a file descriptor. Initialize the configuration with the new information.
1461  */
1462  cfg = talloc_memdup(out, my->info.cfg, sizeof(*my->info.cfg));
1463  if (!cfg) {
1464  fr_strerror_const("Out of memory");
1465  close(fd);
1466  talloc_free(out);
1467  return fr_bio_error(GENERIC);
1468  }
1469 
1470  /*
1471  * Set the type to ACCEPTED, and set up the rest of the callbacks to match.
1472  */
1473  cfg->type = FR_BIO_FD_ACCEPTED;
1474  out->info.socket.fd = fd;
1475 
1476  rcode = fr_bio_fd_open(bio, cfg);
1477  if (rcode < 0) {
1478  talloc_free(out);
1479  return rcode;
1480  }
1481 
1482  fr_assert(out->info.type == FR_BIO_FD_CONNECTED);
1483 
1484  *out_p = (fr_bio_t *) out;
1485  return 1;
1486 }
static int const char char buffer[256]
Definition: acutest.h:574
fr_bio_write_t _CONST write
write to the underlying bio
Definition: base.h:116
fr_bio_read_t _CONST read
read from the underlying bio
Definition: base.h:115
static fr_bio_t * fr_bio_prev(fr_bio_t *bio)
Definition: base.h:121
static fr_bio_t * fr_bio_next(fr_bio_t *bio)
Definition: base.h:130
void(* fr_bio_callback_t)(fr_bio_t *bio)
Definition: base.h:85
#define fr_bio_error(_x)
Definition: base.h:192
Definition: base.h:112
#define UNCONST(_type, _ptr)
Remove const qualification from a pointer.
Definition: build.h:165
#define NDEBUG_UNUSED
Definition: build.h:324
#define FALL_THROUGH
clang 10 doesn't recognised the FALL-THROUGH comment anymore
Definition: build.h:320
#define DIAG_ON(_x)
Definition: build.h:456
#define UNUSED
Definition: build.h:313
#define DIAG_OFF(_x)
Definition: build.h:455
fr_dcursor_eval_t void const * uctx
Definition: dcursor.h:546
static fr_time_delta_t timeout
Definition: dhcpclient.c:54
static fr_slen_t in
Definition: dict.h:821
#define fr_event_fd_insert(...)
Definition: event.h:232
@ FR_EVENT_FILTER_IO
Combined filter for read/write functions/.
Definition: event.h:62
#define fr_event_timer_in(...)
Definition: event.h:255
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:1235
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:1012
static ssize_t fr_bio_fd_read_discard(fr_bio_t *bio, UNUSED void *packet_ctx, void *buffer, size_t size)
Discard all reads from a UDP socket.
Definition: fd.c:1333
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:1323
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:220
int fr_bio_fd_socket_name(fr_bio_fd_t *my)
Definition: fd.c:630
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:1136
#define ADDR_INIT
Definition: fd.c:84
static int fr_bio_fd_write_resume(fr_bio_t *bio)
Definition: fd.c:129
int fr_bio_fd_init_connected(fr_bio_fd_t *my)
Definition: fd.c:783
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:168
static ssize_t fr_bio_fd_try_connect(fr_bio_fd_t *my)
Try to connect().
Definition: fd.c:679
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:185
#define SOL_IP
Definition: fd.c:33
static int fr_bio_fd_eof(fr_bio_t *bio)
Definition: fd.c:118
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:256
int fr_filename_to_sockaddr(struct sockaddr_un *sun, socklen_t *sunlen, char const *filename)
Definition: fd.c:612
int fr_bio_fd_init_listen(fr_bio_fd_t *my)
Definition: fd.c:964
int fr_bio_fd_accept(TALLOC_CTX *ctx, fr_bio_t **out_p, fr_bio_t *bio)
Alternative to calling fr_bio_read() on new socket.
Definition: fd.c:1388
static void fr_bio_fd_el_timeout(UNUSED fr_event_list_t *el, UNUSED fr_time_t now, void *uctx)
We have a timeout on the conenction.
Definition: fd.c:1207
static ssize_t fr_bio_fd_read_accept(fr_bio_t *bio, void *packet_ctx, void *buffer, size_t size)
Return an fd on read()
Definition: fd.c:891
static int fr_bio_fd_init_file(fr_bio_fd_t *my)
Files are a special case of connected sockets.
Definition: fd.c:752
static int fr_bio_fd_destructor(fr_bio_fd_t *my)
Definition: fd.c:94
int fr_bio_fd_init_common(fr_bio_fd_t *my)
Definition: fd.c:846
int fr_bio_fd_write_only(fr_bio_t *bio)
Mark up a bio as write-only.
Definition: fd.c:1353
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:1119
int fr_bio_fd_close(fr_bio_t *bio)
Close the FD, but leave the bio allocated and alive.
Definition: fd.c:1058
static void fr_bio_fd_set_open(fr_bio_fd_t *my)
Definition: fd.c:660
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:143
@ FR_BIO_FD_ACCEPTED
temporarily until it's connected.
Definition: fd.h:68
@ FR_BIO_FD_CONNECTED
connected client sockets (UDP or TCP)
Definition: fd.h:65
@ FR_BIO_FD_UNCONNECTED
unconnected UDP / datagram only
Definition: fd.h:62
@ FR_BIO_FD_LISTEN
returns new fd in buffer on fr_bio_read() or fr_bio_fd_accept()
Definition: fd.h:66
@ FR_BIO_FD_STATE_CLOSED
Definition: fd.h:56
@ FR_BIO_FD_STATE_CONNECTING
Definition: fd.h:58
@ FR_BIO_FD_STATE_OPEN
error states must be before this
Definition: fd.h:57
fr_bio_fd_type_t type
accept, connected, unconnected, etc.
Definition: fd.h:79
#define AF_FILE_BIO
Definition: fd.h:38
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:715
fr_socket_t socket
socket information, including FD.
Definition: fd.h:50
Configuration for sockets.
Definition: fd.h:78
Run-time status of the socket.
Definition: fd.h:110
Per-packet context.
Definition: fd.h:49
fr_bio_shutdown & my
Definition: fd_errno.h:59
#define fr_bio_fd_packet_ctx(_my, _packet_ctx)
Definition: fd_priv.h:59
Our FD bio structure.
Definition: fd_priv.h:35
void fr_ipaddr_get_scope_id(fr_ipaddr_t *ipaddr)
Definition: inet.c:1486
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:1441
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:1392
int fr_bio_write_blocked(fr_bio_t *bio)
Internal BIO function to tell all BIOs that it's blocked.
Definition: base.c:293
void fr_bio_eof(fr_bio_t *bio)
Internal BIO function to run EOF callbacks.
Definition: base.c:244
int fr_bio_shutdown(fr_bio_t *bio)
Shut down a set of BIOs.
Definition: base.c:141
talloc_free(reap)
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:1260
Stores all information relating to an event list.
Definition: event.c:411
long int ssize_t
Definition: merged_model.c:24
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 0 on write.
Definition: null.c:56
static char const * proto(int id, int porttype)
Definition: radwho.c:85
return
Definition: module.c:174
fr_assert(0)
#define fr_time()
Allow us to arbitrarily manipulate time.
Definition: state_test.c:8
char const * fr_syserror(int num)
Guaranteed to be thread-safe version of strerror.
Definition: syserror.c:243
static int talloc_const_free(void const *ptr)
Free const'd memory.
Definition: talloc.h:224
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:896
#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:878
A time delta, a difference in time measured in nanoseconds.
Definition: time.h:80
"server local" time.
Definition: time.h:69
close(uq->fd)
static fr_event_list_t * el
int fd
File descriptor if this is a live socket.
Definition: socket.h:81
#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 size_t char ** out
Definition: value.h:997