run: |
for tag in `echo "${INPUT_IMAGE_TAGS}" | tr '\n' ' '`; do
echo 'Testing: '${IMAGE_NAME}':'${tag};
- # recent pdns-auth images of tags older than 4.9.x image return a exit code 99
+ # recent pdns-auth images of tags older than 4.9.x image return an exit code 99
docker run ${IMAGE_NAME}:${tag} --version || [ "$?" == "99" ]
done
- name: Check image digest matches
jobs:
build:
name: Verify source code formatting; check Makefile.am sort order
- # on a ubuntu-24.04 VM
+ # on an ubuntu-24.04 VM
runs-on: ubuntu-24.04
steps:
- uses: actions/checkout@v5
jobs:
build:
name: check secpoll zone
- # on a ubuntu-24.04 VM
+ # on an ubuntu-24.04 VM
runs-on: ubuntu-24.04
steps:
- uses: PowerDNS/pdns/set-ubuntu-mirror@meta
Since stack-allocated objects, like local variables in a function, are automatically destroyed when a function exits, be it by reaching the last line, calling return or throwing an exception, it makes it possible to ensure that resources are always properly destroyed by wrapping them in an object.
We describe the use of smart pointers, containers and other wrappers for that purpose below, but first a few words of caution.
-Resources stored in a object are only tied to this object if the constructor executes fully and completes properly.
+Resources stored in an object are only tied to this object if the constructor executes fully and completes properly.
If an exception is raised in the constructor's body, the object is not created and therefore the destructor will not be called.
This means that if the object has non-object members holding resources, like raw file descriptors or raw C-style pointers, they need to be explicitly released before raising the exception; otherwise, they are lost or leaked.
On autoprimary
~~~~~~~~~~~~~~
-- ``autoprimary-query``: Called to determine if a certain host is a autoprimary for a certain domain name.
-- ``autoprimary-name-to-ips``: Called to the IP and account for a autoprimary.
+- ``autoprimary-query``: Called to determine if a certain host is an autoprimary for a certain domain name.
+- ``autoprimary-name-to-ips``: Called to the IP and account for an autoprimary.
TSIG
^^^^
- table ctx - Query context table, contains ``source_address`` and ``real_source_address``.
OUTPUT:
- Expects a array which has tables with following keys:
+ Expects an array which has tables with following keys:
- DNSName name - resource record name (can also be string)
- string type - type of resource record (can also be QType or valid integer)
autoprimary add *IP* *NAMESERVER* [*ACCOUNT*]
- Add a autoprimary entry into the backend. This enables receiving zone
+ Add an autoprimary entry into the backend. This enables receiving zone
updates from other servers.
autoprimary list
There is no need to fill the account name out but it does help keep
track of where a domain comes from.
Additionally, if a secondary selects multiple autoprimaries for a zone based on the name of the primary, it also checks that the ``account`` field is the same for all.
-Adding a autoprimary can be done either directly in the database,
+Adding an autoprimary can be done either directly in the database,
or by using the ``pdnsutil autoprimary add`` command (``pdnsutil
add-autoprimary`` prior to version 5.0).
-This test checks that you can have a apex record as both service record and static record.
+This test checks that you can have an apex record as both service record and static record.
::arg().set("module-dir") = "./.libs";
auto loader = std::make_unique<RemoteLoader>();
BackendMakers().launch("remote");
- // then get us a instance of it
+ // then get us an instance of it
::arg().set("remote-connection-string") = "http:url=http://localhost:62434/dns";
::arg().set("remote-dnssec") = "yes";
backendUnderTest = std::move(BackendMakers().all()[0]);
::arg().set("module-dir") = "./.libs";
auto loader = std::make_unique<RemoteLoader>();
BackendMakers().launch("remote");
- // then get us a instance of it
+ // then get us an instance of it
::arg().set("remote-connection-string") = "http:url=http://localhost:62434/dns/endpoint.json,post=1,post_json=1";
::arg().set("remote-dnssec") = "yes";
backendUnderTest = std::move(BackendMakers().all()[0]);
::arg().set("module-dir") = "./.libs";
auto loader = std::make_unique<RemoteLoader>();
BackendMakers().launch("remote");
- // then get us a instance of it
+ // then get us an instance of it
::arg().set("remote-connection-string") = "pipe:command=unittest_pipe.py";
::arg().set("remote-dnssec") = "yes";
backendUnderTest = std::move(BackendMakers().all()[0]);
::arg().set("module-dir") = "./.libs";
auto loader = std::make_unique<RemoteLoader>();
BackendMakers().launch("remote");
- // then get us a instance of it
+ // then get us an instance of it
::arg().set("remote-connection-string") = "http:url=http://localhost:62434/dns,post=1";
::arg().set("remote-dnssec") = "yes";
backendUnderTest = std::move(BackendMakers().all()[0]);
::arg().set("module-dir") = "./.libs";
auto loader = std::make_unique<RemoteLoader>();
BackendMakers().launch("remote");
- // then get us a instance of it
+ // then get us an instance of it
::arg().set("remote-connection-string") = "unix:path=/tmp/remotebackend.sock";
::arg().set("remote-dnssec") = "yes";
backendUnderTest = std::move(BackendMakers().all()[0]);
::arg().set("module-dir") = "./.libs";
auto loader = std::make_unique<RemoteLoader>();
BackendMakers().launch("remote");
- // then get us a instance of it
+ // then get us an instance of it
::arg().set("remote-connection-string") = "zeromq:endpoint=ipc:///tmp/remotebackend.0";
::arg().set("remote-dnssec") = "yes";
backendUnderTest = std::move(BackendMakers().all()[0]);
// clang-format on
}
catch (SSqlException &e) {
- throw PDNSException("GSQLBackend unable to search for a autoprimary with IP " + ipAddress + " and nameserver name '" + i.content + "' for domain '" + domain.toLogString() + "': " + e.txtReason());
+ throw PDNSException("GSQLBackend unable to search for an autoprimary with IP " + ipAddress + " and nameserver name '" + i.content + "' for domain '" + domain.toLogString() + "': " + e.txtReason());
}
if(!d_result.empty()) {
ASSERT_ROW_COLUMNS("autoprimary-query", d_result[0], 1);
return false;
}
- //! determine if ip is a autoprimary or a domain
+ //! determine if ip is an autoprimary or a domain
virtual bool autoPrimaryBackend(const string& /* ip */, const ZoneName& /* domain */, const vector<DNSResourceRecord>& /* nsset */, string* /* nameserver */, string* /* account */, DNSBackend** /* db */)
{
return false;
return false;
}
- //! called by PowerDNS to create a secondary record for a autoPrimary
+ //! called by PowerDNS to create a secondary record for an autoPrimary
virtual bool createSecondaryDomain(const string& /* ip */, const ZoneName& /* domain */, const string& /* nameserver */, const string& /* account */)
{
return false;
mostly to keep some counters like the 'outstanding' one sane.
We have two flags:
- - inUse tells us if there currently is a in-flight query whose state is stored
+ - inUse tells us if there currently is an in-flight query whose state is stored
in this state
- locked tells us whether someone currently owns the state, so no-one else can touch
it
/* We are never called for a GETNEXT if it's registered as a
"instance", as it's "magically" handled for us. */
-/* a instance handler also only hands us one request at a time, so
+/* an instance handler also only hands us one request at a time, so
we don't need to loop over a list of requests; we'll only get one. */
static int handleCounter64Stats(netsnmp_mib_handler* handler,
:pullreq: 11621
:tickets: 11604
- Fix a crash on a invalid protocol in DoH forwarded-for header
+ Fix a crash on an invalid protocol in DoH forwarded-for header
.. change::
:tags: Bug Fixes
:pullreq: 11667
:tickets: 11621
- Fix a crash on a invalid protocol in DoH forwarded-for header
+ Fix a crash on an invalid protocol in DoH forwarded-for header
.. changelog::
:version: 1.7.1
:align: center
:alt: DNSDist Lazy health checks
-The threshold of failed regular queries is configured via ``lazyHealthCheckThreshold``, indicating of percentage of regular queries that should have resulted in a failure over the last recent queries. Only the results of the last ``lazyHealthCheckSampleSize`` queries will be considered, as the results are kept in a in-memory circular buffer. The results of at least ``lazyHealthCheckMinSampleCount`` queries should be present for the threshold to be considered meaningful, to avoid an issue with a too small sample.
+The threshold of failed regular queries is configured via ``lazyHealthCheckThreshold``, indicating of percentage of regular queries that should have resulted in a failure over the last recent queries. Only the results of the last ``lazyHealthCheckSampleSize`` queries will be considered, as the results are kept in an in-memory circular buffer. The results of at least ``lazyHealthCheckMinSampleCount`` queries should be present for the threshold to be considered meaningful, to avoid an issue with a too small sample.
By default both queries that resulted in a timeout and those that received a ``ServFail`` answer are considered failures, but it is possible to set ``lazyHealthCheckMode`` to ``TimeoutOnly`` so that only timeouts are considered failures.
:property integer tlsHandshakeFailuresUnknownKeyExchangeType: Amount of TLS connections where the client has tried to negotiate an unknown TLS key-exchange mechanism
:property integer tlsHandshakeFailuresUnknownProtocol: Amount of TLS connections where the client has tried to negotiate an unknown TLS version
:property integer tlsHandshakeFailuresUnsupportedEC: Amount of TLS connections where the client has tried to negotiate an unsupported elliptic curve
- :property integer tlsHandshakeFailuresUnsupportedProtocol: Amount of TLS connections where the client has tried to negotiate a unsupported TLS version
+ :property integer tlsHandshakeFailuresUnsupportedProtocol: Amount of TLS connections where the client has tried to negotiate an unsupported TLS version
:property integer tlsInactiveTicketKey: Amount of TLS sessions resumed from an inactive key
:property integer tlsNewSessions: Amount of new TLS sessions negotiated
:property integer tlsResumptions: Amount of TLS sessions resumed
\r
.. function:: errlog(line)\r
\r
- Writes a error line.\r
+ Writes an error line.\r
\r
:param str line: The line to write.\r
\r
BOOST_CHECK(!pool.isTCPOnly());
BOOST_CHECK(!pool.isConsistent());
/* the pool was in a consistent state without ECS,
- and now is in a inconsistent state so it not automatically
+ and now is in an inconsistent state so it not automatically
updated */
BOOST_CHECK(!pool.getECS());
}
- ReadLock, WriteLock, TryReadLock and TryWriteLock are there as RAII
objects allowing to take a lock and be sure that it will always be unlocked
- when we exit the block, even with a unforeseen exception.
+ when we exit the block, even with an unforeseen exception.
They are light wrappers around std::unique_lock and std::shared_lock
since C++17.
:pullreq: 11359
:tickets: 11257
- Initialize isNew before calling a exception throwing function.
+ Initialize isNew before calling an exception throwing function.
.. change::
:tags: Improvements
An issue in the processing of queries for misconfigured domains has been found in PowerDNS Recursor
4.8.0, allowing a remote attacker to crash the recursor by sending a DNS query for one of these
-domains. The issue happens because the recursor enters a unbounded loop, exceeding its stack
+domains. The issue happens because the recursor enters an unbounded loop, exceeding its stack
memory. Because of the specific way in which this issue happens, we do not believe this issue to be
exploitable for code execution.
void NegCache::updateStaleEntry(time_t now, negcache_t::iterator& entry, QType qtype)
{
- // We need to take care a infrequently access stale item cannot be extended past
+ // We need to take care an infrequently access stale item cannot be extended past
// s_maxServedStaleExtension * s_serveStaleExtensionPeriod
// We we look how old the entry is, and increase d_servedStale accordingly, taking care not to overflow
const time_t howlong = std::max(static_cast<time_t>(1), now - entry->d_ttd);
~EventScope()
{
// If the dt is called after an explicit close(), value does not matter.
- // Otherwise, it signals a implicit close, e.g. an exception was thrown
+ // Otherwise, it signals an implicit close, e.g. an exception was thrown
close(-1);
}
EventScope(const EventScope&) = delete;
...
```
-Lastly, there is code to support converting a old-style settings to a new-style struct found in `pdns::settings::rec::oldKVToBridgeStruct()`.
+Lastly, there is code to support converting an old-style settings to a new-style struct found in `pdns::settings::rec::oldKVToBridgeStruct()`.
This code is used to convert old style settings files to YAML (used by `rec_control show-yaml`) and to generate a yaml file with all the defaults values (used by `pdns_recursor --config=default`).
The functions implementing that are `pdns::settings::rec::oldStyleSettingsFileToYaml` and `std::string pdns::settings::rec::defaultsToYaml()`, found in `cxxsupport.cc`.
Starting with version 5.1.0, in the absence of a ``recursor.yml`` file, an existing ``recursor.conf`` will be processed as YAML,
if that fails, it will be processed as old-style configuration.
- Packages will stop installing a old-style ``recursor.conf`` file and start installing a default ``recursor.conf`` file containing YAML syntax.
+ Packages will stop installing an old-style ``recursor.conf`` file and start installing a default ``recursor.conf`` file containing YAML syntax.
With the release of 5.2.0, the default will be to expect a YAML configuration file and reading of old-style ``recursor.conf`` files will have to be enabled specifically by providing a command line option ``--enable-old-settings``.
fn allow_from_to_yaml_string_incoming(key: &String, filekey: &String, vec: &Vec<String>) -> Result<String>;
fn allow_for_to_yaml_string(vec: &Vec<String>) -> Result<String>;
- // Merge a string representing YAML settings into a existing setttings struct
+ // Merge a string representing YAML settings into an existing setttings struct
fn merge(lhs: &mut Recursorsettings, rhs: &str) -> Result<()>;
// Validate the sections inside the main settings struct, sections themselves will validate their fields
'default' : '',
'help' : 'A Proxy Protocol header should not be used for these listen addresses.',
'doc' : '''
-If set, clients sending from an address in :ref:`setting-proxy-protocol-from` to a address:port listed here are excluded from using the Proxy Protocol.
+If set, clients sending from an address in :ref:`setting-proxy-protocol-from` to an address:port listed here are excluded from using the Proxy Protocol.
If no port is specified, port 53 is assumed.
This is typically used to provide an easy to use address and port to send debug queries to.
''',
/* We are never called for a GETNEXT if it's registered as a
"instance", as it's "magically" handled for us. */
-/* a instance handler also only hands us one request at a time, so
+/* an instance handler also only hands us one request at a time, so
we don't need to loop over a list of requests; we'll only get one. */
static int handleCounter64Stats(netsnmp_mib_handler* /* handler */,
return answer;
}
-// do a id.server/CH/TXT query
+// do an id.server/CH/TXT query
std::string serverID()
{
auto buffer = resolve("id.server", QClass::CHAOS, QType::TXT);
void MemRecursorCache::updateStaleEntry(time_t now, MemRecursorCache::OrderedTagIterator_t& entry)
{
- // We need to take care a infrequently access stale item cannot be extended past
+ // We need to take care an infrequently access stale item cannot be extended past
// s_maxServedStaleExtension * s_serveStaleExtensionPeriod
// We look how old the entry is, and increase d_servedStale accordingly, taking care not to overflow
const time_t howlong = std::max(static_cast<time_t>(1), now - entry->d_ttd);
BOOST_CHECK_EQUAL(cache->getEntriesCount(), 3U);
- /* we have set a upper bound to 2 entries, so we are above,
+ /* we have set an upper bound to 2 entries, so we are above,
and one entry is actually expired, so we will prune one entry
to get below the limit */
cache->prune(now.tv_sec + 15);
}
} break;
default: {
- // In any other case, we must check if the TYPE and RDATA match to provide an update (which effectively means a update of TTL)
+ // In any other case, we must check if the TYPE and RDATA match to provide an update (which effectively means an update of TTL)
int updateTTL = 0;
foundRecord = false;
bool lowerCase = false;
def testAuthSendsIncorrectClientCookie(self):
confdir = os.path.join('configs', self._confdir)
- # Case: rec gets a an incorrect client cookie back, we ignore that and go to TCP
+ # Case: rec gets an incorrect client cookie back, we ignore that and go to TCP
self.recControl(confdir, 'clear-cookies', '*')
tcp1 = self.recControl(confdir, 'get tcp-outqueries')
query = dns.message.make_query('wrongcc.cookies.example.', 'A')
query = dns.message.make_query(nameECS, 'TXT', 'IN')
self.sendECSQuery(query, expected2)
- # And a unknown tag and no subnet query does hit the general case
+ # And an unknown tag and no subnet query does hit the general case
self.setRoutingTag('bag')
query = dns.message.make_query(nameECS, 'TXT', 'IN')
self.sendECSQuery(query, expected2)
query = dns.message.make_query(nameECS, 'TXT', 'IN')
self.sendECSQuery(query, expected2)
- # And a unknown tag and no subnet query does hit the general case
+ # And an unknown tag and no subnet query does hit the general case
self.setRoutingTag('bag')
query = dns.message.make_query(nameECS, 'TXT', 'IN')
self.sendECSQuery(query, expected2)
def testIdServerUDP(self):
"""
- Send a id.server CH TXT query over UDP and look for the server id
+ Send an id.server CH TXT query over UDP and look for the server id
"""
query = dns.message.make_query('id.server', 'TXT', 'CH', use_edns=False)
response = self.sendUDPQuery(query)
def testIdServerTCP(self):
"""
- Send a id.server CH TXT query over TCP and look for the server id
+ Send an id.server CH TXT query over TCP and look for the server id
"""
query = dns.message.make_query('id.server', 'TXT', 'CH', use_edns=False)
response = self.sendTCPQuery(query)
def testIdServerUDPEDNS(self):
"""
- Send a id.server CH TXT query over UDP (with EDNS) and look for the server id
+ Send an id.server CH TXT query over UDP (with EDNS) and look for the server id
"""
query = dns.message.make_query('id.server', 'TXT', 'CH', use_edns=True)
response = self.sendUDPQuery(query)
def testIdServerTCPEDNS(self):
"""
- Send a id.server CH TXT query over TCP (with EDNS) and look for the server id
+ Send an id.server CH TXT query over TCP (with EDNS) and look for the server id
"""
query = dns.message.make_query('id.server', 'TXT', 'CH', use_edns=True)
response = self.sendTCPQuery(query)