From: Wouter Wijngaards Date: Thu, 31 Oct 2013 15:06:11 +0000 (+0000) Subject: - Set SO_REUSEADDR so that the wildcard interface and a more specific X-Git-Tag: release-1.4.22rc1~94 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=d6e6354f36f364b0e600d2e16321695b7b639756;p=thirdparty%2Funbound.git - Set SO_REUSEADDR so that the wildcard interface and a more specific interface port 53 can be used at the same time, and one of the daemons is unbound. git-svn-id: file:///svn/unbound/trunk@2996 be551aaa-1e26-0410-a405-d3ace91eadb9 --- diff --git a/doc/Changelog b/doc/Changelog index 8e168dc04..841e93c6a 100644 --- a/doc/Changelog +++ b/doc/Changelog @@ -1,3 +1,8 @@ +31 Oct 2013: Wouter + - Set SO_REUSEADDR so that the wildcard interface and a more specific + interface port 53 can be used at the same time, and one of the + daemons is unbound. + 22 Oct 2013: Wouter - Patch from Neel Goyal: Add an API call to set an event base on an existing ub_ctx. This basically just destroys the current worker and diff --git a/services/listen_dnsport.c b/services/listen_dnsport.c index 368faaea4..6eeedb75e 100644 --- a/services/listen_dnsport.c +++ b/services/listen_dnsport.c @@ -91,10 +91,10 @@ verbose_print_addr(struct addrinfo *addr) int create_udp_sock(int family, int socktype, struct sockaddr* addr, socklen_t addrlen, int v6only, int* inuse, int* noproto, - int rcv, int snd) + int rcv, int snd, int listen) { int s; -#if defined(IPV6_USE_MIN_MTU) +#if defined(SO_REUSEADDR) || defined(IPV6_USE_MIN_MTU) int on=1; #endif #ifdef IPV6_MTU @@ -129,6 +129,25 @@ create_udp_sock(int family, int socktype, struct sockaddr* addr, *noproto = 0; return -1; } + if(listen) { +#ifdef SO_REUSEADDR + if(setsockopt(s, SOL_SOCKET, SO_REUSEADDR, (void*)&on, + (socklen_t)sizeof(on)) < 0) { +#ifndef USE_WINSOCK + log_err("setsockopt(.. SO_REUSEADDR ..) failed: %s", + strerror(errno)); + close(s); +#else + log_err("setsockopt(.. SO_REUSEADDR ..) failed: %s", + wsa_strerror(WSAGetLastError())); + closesocket(s); +#endif + *noproto = 0; + *inuse = 0; + return -1; + } +#endif /* SO_REUSEADDR */ + } if(rcv) { #ifdef SO_RCVBUF int got; @@ -526,7 +545,7 @@ make_sock(int stype, const char* ifname, const char* port, verbose_print_addr(res); s = create_udp_sock(res->ai_family, res->ai_socktype, (struct sockaddr*)res->ai_addr, res->ai_addrlen, - v6only, &inuse, &noproto, (int)rcv, (int)snd); + v6only, &inuse, &noproto, (int)rcv, (int)snd, 1); if(s == -1 && inuse) { log_err("bind: address already in use"); } else if(s == -1 && noproto && hints->ai_family == AF_INET6){ diff --git a/services/listen_dnsport.h b/services/listen_dnsport.h index 4d37aca5e..451a64abc 100644 --- a/services/listen_dnsport.h +++ b/services/listen_dnsport.h @@ -178,11 +178,13 @@ void listen_start_accept(struct listen_dnsport* listen); IPv6 proto (family) is not available. * @param rcv: set size on rcvbuf with socket option, if 0 it is not set. * @param snd: set size on sndbuf with socket option, if 0 it is not set. + * @param listen: if true, this is a listening UDP port, eg port 53, and + * set SO_REUSEADDR on it. * @return: the socket. -1 on error. */ int create_udp_sock(int family, int socktype, struct sockaddr* addr, socklen_t addrlen, int v6only, int* inuse, int* noproto, int rcv, - int snd); + int snd, int listen); /** * Create and bind TCP listening socket diff --git a/services/outside_network.c b/services/outside_network.c index 373d8f353..ece59098a 100644 --- a/services/outside_network.c +++ b/services/outside_network.c @@ -849,13 +849,13 @@ udp_sockport(struct sockaddr_storage* addr, socklen_t addrlen, int port, sa->sin6_port = (in_port_t)htons((uint16_t)port); fd = create_udp_sock(AF_INET6, SOCK_DGRAM, (struct sockaddr*)addr, addrlen, 1, inuse, &noproto, - 0, 0); + 0, 0, 0); } else { struct sockaddr_in* sa = (struct sockaddr_in*)addr; sa->sin_port = (in_port_t)htons((uint16_t)port); fd = create_udp_sock(AF_INET, SOCK_DGRAM, (struct sockaddr*)addr, addrlen, 1, inuse, &noproto, - 0, 0); + 0, 0, 0); } return fd; }