From: Greg Hudson Date: Thu, 1 Jul 2010 16:56:22 +0000 (+0000) Subject: In kpropd, when getting a wildcard address to listen on, try IPv6 X-Git-Tag: krb5-1.9-beta1~175 X-Git-Url: http://git.tremily.us/?a=commitdiff_plain;h=3ecdc07603dfa6acc4604abfc5c2e0274204746d;p=krb5.git 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 --- diff --git a/src/slave/kpropd.c b/src/slave/kpropd.c index c931d43cd..a46009aed 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