.. code-block:: ini
- local-ipv6=
local-address=127.0.0.1
local-port=5300
.. code-block:: ini
- local-ipv6=
local-address=127.0.0.1
local-port=5300
``local-address``
-----------------
+.. versionchanged:: 4.3.0
+ Before 4.3.0, this setting only supported IPv4.
+
- IPv4 Addresses, separated by commas or whitespace
-- Default: 0.0.0.0
+- Default: 0.0.0.0, ``::``
-Local IP address to which we bind. It is highly advised to bind to
+Local IP addresses to which we bind. It is highly advised to bind to
specific interfaces and not use the default 'bind to any'. This causes
big problems if you have multiple IP addresses. Unix does not provide a
way of figuring out what IP address a packet was sent to when binding to
``local-ipv6``
--------------
+.. deprecated:: 4.3.0
+ This setting has been removed, use :ref:`setting-localaddress`
+
- IPv6 Addresses, separated by commas or whitespace
- Default: '::'
``local-ipv6-nonexist-fail``
----------------------------
+.. deprecated:: 4.3.0
+ This setting has been removed, use :ref:`setting-localaddress-nonexist-fail`
+
- Boolean
- Default: no
::arg().setSwitch("forward-dnsupdate","A global setting to allow DNS update packages that are for a Slave domain, to be forwarded to the master.")="yes";
::arg().setSwitch("log-dns-details","If PDNS should log DNS non-erroneous details")="no";
::arg().setSwitch("log-dns-queries","If PDNS should log all incoming DNS queries")="no";
- ::arg().set("local-address","Local IP addresses to which we bind")="0.0.0.0";
+ ::arg().set("local-address","Local IP addresses to which we bind")="0.0.0.0, ::";
::arg().setSwitch("local-address-nonexist-fail","Fail to start if one or more of the local-address's do not exist on this server")="yes";
::arg().setSwitch("non-local-bind", "Enable binding to non-local addresses by using FREEBIND / BINDANY socket options")="no";
- ::arg().set("local-ipv6","Local IP address to which we bind")="::";
::arg().setSwitch("reuseport","Enable higher performance on compliant kernels by using SO_REUSEPORT allowing each receiver thread to open its own socket")="no";
- ::arg().setSwitch("local-ipv6-nonexist-fail","Fail to start if one or more of the local-ipv6 addresses do not exist on this server")="yes";
::arg().set("query-local-address","Source IP address for sending queries")="0.0.0.0";
::arg().set("query-local-address6","Source IPv6 address for sending queries")="::";
::arg().set("overload-queue-length","Maximum queuelength moving to packetcache only")="0";
vector<ComboAddress> g_localaddresses; // not static, our unit tests need to poke this
-void UDPNameserver::bindIPv4()
+void UDPNameserver::bindAddresses()
{
vector<string>locals;
stringtok(locals,::arg()["local-address"]," ,");
throw PDNSException("No local address specified");
int s;
- for(vector<string>::const_iterator i=locals.begin();i!=locals.end();++i) {
- string localname(*i);
- ComboAddress locala;
+ // for(vector<string>::const_iterator i=locals.begin();i!=locals.end();++i) {
+ for (const auto &local : locals) {
+ ComboAddress locala(local, ::arg().asNum("local-port"));
- s=socket(AF_INET,SOCK_DGRAM,0);
+ s = socket(locala.sin4.sin_family, SOCK_DGRAM, 0);
- if(s<0) {
- int err = errno;
- g_log<<Logger::Error<<"Unable to acquire UDP socket: "+stringerror(err) << endl;
- throw PDNSException("Unable to acquire a UDP socket: "+stringerror(err));
+ if(s < 0) {
+ if(errno == EAFNOSUPPORT) {
+ g_log<<Logger::Error<<"Binding "<<locala.toStringWithPort()<<": Address Family is not supported - skipping bind" << endl;
+ return;
+ }
+ throw PDNSException("Unable to acquire a UDP socket: "+stringerror());
}
-
+
setCloseOnExec(s);
-
if(!setNonBlocking(s))
- throw PDNSException("Unable to set UDP socket to non-blocking: "+stringerror());
-
- locala=ComboAddress(localname, ::arg().asNum("local-port"));
+ throw PDNSException("Unable to set UDP socket " + locala.toStringWithPort() + " to non-blocking: "+stringerror());
- if(locala.sin4.sin_family != AF_INET)
- throw PDNSException("Attempting to bind IPv4 socket to IPv6 address");
-
- if(IsAnyAddress(locala))
+ if(IsAnyAddress(locala)) {
setsockopt(s, IPPROTO_IP, GEN_IP_PKTINFO, &one, sizeof(one));
+ if (locala.isIPv6()) {
+ setsockopt(s, IPPROTO_IPV6, IPV6_V6ONLY, &one, sizeof(one)); // if this fails, we report an error in tcpreceiver too
+#ifdef IPV6_RECVPKTINFO
+ setsockopt(s, IPPROTO_IPV6, IPV6_RECVPKTINFO, &one, sizeof(one));
+#endif
+ }
+ }
if (!setSocketTimestamps(s))
- g_log<<Logger::Warning<<"Unable to enable timestamp reporting for socket"<<endl;
+ g_log<<Logger::Warning<<"Unable to enable timestamp reporting for socket "<<locala.toStringWithPort()<<endl;
if (locala.isIPv4()) {
try {
#endif
if( ::arg().mustDo("non-local-bind") )
- Utility::setBindAny(AF_INET, s);
-
+ Utility::setBindAny(locala.sin4.sin_family, s);
if( !d_additional_socket )
g_localaddresses.push_back(locala);
string binderror = stringerror();
close(s);
if( errno == EADDRNOTAVAIL && ! ::arg().mustDo("local-address-nonexist-fail") ) {
- g_log<<Logger::Error<<"IPv4 Address " << localname << " does not exist on this server - skipping UDP bind" << endl;
+ g_log<<Logger::Error<<"Address " << locala << " does not exist on this server - skipping UDP bind" << endl;
continue;
} else {
g_log<<Logger::Error<<"Unable to bind UDP socket to '"+locala.toStringWithPort()+"': "<<binderror<<endl;
}
}
d_sockets.push_back(s);
- g_log<<Logger::Error<<"UDP server bound to "<<locala.toStringWithPort()<<endl;
struct pollfd pfd;
pfd.fd = s;
pfd.events = POLLIN;
pfd.revents = 0;
d_rfds.push_back(pfd);
+ g_log<<Logger::Error<<"UDP server bound to "<<locala.toStringWithPort()<<endl;
}
}
return false;
}
-
-void UDPNameserver::bindIPv6()
-{
- vector<string> locals;
- stringtok(locals,::arg()["local-ipv6"]," ,");
- int one=1;
-
- if(locals.empty())
- return;
-
- int s;
- for(vector<string>::const_iterator i=locals.begin();i!=locals.end();++i) {
- string localname(*i);
-
- s=socket(AF_INET6,SOCK_DGRAM,0);
- if(s<0) {
- if( errno == EAFNOSUPPORT ) {
- g_log<<Logger::Error<<"IPv6 Address Family is not supported - skipping UDPv6 bind" << endl;
- return;
- } else {
- g_log<<Logger::Error<<"Unable to acquire a UDPv6 socket: "+stringerror() << endl;
- throw PDNSException("Unable to acquire a UDPv6 socket: "+stringerror());
- }
- }
-
- setCloseOnExec(s);
- if(!setNonBlocking(s))
- throw PDNSException("Unable to set UDPv6 socket to non-blocking: "+stringerror());
-
- ComboAddress locala(localname, ::arg().asNum("local-port"));
-
- if(IsAnyAddress(locala)) {
- setsockopt(s, IPPROTO_IP, GEN_IP_PKTINFO, &one, sizeof(one)); // linux supports this, so why not - might fail on other systems
-#ifdef IPV6_RECVPKTINFO
- setsockopt(s, IPPROTO_IPV6, IPV6_RECVPKTINFO, &one, sizeof(one));
-#endif
- setsockopt(s, IPPROTO_IPV6, IPV6_V6ONLY, &one, sizeof(one)); // if this fails, we report an error in tcpreceiver too
- }
-
- if (!setSocketTimestamps(s))
- g_log<<Logger::Warning<<"Unable to enable timestamp reporting for socket"<<endl;
-
-#ifdef SO_REUSEPORT
- if( d_can_reuseport )
- if( setsockopt(s, SOL_SOCKET, SO_REUSEPORT, &one, sizeof(one)) )
- d_can_reuseport = false;
-#endif
-
- if( ::arg().mustDo("non-local-bind") )
- Utility::setBindAny(AF_INET6, s);
-
- if( !d_additional_socket )
- g_localaddresses.push_back(locala);
- if(::bind(s, (sockaddr*)&locala, locala.getSocklen())<0) {
- close(s);
- if( errno == EADDRNOTAVAIL && ! ::arg().mustDo("local-ipv6-nonexist-fail") ) {
- g_log<<Logger::Error<<"IPv6 Address " << localname << " does not exist on this server - skipping UDP bind" << endl;
- continue;
- } else {
- g_log<<Logger::Error<<"Unable to bind to UDPv6 socket "<< localname <<": "<<stringerror()<<endl;
- throw PDNSException("Unable to bind to UDPv6 socket");
- }
- }
- d_sockets.push_back(s);
- struct pollfd pfd;
- pfd.fd = s;
- pfd.events = POLLIN;
- pfd.revents = 0;
- d_rfds.push_back(pfd);
- g_log<<Logger::Error<<"UDPv6 server bound to "<<locala.toStringWithPort()<<endl;
- }
-}
-
UDPNameserver::UDPNameserver( bool additional_socket )
{
#ifdef SO_REUSEPORT
// Are we the main socket (false) or a rebinding using SO_REUSEPORT ?
d_additional_socket = additional_socket;
- if(!::arg()["local-address"].empty())
- bindIPv4();
- if(!::arg()["local-ipv6"].empty())
- bindIPv6();
-
- if(::arg()["local-address"].empty() && ::arg()["local-ipv6"].empty())
+ if(::arg()["local-address"].empty())
g_log<<Logger::Critical<<"PDNS is deaf and mute! Not listening on any interfaces"<<endl;
+
+ bindAddresses();
}
void UDPNameserver::send(DNSPacket& p)
bool d_can_reuseport;
#endif
vector<int> d_sockets;
- void bindIPv4();
- void bindIPv6();
+ void bindAddresses();
vector<pollfd> d_rfds;
};
d_connectionroom_sem = make_unique<Semaphore>( ::arg().asNum( "max-tcp-connections" ));
d_maxTCPConnections = ::arg().asNum( "max-tcp-connections" );
d_tid=0;
+
vector<string>locals;
stringtok(locals,::arg()["local-address"]," ,");
-
- vector<string>locals6;
- stringtok(locals6,::arg()["local-ipv6"]," ,");
-
- if(locals.empty() && locals6.empty())
- throw PDNSException("No local address specified");
+ if(locals.empty())
+ throw PDNSException("No local addresses specified");
d_ng.toMasks(::arg()["allow-axfr-ips"] );
signal(SIGPIPE,SIG_IGN);
- for(vector<string>::const_iterator laddr=locals.begin();laddr!=locals.end();++laddr) {
- int s=socket(AF_INET,SOCK_STREAM,0);
-
- if(s<0)
- throw PDNSException("Unable to acquire TCP socket: "+stringerror());
+ for(auto const &laddr : locals) {
+ ComboAddress local(laddr, ::arg().asNum("local-port"));
+ int s=socket(local.sin4.sin_family, SOCK_STREAM, 0);
+ if(s<0)
+ throw PDNSException("Unable to acquire TCP socket: "+stringerror());
setCloseOnExec(s);
- ComboAddress local(*laddr, ::arg().asNum("local-port"));
-
int tmp=1;
- if(setsockopt(s,SOL_SOCKET,SO_REUSEADDR,(char*)&tmp,sizeof tmp)<0) {
+ if(setsockopt(s, SOL_SOCKET,SO_REUSEADDR, (char*)&tmp, sizeof tmp) < 0) {
g_log<<Logger::Error<<"Setsockopt failed"<<endl;
- _exit(1);
+ _exit(1);
}
if (::arg().asNum("tcp-fast-open") > 0) {
#ifdef TCP_FASTOPEN
int fastOpenQueueSize = ::arg().asNum("tcp-fast-open");
if (setsockopt(s, IPPROTO_TCP, TCP_FASTOPEN, &fastOpenQueueSize, sizeof fastOpenQueueSize) < 0) {
- g_log<<Logger::Error<<"Failed to enable TCP Fast Open for listening socket: "<<stringerror()<<endl;
+ g_log<<Logger::Error<<"Failed to enable TCP Fast Open for listening socket "<<local.toStringWithPort()<<": "<<stringerror()<<endl;
}
#else
g_log<<Logger::Warning<<"TCP Fast Open configured but not supported for listening socket"<<endl;
#endif
}
- if( ::arg().mustDo("non-local-bind") )
- Utility::setBindAny(AF_INET, s);
+ if(::arg().mustDo("non-local-bind"))
+ Utility::setBindAny(local.sin4.sin_family, s);
+
+ if(local.isIPv6() && setsockopt(s, IPPROTO_IPV6, IPV6_V6ONLY, &tmp, sizeof(tmp)) < 0) {
+ g_log<<Logger::Error<<"Failed to set IPv6 socket to IPv6 only, continuing anyhow: "<<stringerror()<<endl;
+ }
if(::bind(s, (sockaddr*)&local, local.getSocklen())<0) {
int err = errno;
close(s);
if( err == EADDRNOTAVAIL && ! ::arg().mustDo("local-address-nonexist-fail") ) {
- g_log<<Logger::Error<<"IPv4 Address " << *laddr << " does not exist on this server - skipping TCP bind" << endl;
+ g_log<<Logger::Error<<"Address " << local.toString() << " does not exist on this server - skipping TCP bind" << endl;
continue;
} else {
- g_log<<Logger::Error<<"Unable to bind to TCP socket " << *laddr << ": "<<stringerror(err)<<endl;
+ g_log<<Logger::Error<<"Unable to bind to TCP socket " << local.toStringWithPort() << ": "<<stringerror(err)<<endl;
throw PDNSException("Unable to bind to TCP socket");
}
}
-
- listen(s,128);
- g_log<<Logger::Error<<"TCP server bound to "<<local.toStringWithPort()<<endl;
- d_sockets.push_back(s);
- struct pollfd pfd;
- memset(&pfd, 0, sizeof(pfd));
- pfd.fd = s;
- pfd.events = POLLIN;
-
- d_prfds.push_back(pfd);
- }
- for(vector<string>::const_iterator laddr=locals6.begin();laddr!=locals6.end();++laddr) {
- int s=socket(AF_INET6,SOCK_STREAM,0);
-
- if(s<0)
- throw PDNSException("Unable to acquire TCPv6 socket: "+stringerror());
-
- setCloseOnExec(s);
-
- ComboAddress local(*laddr, ::arg().asNum("local-port"));
-
- int tmp=1;
- if(setsockopt(s,SOL_SOCKET,SO_REUSEADDR,(char*)&tmp,sizeof tmp)<0) {
- g_log<<Logger::Error<<"Setsockopt failed"<<endl;
- _exit(1);
- }
-
- if (::arg().asNum("tcp-fast-open") > 0) {
-#ifdef TCP_FASTOPEN
- int fastOpenQueueSize = ::arg().asNum("tcp-fast-open");
- if (setsockopt(s, IPPROTO_TCP, TCP_FASTOPEN, &fastOpenQueueSize, sizeof fastOpenQueueSize) < 0) {
- g_log<<Logger::Error<<"Failed to enable TCP Fast Open for listening socket: "<<stringerror()<<endl;
- }
-#else
- g_log<<Logger::Warning<<"TCP Fast Open configured but not supported for listening socket"<<endl;
-#endif
- }
-
- if( ::arg().mustDo("non-local-bind") )
- Utility::setBindAny(AF_INET6, s);
- if(setsockopt(s, IPPROTO_IPV6, IPV6_V6ONLY, &tmp, sizeof(tmp)) < 0) {
- g_log<<Logger::Error<<"Failed to set IPv6 socket to IPv6 only, continuing anyhow: "<<stringerror()<<endl;
- }
- if(bind(s, (const sockaddr*)&local, local.getSocklen())<0) {
- int err = errno;
- close(s);
- if( err == EADDRNOTAVAIL && ! ::arg().mustDo("local-ipv6-nonexist-fail") ) {
- g_log<<Logger::Error<<"IPv6 Address " << *laddr << " does not exist on this server - skipping TCP bind" << endl;
- continue;
- } else {
- g_log<<Logger::Error<<"Unable to bind to TCPv6 socket" << *laddr << ": "<<stringerror(err)<<endl;
- throw PDNSException("Unable to bind to TCPv6 socket");
- }
- }
-
- listen(s,128);
- g_log<<Logger::Error<<"TCPv6 server bound to "<<local.toStringWithPort()<<endl; // this gets %eth0 right
+ listen(s, 128);
+ g_log<<Logger::Error<<"TCP server bound to "<<local.toStringWithPort()<<endl;
d_sockets.push_back(s);
-
struct pollfd pfd;
memset(&pfd, 0, sizeof(pfd));
pfd.fd = s;
pfd.events = POLLIN;
-
d_prfds.push_back(pfd);
}
}
pdns_conf.write(AUTH_CONF_TPL)
run_check_call(PDNSUTIL_CMD + ["secure-zone", "powerdnssec.org"])
- servercmd = [pdns_server] + common_args + ["--local-ipv6=", "--no-shuffle", "--dnsupdate=yes", "--cache-ttl=0", "--api=yes"]
+ servercmd = [pdns_server] + common_args + ["--no-shuffle", "--dnsupdate=yes", "--cache-ttl=0", "--api=yes"]
else:
conf_dir = 'rec-conf.d'
_config_template_default = """
module-dir=../regression-tests/modules
daemon=no
-local-ipv6=
bind-config={confdir}/named.conf
bind-dnssec-db={bind_dnssec_db}
socket-dir={confdir}
rm -f pdns*.pid
-$PDNS --daemon=no --local-ipv6=::1 --local-address=127.0.0.1 \
+$PDNS --daemon=no --local-address=127.0.0.1,::1 \
--local-port=$port --socket-dir=./ --no-shuffle --launch=random --no-config \
--module-dir=../regression-tests/modules &
rm -f pdns*.pid
-$PDNS --daemon=no --local-ipv6=::1 --local-address=127.0.0.1 \
+$PDNS --daemon=no --local-address=127.0.0.1,::1 \
--local-port=$port --socket-dir=./ --no-shuffle --launch=pipe --no-config \
--module-dir=../regression-tests/modules --pipe-command=$(pwd)/distributor/slow.pl \
--pipe-abi-version=5 \
{
$RUNWRAPPER $PDNS --daemon=no --local-port=$port --config-dir=. --module-dir=../regression-tests/modules \
--config-name=gsqlite3-master --socket-dir=./ --no-shuffle \
- --master=yes --local-address=127.0.0.1 --local-ipv6='' \
+ --master=yes --local-address=127.0.0.1 \
--query-local-address=127.0.0.1 --cache-ttl=$cachettl --dname-processing --allow-axfr-ips= &
}
slaveport=53
$RUNWRAPPER $PDNS2 --daemon=no --local-port=$slaveport --config-dir=. --module-dir=../regression-tests/modules \
- --config-name=gsqlite3-slave --socket-dir=./ --no-shuffle --local-address=127.0.0.2 --local-ipv6='' \
+ --config-name=gsqlite3-slave --socket-dir=./ --no-shuffle --local-address=127.0.0.2 \
--slave --retrieval-threads=4 --slave=yes --superslave=yes --query-local-address=127.0.0.2 \
--slave-cycle-interval=300 --allow-unsigned-notify=no --allow-unsigned-supermaster=no &
}
{
$RUNWRAPPER $PDNS --daemon=no --local-port=$port --config-dir=. --module-dir=../regression-tests/modules \
--config-name=gsqlite3-master --socket-dir=./ --no-shuffle \
- --master=yes --local-address=127.0.0.1 --local-ipv6= \
+ --master=yes --local-address=127.0.0.1 \
--query-local-address=127.0.0.1 --cache-ttl=$cachettl --dname-processing --allow-axfr-ips= &
}
slaveport=53
$RUNWRAPPER $PDNS2 --daemon=no --local-port=$slaveport --config-dir=. --module-dir=../regression-tests/modules \
- --config-name=gsqlite3-slave --socket-dir=./ --no-shuffle --local-address=127.0.0.2 --local-ipv6= \
+ --config-name=gsqlite3-slave --socket-dir=./ --no-shuffle --local-address=127.0.0.2 \
--slave --retrieval-threads=4 --slave=yes --superslave=yes --query-local-address=127.0.0.2 \
--slave-cycle-interval=300 --dname-processing &
}
module-dir=../regression-tests/modules
launch=bind
daemon=no
-local-ipv6=
bind-config={confdir}/named.conf
bind-dnssec-db={bind_dnssec_db}
socket-dir={confdir}
authcmd = list(cls._auth_cmd)
authcmd.append('--config-dir=%s' % confdir)
authcmd.append('--local-address=%s' % ipaddress)
+ authcmd.append('--local-ipv6=')
print(' '.join(authcmd))
logFile = os.path.join(confdir, 'pdns.log')
launch=bind
daemon=no
local-address=$dir
+## TODO remove when switching circle-ci and travis to 4.3
local-ipv6=
bind-config=named.conf
no-shuffle
distributor-threads=1
EOF
-
if [ -e $dir/prequery.lua ]
then
echo 'lua-prequery-script=prequery.lua' >> $dir/pdns.conf