diff options
Diffstat (limited to 'sysdep/unix/io.c')
-rw-r--r-- | sysdep/unix/io.c | 47 |
1 files changed, 36 insertions, 11 deletions
diff --git a/sysdep/unix/io.c b/sysdep/unix/io.c index e3e2f5f8..c8916378 100644 --- a/sysdep/unix/io.c +++ b/sysdep/unix/io.c @@ -9,7 +9,9 @@ /* Unfortunately, some glibc versions hide parts of RFC 3542 API if _GNU_SOURCE is not defined. */ -#define _GNU_SOURCE 1 +#ifndef _GNU_SOURCE +#define _GNU_SOURCE +#endif #include <stdio.h> #include <stdlib.h> @@ -507,11 +509,11 @@ tm_format_datetime(char *x, struct timeformat *fmt_spec, bird_clock_t t) * Sockaddr helper functions */ -static inline int sockaddr_length(int af) +static inline int UNUSED sockaddr_length(int af) { return (af == AF_INET) ? sizeof(struct sockaddr_in) : sizeof(struct sockaddr_in6); } static inline void -sockaddr_fill4(struct sockaddr_in *sa, ip_addr a, struct iface *ifa, uint port) +sockaddr_fill4(struct sockaddr_in *sa, ip_addr a, uint port) { memset(sa, 0, sizeof(struct sockaddr_in)); #ifdef HAVE_SIN_LEN @@ -542,7 +544,7 @@ void sockaddr_fill(sockaddr *sa, int af, ip_addr a, struct iface *ifa, uint port) { if (af == AF_INET) - sockaddr_fill4((struct sockaddr_in *) sa, a, ifa, port); + sockaddr_fill4((struct sockaddr_in *) sa, a, port); else if (af == AF_INET6) sockaddr_fill6((struct sockaddr_in6 *) sa, a, ifa, port); else @@ -550,7 +552,7 @@ sockaddr_fill(sockaddr *sa, int af, ip_addr a, struct iface *ifa, uint port) } static inline void -sockaddr_read4(struct sockaddr_in *sa, ip_addr *a, struct iface **ifa, uint *port) +sockaddr_read4(struct sockaddr_in *sa, ip_addr *a, uint *port) { *port = ntohs(sa->sin_port); *a = ipa_from_in4(sa->sin_addr); @@ -573,7 +575,7 @@ sockaddr_read(sockaddr *sa, int af, ip_addr *a, struct iface **ifa, uint *port) goto fail; if (af == AF_INET) - sockaddr_read4((struct sockaddr_in *) sa, a, ifa, port); + sockaddr_read4((struct sockaddr_in *) sa, a, port); else if (af == AF_INET6) sockaddr_read6((struct sockaddr_in6 *) sa, a, ifa, port); else @@ -770,7 +772,7 @@ sk_set_tos6(sock *s, int tos) } static inline int -sk_set_high_port(sock *s) +sk_set_high_port(sock *s UNUSED) { /* Port range setting is optional, ignore it if not supported */ @@ -1293,7 +1295,7 @@ sk_setup(sock *s) if (sk_is_ipv6(s)) { - if (s->type != SK_IP) + if ((s->type == SK_TCP_PASSIVE) || (s->type == SK_TCP_ACTIVE) || (s->type == SK_UDP)) if (setsockopt(fd, SOL_IPV6, IPV6_V6ONLY, &y, sizeof(y)) < 0) ERR("IPV6_V6ONLY"); @@ -2247,6 +2249,20 @@ int sk_is_ipv6(sock *s) { return s->af == AF_INET6; } void +sk_err(sock *s, int revents) +{ + int se = 0, sse = sizeof(se); + if ((s->type != SK_MAGIC) && (revents & POLLERR)) + if (getsockopt(s->fd, SOL_SOCKET, SO_ERROR, &se, &sse) < 0) + { + log(L_ERR "IO: Socket error: SO_ERROR: %m"); + se = 0; + } + + s->err_hook(s, se); +} + +void sk_dump_all(void) { node *n; @@ -2557,7 +2573,7 @@ io_loop(void) int steps; steps = MAX_STEPS; - if (s->fast_rx && (pfd[s->index].revents & (POLLIN | POLLHUP | POLLERR)) && s->rx_hook) + if (s->fast_rx && (pfd[s->index].revents & POLLIN) && s->rx_hook) do { steps--; @@ -2579,6 +2595,7 @@ io_loop(void) goto next; } while (e && steps); + current_sock = sk_next(s); next: ; } @@ -2602,18 +2619,26 @@ io_loop(void) goto next2; } - if (!s->fast_rx && (pfd[s->index].revents & (POLLIN | POLLHUP | POLLERR)) && s->rx_hook) + if (!s->fast_rx && (pfd[s->index].revents & POLLIN) && s->rx_hook) { count++; io_log_event(s->rx_hook, s->data); sk_read(s, pfd[s->index].revents); if (s != current_sock) - goto next2; + goto next2; } + + if (pfd[s->index].revents & (POLLHUP | POLLERR)) + { + sk_err(s, pfd[s->index].revents); + goto next2; + } + current_sock = sk_next(s); next2: ; } + stored_sock = current_sock; } } |