summaryrefslogtreecommitdiffstats
path: root/src/slave
diff options
context:
space:
mode:
authorGreg Hudson <ghudson@mit.edu>2010-07-01 16:56:22 +0000
committerGreg Hudson <ghudson@mit.edu>2010-07-01 16:56:22 +0000
commit3ecdc07603dfa6acc4604abfc5c2e0274204746d (patch)
treed4f87555ed503c6b6e86f69683886e02a863346c /src/slave
parentf48a0d1451b94862810f15b19b6bc81212bad225 (diff)
downloadkrb5-3ecdc07603dfa6acc4604abfc5c2e0274204746d.tar.gz
krb5-3ecdc07603dfa6acc4604abfc5c2e0274204746d.tar.xz
krb5-3ecdc07603dfa6acc4604abfc5c2e0274204746d.zip
In kpropd, when getting a wildcard address to listen on, try IPv6
explicitly (with AI_ADDRCONFIG specified where available, to avoid IPv6 on hosts with no IPv6 interface) and then fall back to IPv4. Only set IPV6_V6ONLY on the listener socket if the resulting address is IPv6. Note: we have mostly confirmed that OpenBSD does not have dual-stack support, meaning that it would be better to open separate IPv4 and IPv6 listener sockets, as we do in krb5kdc and kadmind. Unfortunately, the complicated iprop retry-and-backoff logic makes this less than straightforward. ticket: 6686 git-svn-id: svn://anonsvn.mit.edu/krb5/trunk@24156 dc483132-0cff-0310-8789-dd5450dbe970
Diffstat (limited to 'src/slave')
-rw-r--r--src/slave/kpropd.c43
1 files changed, 32 insertions, 11 deletions
diff --git a/src/slave/kpropd.c b/src/slave/kpropd.c
index c931d43cd3..a46009aed4 100644
--- a/src/slave/kpropd.c
+++ b/src/slave/kpropd.c
@@ -235,10 +235,35 @@ static void resync_alarm(int sn)
gfd = -1;
}
+/* Use getaddrinfo to determine a wildcard listener address, preferring
+ * IPv6 if available. */
+static int
+get_wildcard_addr(struct addrinfo **res)
+{
+ struct addrinfo hints;
+ int error;
+
+ memset(&hints, 0, sizeof(hints));
+ hints.ai_socktype = SOCK_STREAM;
+ hints.ai_flags = AI_PASSIVE;
+#ifdef AI_ADDRCONFIG
+ /* Try to avoid IPv6 if the host has no IPv6 interface addresses. */
+ hints.ai_flags |= AI_ADDRCONFIG;
+#endif
+#ifdef KRB5_USE_INET6
+ hints.ai_family = AF_INET6;
+ error = getaddrinfo(NULL, port, &hints, res);
+ if (error == 0)
+ return 0;
+#endif
+ hints.ai_family = AF_INET;
+ return getaddrinfo(NULL, port, &hints, res);
+}
+
int do_standalone(iprop_role iproprole)
{
struct sockaddr_in frominet;
- struct addrinfo hints, *res;
+ struct addrinfo *res;
int finet, s;
GETPEERNAME_ARG3_TYPE fromlen;
int ret, error, val;
@@ -249,12 +274,7 @@ int do_standalone(iprop_role iproprole)
retry:
- memset(&hints, 0, sizeof(hints));
- hints.ai_family = AF_UNSPEC;
- hints.ai_socktype = SOCK_STREAM;
- hints.ai_flags = AI_PASSIVE;
-
- error = getaddrinfo(NULL, port, &hints, &res);
+ error = get_wildcard_addr(&res);
if (error != 0) {
(void) fprintf(stderr, "getaddrinfo: %s\n", gai_strerror(error));
exit(1);
@@ -270,11 +290,12 @@ retry:
if (setsockopt(finet, SOL_SOCKET, SO_REUSEADDR, &val, sizeof(val)) < 0)
com_err(progname, errno, "while setting SO_REUSEADDR option");
-#ifdef IPV6_V6ONLY
- /* Typically, res will be the IPv6 wildcard address. Some systems, such as
- * the *BSDs, don't accept IPv4 connections on this address by default. */
+#if defined(KRB5_USE_INET6) && defined(IPV6_V6ONLY)
+ /* Make sure dual-stack support is enabled on IPv6 listener sockets if
+ * possible. */
val = 0;
- if (setsockopt(finet, IPPROTO_IPV6, IPV6_V6ONLY, &val, sizeof(val)) < 0)
+ if (res->ai_family == AF_INET6 &&
+ setsockopt(finet, IPPROTO_IPV6, IPV6_V6ONLY, &val, sizeof(val)) < 0)
com_err(progname, errno, "while unsetting IPV6_V6ONLY option");
#endif