You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
77 lines
2.4 KiB
77 lines
2.4 KiB
7 years ago
|
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,
|