From fc1611fc40382ced82487821507af0a5f5504ae8 Mon Sep 17 00:00:00 2001 From: Erik Ekman Date: Tue, 30 Jun 2015 21:56:11 +0200 Subject: [PATCH] Only accept IPv6 in server IPv6 socket Set IPV6_V6ONLY flag on server socket. Not all operating systems support mixing v4/v6 in one socket, so separate them all the time. --- src/common.c | 10 ++++++++++ src/common.h | 1 + src/iodined.c | 4 +++- 3 files changed, 14 insertions(+), 1 deletion(-) diff --git a/src/common.c b/src/common.c index 2062239..ce6c2aa 100644 --- a/src/common.c +++ b/src/common.c @@ -172,6 +172,12 @@ get_addr(char *host, int port, int addr_family, int flags, struct sockaddr_stora int open_dns(struct sockaddr_storage *sockaddr, size_t sockaddr_len) +{ + return open_dns_opt(sockaddr, sockaddr_len, -1); +} + +int +open_dns_opt(struct sockaddr_storage *sockaddr, size_t sockaddr_len, int v6only) { int flag; int fd; @@ -190,6 +196,10 @@ open_dns(struct sockaddr_storage *sockaddr, size_t sockaddr_len) fd_set_close_on_exec(fd); #endif + if (sockaddr->ss_family == AF_INET6 && v6only >= 0) { + setsockopt(fd, IPPROTO_IPV6, IPV6_V6ONLY, (const void*) &v6only, sizeof(v6only)); + } + #ifdef IP_OPT_DONT_FRAG /* Set dont-fragment ip header flag */ flag = DONT_FRAG_VALUE; diff --git a/src/common.h b/src/common.h index cb59f3f..2de23e9 100644 --- a/src/common.h +++ b/src/common.h @@ -106,6 +106,7 @@ void check_superuser(void (*usage_fn)(void)); char *format_addr(struct sockaddr_storage *sockaddr, int sockaddr_len); int get_addr(char *, int, int, int, struct sockaddr_storage *); int open_dns(struct sockaddr_storage *, size_t); +int open_dns_opt(struct sockaddr_storage *sockaddr, size_t sockaddr_len, int v6only); int open_dns_from_host(char *host, int port, int addr_family, int flags); void close_dns(int); diff --git a/src/iodined.c b/src/iodined.c index 51b9c13..659c9a7 100644 --- a/src/iodined.c +++ b/src/iodined.c @@ -2687,7 +2687,9 @@ main(int argc, char **argv) goto cleanup; } if ((addrfamily == AF_UNSPEC || addrfamily == AF_INET6) && - (dns_fds.v6fd = open_dns(&dns6addr, dns6addr_len)) < 0) { + /* Set IPv6 socket to V6ONLY */ + (dns_fds.v6fd = open_dns_opt(&dns6addr, dns6addr_len, 1)) < 0) { + retval = 1; goto cleanup; }