summaryrefslogtreecommitdiff
path: root/sysdep/unix/io.c
diff options
context:
space:
mode:
Diffstat (limited to 'sysdep/unix/io.c')
-rw-r--r--sysdep/unix/io.c47
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;
}
}