2 * BIRD Internet Routing Daemon -- Unix I/O
4 * (c) 1998--1999 Martin Mares <mj@ucw.cz>
6 * Can be freely distributed and used under the terms of the GNU GPL.
13 #include <sys/types.h>
14 #include <sys/socket.h>
15 #include <sys/fcntl.h>
20 #include "nest/bird.h"
21 #include "lib/lists.h"
22 #include "lib/resource.h"
23 #include "lib/timer.h"
24 #include "lib/socket.h"
25 #include "lib/event.h"
26 #include "lib/string.h"
27 #include "nest/iface.h"
30 #include "lib/sysio.h"
39 long int rand_low
, rand_high
;
43 return (rand_low
& 0xffff) | ((rand_high
& 0xffff) << 16);
58 struct rfile
*a
= (struct rfile
*) r
;
66 struct rfile
*a
= (struct rfile
*) r
;
68 debug("(FILE *%p)\n", a
->f
);
71 static struct resclass rf_class
= {
79 tracked_fopen(pool
*p
, char *name
, char *mode
)
81 FILE *f
= fopen(name
, mode
);
85 struct rfile
*r
= ralloc(p
, &rf_class
);
95 #define NEAR_TIMER_LIMIT 4
97 static list near_timers
, far_timers
;
98 static bird_clock_t first_far_timer
= TIME_INFINITY
;
105 timer
*t
= (timer
*) r
;
113 timer
*t
= (timer
*) r
;
115 debug("(code %p, data %p, ", t
->hook
, t
->data
);
117 debug("rand %d, ", t
->randomize
);
119 debug("recur %d, ", t
->recurrent
);
121 debug("expires in %d sec)\n", t
->expires
- now
);
123 debug("inactive)\n");
126 static struct resclass tm_class
= {
136 timer
*t
= ralloc(p
, &tm_class
);
145 tm_insert_near(timer
*t
)
147 node
*n
= HEAD(near_timers
);
149 while (n
->next
&& (SKIP_BACK(timer
, n
, n
)->expires
< t
->expires
))
151 insert_node(&t
->n
, n
->prev
);
155 tm_start(timer
*t
, unsigned after
)
160 after
+= random() % (t
->randomize
+ 1);
162 if (t
->expires
== when
)
167 if (after
<= NEAR_TIMER_LIMIT
)
171 if (!first_far_timer
|| first_far_timer
> when
)
172 first_far_timer
= when
;
173 add_tail(&far_timers
, &t
->n
);
188 tm_dump_them(char *name
, list
*l
)
193 debug("%s timers:\n", name
);
196 t
= SKIP_BACK(timer
, n
, n
);
206 tm_dump_them("Near", &near_timers
);
207 tm_dump_them("Far", &far_timers
);
213 time_t x
= first_far_timer
;
215 if (!EMPTY_LIST(near_timers
))
217 timer
*t
= SKIP_BACK(timer
, n
, HEAD(near_timers
));
230 if (first_far_timer
<= now
)
232 bird_clock_t limit
= now
+ NEAR_TIMER_LIMIT
;
233 first_far_timer
= TIME_INFINITY
;
234 n
= HEAD(far_timers
);
237 t
= SKIP_BACK(timer
, n
, n
);
238 if (t
->expires
<= limit
)
243 else if (t
->expires
< first_far_timer
)
244 first_far_timer
= t
->expires
;
248 while ((n
= HEAD(near_timers
)) -> next
)
251 t
= SKIP_BACK(timer
, n
, n
);
252 if (t
->expires
> now
)
255 delay
= t
->expires
- now
;
259 int i
= t
->recurrent
- delay
;
269 tm_parse_date(char *x
)
275 if (sscanf(x
, "%d-%d-%d%n", &tm
.tm_mday
, &tm
.tm_mon
, &tm
.tm_year
, &n
) != 3 || x
[n
])
279 tm
.tm_hour
= tm
.tm_min
= tm
.tm_sec
= 0;
281 if (t
== (time_t) -1)
287 tm_format_date(char *x
, bird_clock_t t
)
292 sprintf(x
, "%02d-%02d-%04d", tm
->tm_mday
, tm
->tm_mon
+1, tm
->tm_year
+1900);
296 tm_format_datetime(char *x
, bird_clock_t t
)
301 if (strftime(x
, TM_DATETIME_BUFFER_SIZE
, "%d-%m-%Y %H:%M:%S", tm
) == TM_DATETIME_BUFFER_SIZE
)
302 strcpy(x
, "<too-long>");
306 tm_format_reltime(char *x
, bird_clock_t t
)
309 bird_clock_t delta
= now
- t
;
310 static char *month_names
[12] = { "Jan", "Feb", "Mar", "Apr", "May", "Jun", "Jul", "Aug", "Sep", "Oct", "Nov", "Dec" };
315 else if (delta
< 20*3600)
316 bsprintf(x
, "%02d:%02d", tm
->tm_hour
, tm
->tm_min
);
317 else if (delta
< 360*86400)
318 bsprintf(x
, "%s%02d", month_names
[tm
->tm_mon
], tm
->tm_mday
);
320 bsprintf(x
, "%d", tm
->tm_year
+1900);
328 #define SOL_IP IPPROTO_IP
331 static list sock_list
;
336 sock
*s
= (sock
*) r
;
345 sock
*s
= (sock
*) r
;
346 static char *sk_type_names
[] = { "TCP<", "TCP>", "TCP", "UDP", "UDP/MC", "IP", "IP/MC", "MAGIC", "UNIX<", "UNIX", "DEL!" };
348 debug("(%s, ud=%p, sa=%08x, sp=%d, da=%08x, dp=%d, tos=%d, ttl=%d, if=%s)\n",
349 sk_type_names
[s
->type
],
357 s
->iface
? s
->iface
->name
: "none");
360 static struct resclass sk_class
= {
370 sock
*s
= ralloc(p
, &sk_class
);
373 s
->saddr
= s
->daddr
= IPA_NONE
;
374 s
->sport
= s
->dport
= 0;
375 s
->tos
= s
->ttl
= -1;
388 #define ERR(x) do { err = x; goto bad; } while(0)
389 #define WARN(x) log(L_WARN "sk_setup: %s: %m", x)
394 fill_in_sockaddr(sockaddr
*sa
, ip_addr a
, unsigned port
)
396 sa
->sin6_family
= AF_INET6
;
397 sa
->sin6_port
= htons(port
);
398 sa
->sin6_flowinfo
= 0;
399 set_inaddr(&sa
->sin6_addr
, a
);
403 get_sockaddr(sockaddr
*sa
, ip_addr
*a
, unsigned *port
)
405 if (sa
->sin6_family
!= AF_INET6
)
406 bug("get_sockaddr called for wrong address family");
408 *port
= ntohs(sa
->sin6_port
);
409 memcpy(a
, &sa
->sin6_addr
, sizeof(*a
));
416 fill_in_sockaddr(sockaddr
*sa
, ip_addr a
, unsigned port
)
418 sa
->sin_family
= AF_INET
;
419 sa
->sin_port
= htons(port
);
420 set_inaddr(&sa
->sin_addr
, a
);
424 get_sockaddr(sockaddr
*sa
, ip_addr
*a
, unsigned *port
)
426 if (sa
->sin_family
!= AF_INET
)
427 bug("get_sockaddr called for wrong address family");
429 *port
= ntohs(sa
->sin_port
);
430 memcpy(a
, &sa
->sin_addr
.s_addr
, sizeof(*a
));
443 if (fcntl(fd
, F_SETFL
, O_NONBLOCK
) < 0)
444 ERR("fcntl(O_NONBLOCK)");
445 if (s
->type
== SK_UNIX
)
448 if (s
->ttl
>= 0 && s
->type
!= SK_UDP_MC
&& s
->type
!= SK_IP_MC
&&
449 setsockopt(fd
, SOL_IPV6
, IPV6_UNICAST_HOPS
, &s
->ttl
, sizeof(s
->ttl
)) < 0)
450 ERR("IPV6_UNICAST_HOPS");
452 if ((s
->tos
>= 0) && setsockopt(fd
, SOL_IP
, IP_TOS
, &s
->tos
, sizeof(s
->tos
)) < 0)
456 if (setsockopt(fd
, SOL_IP
, IP_TTL
, &s
->ttl
, sizeof(s
->ttl
)) < 0)
458 if (setsockopt(fd
, SOL_SOCKET
, SO_DONTROUTE
, &one
, sizeof(one
)) < 0)
462 /* FIXME: Set send/receive buffers? */
463 /* FIXME: Set keepalive for TCP connections? */
470 sk_alloc_bufs(sock
*s
)
472 if (!s
->rbuf
&& s
->rbsize
)
473 s
->rbuf
= mb_alloc(s
->pool
, s
->rbsize
);
475 if (!s
->tbuf
&& s
->tbsize
)
476 s
->tbuf
= mb_alloc(s
->pool
, s
->tbsize
);
477 s
->tpos
= s
->ttx
= s
->tbuf
;
481 sk_tcp_connected(sock
*s
)
489 sk_passive_connected(sock
*s
, struct sockaddr
*sa
, int al
, int type
)
491 int fd
= accept(s
->fd
, sa
, &al
);
494 sock
*t
= sk_new(s
->pool
);
498 add_tail(&sock_list
, &t
->n
);
500 if (err
= sk_setup(t
))
502 log(L_ERR
"Incoming connection: %s: %m", err
);
503 s
->err_hook(s
, errno
);
509 else if (errno
!= EINTR
&& errno
!= EAGAIN
)
511 log(L_ERR
"accept: %m");
512 s
->err_hook(s
, errno
);
524 int has_src
= ipa_nonzero(s
->saddr
) || s
->sport
;
531 fd
= socket(BIRD_PF
, SOCK_STREAM
, IPPROTO_TCP
);
535 fd
= socket(BIRD_PF
, SOCK_DGRAM
, IPPROTO_UDP
);
539 fd
= socket(BIRD_PF
, SOCK_RAW
, s
->dport
);
545 bug("sk_open() called for invalid sock type %d", type
);
548 die("sk_open: socket: %m");
551 if (err
= sk_setup(s
))
557 if (s
->iface
) /* It's a broadcast socket */
559 bug("IPv6 has no broadcasts");
561 if (setsockopt(fd
, SOL_SOCKET
, SO_BROADCAST
, &one
, sizeof(one
)) < 0)
569 /* Fortunately, IPv6 socket interface is recent enough and therefore standardized */
570 ASSERT(s
->iface
&& s
->iface
->addr
);
571 if (ipa_nonzero(s
->daddr
))
573 int t
= s
->iface
->index
;
575 if (setsockopt(fd
, SOL_IPV6
, IPV6_MULTICAST_HOPS
, &s
->ttl
, sizeof(s
->ttl
)) < 0)
576 ERR("IPV6_MULTICAST_HOPS");
577 if (setsockopt(fd
, SOL_IPV6
, IPV6_MULTICAST_LOOP
, &zero
, sizeof(zero
)) < 0)
578 ERR("IPV6_MULTICAST_LOOP");
579 if (setsockopt(fd
, SOL_IPV6
, IPV6_MULTICAST_IF
, &t
, sizeof(t
)) < 0)
580 ERR("IPV6_MULTICAST_IF");
584 struct ipv6_mreq mreq
;
585 set_inaddr(&mreq
.ipv6mr_multiaddr
, s
->daddr
);
586 mreq
.ipv6mr_ifindex
= s
->iface
->index
;
587 if (setsockopt(fd
, SOL_IPV6
, IPV6_ADD_MEMBERSHIP
, &mreq
, sizeof(mreq
)) < 0)
588 ERR("IPV6_ADD_MEMBERSHIP");
591 /* With IPv4 there are zillions of different socket interface variants. Ugh. */
592 ASSERT(s
->iface
&& s
->iface
->addr
);
593 if (err
= sysio_mcast_join(s
))
603 if (type
== SK_IP
|| type
== SK_IP_MC
)
608 if (setsockopt(fd
, SOL_SOCKET
, SO_REUSEADDR
, &one
, sizeof(one
)) < 0)
611 fill_in_sockaddr(&sa
, s
->saddr
, port
);
612 if (bind(fd
, (struct sockaddr
*) &sa
, sizeof(sa
)) < 0)
615 fill_in_sockaddr(&sa
, s
->daddr
, s
->dport
);
619 if (connect(fd
, (struct sockaddr
*) &sa
, sizeof(sa
)) >= 0)
621 else if (errno
!= EINTR
&& errno
!= EAGAIN
)
632 #ifdef IPV6_MTU_DISCOVER
634 int dont
= IPV6_PMTUDISC_DONT
;
635 if (setsockopt(fd
, SOL_IPV6
, IPV6_MTU_DISCOVER
, &dont
, sizeof(dont
)) < 0)
636 ERR("IPV6_MTU_DISCOVER");
642 int dont
= IP_PMTUDISC_DONT
;
643 if (setsockopt(fd
, SOL_IP
, IP_PMTUDISC
, &dont
, sizeof(dont
)) < 0)
651 add_tail(&sock_list
, &s
->n
);
655 log(L_ERR
"sk_open: %s: %m", err
);
662 sk_open_unix(sock
*s
, char *name
)
665 struct sockaddr_un sa
;
668 fd
= socket(AF_UNIX
, SOCK_STREAM
, 0);
670 die("sk_open_unix: socket: %m");
672 if (err
= sk_setup(s
))
675 sa
.sun_family
= AF_UNIX
;
676 strcpy(sa
.sun_path
, name
);
677 if (bind(fd
, (struct sockaddr
*) &sa
, sizeof(sa
)) < 0)
682 add_tail(&sock_list
, &s
->n
);
686 log(L_ERR
"sk_open_unix: %s: %m", err
);
693 sk_maybe_write(sock
*s
)
702 while (s
->ttx
!= s
->tpos
)
704 e
= write(s
->fd
, s
->ttx
, s
->tpos
- s
->ttx
);
707 if (errno
!= EINTR
&& errno
!= EAGAIN
)
709 log(L_ERR
"write: %m");
710 s
->err_hook(s
, errno
);
717 s
->ttx
= s
->tpos
= s
->tbuf
;
726 if (s
->tbuf
== s
->tpos
)
728 fill_in_sockaddr(&sa
, s
->faddr
, s
->fport
);
729 e
= sendto(s
->fd
, s
->tbuf
, s
->tpos
- s
->tbuf
, 0, (struct sockaddr
*) &sa
, sizeof(sa
));
732 if (errno
!= EINTR
&& errno
!= EAGAIN
)
734 log(L_ERR
"sendto: %m");
735 s
->err_hook(s
, errno
);
744 bug("sk_maybe_write: unknown socket type %d", s
->type
);
749 sk_send(sock
*s
, unsigned len
)
754 s
->tpos
= s
->tbuf
+ len
;
755 return sk_maybe_write(s
);
759 sk_send_to(sock
*s
, unsigned len
, ip_addr addr
, unsigned port
)
764 s
->tpos
= s
->tbuf
+ len
;
765 return sk_maybe_write(s
);
776 fill_in_sockaddr(&sa
, s
->daddr
, s
->dport
);
777 if (connect(s
->fd
, (struct sockaddr
*) &sa
, sizeof(sa
)) >= 0)
779 else if (errno
!= EINTR
&& errno
!= EAGAIN
)
781 log(L_ERR
"connect: %m");
782 s
->err_hook(s
, errno
);
789 return sk_passive_connected(s
, (struct sockaddr
*) &sa
, sizeof(sa
), SK_TCP
);
791 case SK_UNIX_PASSIVE
:
793 struct sockaddr_un sa
;
794 return sk_passive_connected(s
, (struct sockaddr
*) &sa
, sizeof(sa
), SK_UNIX
);
799 int c
= read(s
->fd
, s
->rpos
, s
->rbuf
+ s
->rbsize
- s
->rpos
);
803 if (errno
!= EINTR
&& errno
!= EAGAIN
)
805 log(L_ERR
"read: %m");
806 s
->err_hook(s
, errno
);
814 if (s
->rx_hook(s
, s
->rpos
- s
->rbuf
))
821 return s
->rx_hook(s
, 0);
826 int e
= recvfrom(s
->fd
, s
->rbuf
, s
->rbsize
, 0, (struct sockaddr
*) &sa
, &al
);
830 if (errno
!= EINTR
&& errno
!= EAGAIN
)
832 log(L_ERR
"recvfrom: %m");
833 s
->err_hook(s
, errno
);
837 s
->rpos
= s
->rbuf
+ e
;
838 get_sockaddr(&sa
, &s
->faddr
, &s
->fport
);
848 while (s
->ttx
!= s
->tbuf
&& sk_maybe_write(s
) > 0)
858 debug("Open sockets:\n");
859 WALK_LIST(n
, sock_list
)
861 s
= SKIP_BACK(sock
, n
, n
);
875 volatile int async_config_flag
; /* Asynchronous reconfiguration/dump scheduled */
876 volatile int async_dump_flag
;
881 init_list(&near_timers
);
882 init_list(&far_timers
);
883 init_list(&sock_list
);
884 init_list(&global_event_list
);
904 events
= ev_run_list(&global_event_list
);
906 tout
= tm_first_shot();
912 timo
.tv_sec
= events
? 0 : tout
- now
;
916 WALK_LIST(n
, sock_list
)
918 s
= SKIP_BACK(sock
, n
, n
);
925 if (s
->tx_hook
&& s
->ttx
!= s
->tpos
)
934 * Yes, this is racy. But even if the signal comes before this test
935 * and entering select(), it gets caught on the next timer tick.
938 if (async_config_flag
)
941 async_config_flag
= 0;
950 if (async_shutdown_flag
)
953 async_shutdown_flag
= 0;
957 /* And finally enter select() to find active sockets */
959 hi
= select(hi
+1, &rd
, &wr
, NULL
, &timo
);
962 if (errno
== EINTR
|| errno
== EAGAIN
)
968 WALK_LIST_DELSAFE(n
, p
, sock_list
)
970 s
= SKIP_BACK(sock
, n
, n
);
971 if (FD_ISSET(s
->fd
, &rd
))
977 if (s
->type
!= SK_DELETED
&& FD_ISSET(s
->fd
, &wr
))
982 if (s
->type
== SK_DELETED
)