From 659bfd369dc6810ac5349c433455c0d317482354 Mon Sep 17 00:00:00 2001
From: Steve Grubb <sgrubb@redhat.com>
Date: Tue, 17 Oct 2017 14:31:46 -0400
Subject: [PATCH] Fixup ipv6 server side binding
---
src/auditd-listen.c | 32 ++++++++++++++++++++++++++++++++
2 files changed, 33 insertions(+)
diff --git a/src/auditd-listen.c b/src/auditd-listen.c
index 7a5c2c6..0d1717f 100644
--- a/src/auditd-listen.c
+++ b/src/auditd-listen.c
@@ -914,6 +914,7 @@ int auditd_tcp_listen_init(struct ev_loop *loop, struct daemon_conf *config)
struct addrinfo hints;
char local[16];
int one = 1, rc;
+ int prefer_ipv6 = 0;
ev_periodic_init(&periodic_watcher, periodic_handler,
0, config->tcp_client_max_idle, NULL);
@@ -929,6 +930,7 @@ int auditd_tcp_listen_init(struct ev_loop *loop, struct daemon_conf *config)
memset(&hints, '\0', sizeof(hints));
hints.ai_flags = AI_PASSIVE | AI_ADDRCONFIG;
hints.ai_socktype = SOCK_STREAM;
+ hints.ai_family = AF_UNSPEC;
snprintf(local, sizeof(local), "%ld", config->tcp_listen_port);
rc = getaddrinfo(NULL, local, &hints, &ai);
@@ -937,9 +939,32 @@ int auditd_tcp_listen_init(struct ev_loop *loop, struct daemon_conf *config)
return 1;
}
+ {
+ int ipv4 = 0, ipv6 = 0;
nlsocks = 0;
runp = ai;
while (runp && nlsocks < N_SOCKS) {
+ // Let's take a pass through and see what we got.
+ if (runp->ai_family == AF_INET)
+ ipv4++;
+ else if (runp->ai_family == AF_INET6)
+ ipv6++;
+ runp = runp->ai_next;
+ nlsocks++;
+ }
+
+ if (nlsocks == 2 && ipv4 && ipv6)
+ prefer_ipv6 = 1;
+ }
+
+ nlsocks = 0;
+ runp = ai;
+ while (runp && nlsocks < N_SOCKS) {
+ // On linux, ipv6 sockets by default include ipv4 so
+ // we only need one.
+ if (runp->ai_family == AF_INET && prefer_ipv6)
+ goto next_try;
+
listen_socket[nlsocks] = socket(runp->ai_family,
runp->ai_socktype, runp->ai_protocol);
if (listen_socket[nlsocks] < 0) {
@@ -950,6 +975,13 @@ int auditd_tcp_listen_init(struct ev_loop *loop, struct daemon_conf *config)
/* This avoids problems if auditd needs to be restarted. */
setsockopt(listen_socket[nlsocks], SOL_SOCKET, SO_REUSEADDR,
(char *)&one, sizeof (int));
+
+ // If we had more than 2 addresses suggested we'll
+ // separate the sockets.
+ if (!prefer_ipv6 && runp->ai_family == AF_INET6)
+ setsockopt(listen_socket[nlsocks], IPPROTO_IPV6,
+ IPV6_V6ONLY, &one, sizeof(int));
+
set_close_on_exec(listen_socket[nlsocks]);
if (bind(listen_socket[nlsocks], runp->ai_addr,