diff options
author | Greg Hudson <ghudson@mit.edu> | 2010-07-01 16:56:22 +0000 |
---|---|---|
committer | Greg Hudson <ghudson@mit.edu> | 2010-07-01 16:56:22 +0000 |
commit | 3ecdc07603dfa6acc4604abfc5c2e0274204746d (patch) | |
tree | d4f87555ed503c6b6e86f69683886e02a863346c | |
parent | f48a0d1451b94862810f15b19b6bc81212bad225 (diff) | |
download | krb5-3ecdc07603dfa6acc4604abfc5c2e0274204746d.zip krb5-3ecdc07603dfa6acc4604abfc5c2e0274204746d.tar.gz krb5-3ecdc07603dfa6acc4604abfc5c2e0274204746d.tar.bz2 |
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
-rw-r--r-- | src/slave/kpropd.c | 43 |
1 files changed, 32 insertions, 11 deletions
diff --git a/src/slave/kpropd.c b/src/slave/kpropd.c index c931d43..a46009a 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 |