It is a book about a Spanish guy called Manual. You should read it.
-- Dilbert
The PowerDNS dynamic nameserver
The PowerDNS daemon is a versatile nameserver which supports a large number
of backends. These backends can either be plain zonefiles or be
more dynamic in nature.
Prime examples of backends include relational databases, but also
loadbalancing and failover algorithms.
The company is called PowerDNS BV, the nameserver daemon is called PDNS.
Function & design of PDNS
PDNS is an authoritative only nameserver. It will answer questions about domains it knows about,
but will not go out on the net to resolve queries about other domains. However, it can use a
recursing backend to provide that functionality.
When PDNS answers a question, it comes out of the database, and can be trusted as being authoritative. There is
no way to pollute the cache or to confuse the daemon.
PDNS has been designed to serve both the needs of small installations by being easy to setup, as well as
for serving very large query volumes on large numbers of domains.
Another prime goal is security. By the use of language features, the PDNS source code
is very small (in the order of 10.000 lines) which makes auditing easy. In the same way, library features have been used
to mitigate the risks of buffer overflows.
Finally, PDNS is able to give a lot of statistics on its operation which is both helpful in
determining the scalability of an installation as well as for spotting problems.
About this document
If you are reading this document from disk, you may want to check http://doc.powerdns.com
for updates. The PDF version is available on http://doc.powerdns.com/pdf, a text file is
on http://doc.powerdns.com/txt/.
Release notes
Before proceeding, it is advised to check the release notes for your PDNS version, as specified in the name of the distribution
file.
Version 2.9.4
Yet another grand release. Big news is the addition of a recursing nameserver which has sprung into existence
over the past week. It is in use on several computers already but it is not ready for prime time. Complete integration
with PowerDNS is expected around 2.9.5, for now the recursor is a separate program.
In preliminary tests, the recursor appears to be four times faster than BIND 9 on a naive benchmark starting from a cold cache. BIND 9
managed to get through to some slower nameservers however, which were given up on by PowerDNS. We will continue to tune the recursor.
See for further details.
The BIND Backend has also been tested (see the bind-domain-status item below) rather heavily by several parties. After some
discussion online, one of the BIND authors ventured that the newsgroup comp.protocols.dns.bind may now in fact be an appropriate venue
for discussing PowerDNS. Since this discussion, traffic to the PowerDNS pages has increased sixfold and shows no signs of slowing down.
From this, it is apparent that far more people are interested in PowerDNS than yet know about it. So spread the word!
In other news, we now have a security page at . Furthermore, Maurice Nonnekes contributed an OpenBSD
port! See his page for more details!
New features and improvements:
All SQL queries in the generic backends are now available for configuration. (Martin Klebermass/bert hubert).
See .
A recursing nameserver! See .
An incoming AXFR now only starts a backend zone replacement transaction after the first record arrived successfully, thus making
sure no work is done when a remote nameserver is unable/unwilling to AXFR a zone to us.
Zoneparser error messages were improved slightly (thanks to Stef van Dessel for spotting this shortcoming)
XS4ALL's Erik Bos checked how PowerDNS reacted to a BIND installation with almost 60.000 domains, some of which
with >100.000 records, and he discovered the pdns_control bind-domain-status command
became very slow with larger numbers of domains. Fixed, 60.000 domains are now listed in under one second.
If a remote nameserver disconnects during an incoming AXFR, the update is now rolled back, unless the AXFR was
properly terminated.
The migration chapter mentioned the use of deprecated backends.
A tremendous number of bugs were discovered and fixed:
Zone parser would only accept $include and not $INCLUDE
Zone parser had problems with $lines with comments on the end
Wildcard ANY queries were broken (thanks Colemarcus for spotting this)
A connection failure with the Generic backends would lead to a powerdns reload (cast of many)
Generic backends had some semantic problems with slave support. Symptoms were oft-repeated notifications
and transfers (thanks to Mark Bergsma for helping resolve this).
Solaris version compiles again. Thanks to Mohamed Lrhazi for reporting that it didn't.
Some UltraSPARC alignment fixes. Thanks to Mohamed Lrhazi for being helpful in spotting these.
One problem is still outstanding, Mohamed sent a core dump that tells us where the problem is. Expect the
fix to be in 2.9.5. Volunteers can grep the source for 'UltraSPARC' to find where the problem is.
Our support of IPv6 on FreeBSD had phase of moon dependent bugs, fixed by Peter van Dijk.
Some crashes of and by pdns_control were fixed, thanks to Mark Bergsma for helping resolve these.
Outgoing AXFR in pdns installations with multiple loaded backends was broken (thanks to Stuart Walsh for reporting this).
A failed BIND Backend incoming AXFR would block the zone until it succeeded again.
Generic PostgreSQL backend wouldn't compile with newer libpq++, fixed by Julien Lemoine/SpeedBlue.
Potential bug (not observed) when listening on multiple interfaces fixed.
Some typos in manpages fixed (reported by Marco Davids).
Version 2.9.3a2.9.3a is identical to 2.9.3 except that zone2sql does work
Broad range of huge improvements. We now have an all-static .rpm and .deb for Linux users and a a link to an OpenBSD port.
Major news is that work on the Bind backend has progressed to the point that we've just retired our last Bind server and
replaced it with PowerDNS in Bind mode! This server is operating a number of master and slave setups so it should stress the Bind backend
somewhat.
This version is rapidly approaching the point where it is a better-Bind-than-Bind and nearly a drop-in replacement for authoritative
setups. PowerDNS is now equipped with a powerful
master/slave apparatus that offers a lot of insight and control to the user, even when operating from Bind zonefiles and a
Bind configuration. Observe.
After the SOA of ds9a.nl was raised:
pdns[17495]: All slave domains are fresh
pdns[17495]: 1 domain for which we are master needs notifications
pdns[17495]: Queued notification of domain 'ds9a.nl' to 195.193.163.3
pdns[17495]: Queued notification of domain 'ds9a.nl' to 213.156.2.1
pdns[17520]: AXFR of domain 'ds9a.nl' initiated by 195.193.163.3
pdns[17520]: AXFR of domain 'ds9a.nl' to 195.193.163.3 finished
pdns[17521]: AXFR of domain 'ds9a.nl' initiated by 213.156.2.1
pdns[17521]: AXFR of domain 'ds9a.nl' to 213.156.2.1 finished
pdns[17495]: Removed from notification list: 'ds9a.nl' to 195.193.163.3 (was acknowledged)
pdns[17495]: Removed from notification list: 'ds9a.nl' to 213.156.2.1 (was acknowledged)
pdns[17495]: No master domains need notifications
If however our slaves would ignore us, as some are prone to do, we can send some additional notifications:
$ sudo pdns_control notify ds9a.nl
Added to queue
pdns[17492]: Notification request for domain 'ds9a.nl' received
pdns[17492]: Queued notification of domain 'ds9a.nl' to 195.193.163.3
pdns[17492]: Queued notification of domain 'ds9a.nl' to 213.156.2.1
pdns[17495]: Removed from notification list: 'ds9a.nl' to 195.193.163.3 (was acknowledged)
pdns[17495]: Removed from notification list: 'ds9a.nl' to 213.156.2.1 (was acknowledged)
Conversely, if PowerDNS needs to be reminded to retrieve a zone from a master, a command is provided:
$ sudo pdns_control retrieve forfun.net
Added retrieval request for 'forfun.net' from master 212.187.98.67
pdns[17495]: AXFR started for 'forfun.net', transaction started
pdns[17495]: Zone 'forfun.net' (/var/cache/bind/forfun.net) reloaded
pdns[17495]: AXFR done for 'forfun.net', zone committed
Also, you can force PowerDNS to reload a zone from disk immediately with pdns_control bind-reload-now.
All this happens 'live', per your instructions. Without instructions, the right things also happen, but the operator is in charge.
For more about all this coolness, see and .
Again some changes in compilation instructions. The hybrid pgmysql backend has been split up into 'gmysql' and 'gpgsql', sharing
a common base within the PowerDNS server itself. This means that you can no longer compile
--with-modules="pgmysql" --enable-mysql --enable-pgsql but that you should now use:
--with-modules="gmysql gpgsql". The old launch-names remain available.
If you launch the Generic PgSQL backend as gpgsql2, all parameters will have gpsql2 as a prefix, for example
pgsql2-dbname. If launched as gpsql, the regular names are in effect.
The pdns_control protocol was changed which means that older pdns_controls cannot talk to 2.9.3. The other way around is
broken too. This may lead to problems with automatic upgrade scripts, so pay attention if your daemon is truly restarted.
Also make sure no old pdns_control command is around to confuse things.
Improvements:
Bind backend can now deal with missing files and try to find them later.
Bind backend is now explicitly master capable and triggers the sending of notifications.
General robustness improvements in Bind backend - many errors are now non-fatal.
Accessability, Serviceability. New pdns_server commands like bind-list-rejects
(lists zones that could not be loaded, and the reason why), bind-reload-now (reload a zone from disk NOW),
rediscover (reread named.conf NOW). More is coming up.
Added support for retrieving RP (Responsible Person) records from remote masters. Serving them was already possible.
Added support for LOC records, which encode the geographical location of a host, both serving and retrieving (thanks to Marco Davids
using them on our last Bind server, forcing us to implement this silly record).
Configuration file parser now strips leading spaces too, allowing "chroot= /tmp" to work, as well as "chroot=/tmp"
(Thanks to Hub Dohmen for reporting this for months on end).
Added bind-domain-status command that shows the status of all domains (when/if they were parsed, any errors
encountered while parsing them).
Added bind-reload-now command that tries to reload a zone from disk NOW, and reports back errors to the operator
immediatly.
Added retrieve command that queues a request to retrieve a zone from its master.
Zones retrieved from masters are now stored way smaller on disk because the domain is stripped from records, which is derived
from the configuration file. Retrieved zones are now prefixed with some information on where they came from.
Changes:
gpgsql and gmysql backends split out of the hybrid pgmysqlbackend. This again changed compilation instructions!
pdns_control now uses the rarely seen SOCK_STREAM Unix Domain socket variety so it can transport
large amounts of text, which is needed for the bind-domain-status command, for which see
. This breaks compatability with older pdns_control and pdns_server binaries!
Bind backend now ignores 'hint' and 'forward' and other unsupported zone types.
AXFRs are now logged more heavily by default. An AXFR is a heavy operation anyhow, some more logging does not further
increase the load materially. Does help in clearing up what slaves are doing.
A lot of master/slave chatter has been silenced, making output more relevant. No more repetitive 'No master domains need notifications' etc, only changes are reported now.
Bugfixes:
Windows version did not compile without minor changes.
Confusing error reporting on Windows 98 (which does not support PowerDNS) fixed
Potential crashes with shortened packets addressed. An upgrade is advised!
notify (which was already there, just badly documented) no longer prints out debugging garbage.
pgmysql backend had problems launching when not compiled in but available as a module. Workaround for 2.9.2 is 'load-modules=pgmysql',
but even then gpgsql would not work! gmysql would then, however. These modules are now split out, removing such issues.
Version 2.9.2
Bugfixes galore. Solaris porting created some issues on all platforms. Great news is that PowerDNS is now in Debian 'sid' (unstable). The 2.9.1
packages in there currently aren't very good but the 2.9.2 ones will be. Many thanks to Wichert Akkerman, our 'downstream' for making this possible.
The Generic MySQL backend, part of the Generic MySQL & PostgreSQL backend, is now the DEFAULT! The previous default, the
'mysql' backend (note the lack of 'g') is now DEPRECATED. This was the source of much confusion. The 'mysql' backend
does not support MASTER or SLAVE operation. The Generic backends do.
To get back the mysql backend, add --with-modules="mysql" or --with-dynmodules="mysql" if you prefer to load your modules at runtime.
Bugs fixed:
Silly debugging output removed from the webserver (found by Paul Wouters)
SEVERE: due to Solaris portability fixes, qtypes<127 were broken.
These include NAPTR, ANY and AXFR. The upshot is that powerdns
wasn't performing outgoing AXFRs nor ANY queries. These were the
'question for type -1' warnings in the log
incoming AXFR could theoretically miss some trailing records (not observed, but could happen)
incoming AXFR did not support TXT records (spotted by Paul Wouters)
with some remotes, an incoming AXFR would not terminate until a
timeout occured (observed by Paul Wouters)
Documentation bug, pgmysql != mypgsql
Documentation:
Documented the 'random backend', see .
Wichert Akkerman contributed three manpages.
Building PowerDNS on Unix is now documented somewhat more, see .
Features:
pdns init.d script is now +x by default
OpenBSD is on its way of becoming a supported platform! As of 2.9.2, PowerDNS compiles on OpenBSD but swiftly crashes.
Help is welcome.
ODBC backend (for Windows only) was missing from the distribution, now added.
xdb backend added - see . Designed for use by root-server operators.
Dynamic modules are back which is good news for distributors who want to make a pdns packages that does not
depend one every database under the sun.
Version 2.9.1
Thanks to the great enthusiasm from around the world, powerdns is now available for Solaris and FreeBSD users again!
Furthermore, the Windows build is back. We are very grateful for the help of:
Michel StolWichert AkkermanEdvard TuinderKoos van den HoutNiels BakkerErik BosAlex Blekersteven stillawayRoel van der MadeSteven Van Steen
We are happy to have been able to work with the open source community to improve PowerDNS!
Changes:
The monitor command set no longer allows the changing of non-existant variables.
IBM Universal Database DB2 backend now included in source distribution (untested!)
Oracle backend now included in source distribution (sligthly tested!)
configure script now searches for postgresql and mysql includes
Bind parser now no longer dies on records with a ' in them (Erik Bos)
The pipebackend was accidentally left out of 2.9
FreeBSD fixes (with help from Erik Bos, Alex Bleeker, Niels Bakker)
Heap of Solaris work (with help from Edvard Tuinder, Stefan Van Steen, Koos van den Hout, Roel van der Made and
especially Mark Bakker).
Now compiles in 2.7 and 2.8, haven't tried 2.9. May be a bit dysfunctional on 2.7 though - it won't do IPv6 and it won't serve AAAA. Patches
welcome!
Windows 32 build is back! Michel Stol updated his earlier work to the current version.
S/Linux (Linux on Sparc) build works now (with help from steven stillaway).
Silly debugging message ('sd.ttl from cache') removed
.debs are back, hopefully in 'sid' soon! (Wichert Akkerman)
Removal of bzero and other less portable constructs. Discovered that recent Linux glibc's need -D_GNU_SOURCE (Wichert Akkerman). Version 2.9
Open source release. Do not deploy unless you know what you are
doing. Stability is expected to return with 2.9.1, as are the binary builds.
License changed to the GNU General Public License version 2.
Cleanups by Erik Bos @ xs4all.
Build improvements by Wichert Akkerman
Lots of work on the build system, entirely revamped. By PowerDNS.
Version 2.8
From this release onwards, we'll concentrate on stabilising for the 3.0 release. So if you have any must-have features,
let us know soonest. The 2.8 release fixes a bunch of small stability issues and add two new features. In the spirit of the move to
stability, this release has already been running 24 hours on our servers before release.
pipe backend gains the ability to restricts its invocation to a limited number of requests. This allows a very busy nameserver
to still serve packets from a slow perl backend.
pipe backend now honors query-logging, which also documents which queries were blocked by the regex.
pipe backend now has its own backend chapter.
An incoming AXFR timeout at the wrong moment had the ability to crash the binary, forcing a reload. Thanks to our bug spotting
champions Mike Benoit and Simon Kirby of NetNation for reporting this.
Version 2.7 and 2.7.1
This version fixes some very long standing issues and adds a few new features. If you are still running 2.6, upgrade yesterday. If you
were running 2.6.1, an upgrade is still strongly advised.
Features:
The controlsocket is now readable and writable by the 'setgid' user. This allows for non-root
access to PDNS which is nice for mrtg or cricket graphs.
MySQL backend (the non-generic one) gains the ability to read from a different table using the
mysql-table setting.
pipe backend now has a configurable timeout using the pipe-timeout setting. Thanks fo Steve Bromwich
for pointing out the need for this.
Experimental backtraces. If PowerDNS crashes, it will log a lot of numbers and sometimes more to the syslog.
If you see these, please report them to us. Only available under Linux.
Bugs:
2.7 briefly broke the mysql backend, so don't use it if you use that. 2.7.1 fixes this.
SOA records could sometimes have the wrong TTL. Thanks to Jonas Daugaard for reporting this.
An ANY query might lead to duplicate SOA records being returned under exceptional circumstances.
Thanks to Jonas Daugaard for reporting this.
Underlying the above bug, packet compression could sometimes suddenly be turned off, leading to
overly large responses and non-removal of duplicate records.
The allow-axfr-ips setting did not accept IP ranges (1.2.3.0/24) which the
documentation claimed it did (thanks to Florus Both of Ascio technologies for being sufficiently persistent in reporting this).
Killed backends were not being respawned, leading to suboptimal behaviour on intermittent database errors. Thanks to Steve Bromwich for
reporting this.
Corrupt packets during an incoming AXFR when acting as a slave would cause a PowerDNS reload instead of just failing that AXFR.
Thanks to Mike Benoit and Simon Kirby of NetNation for reporting this.
Label compression in incoming AXFR had problems with large offsets, causing the above mentioned errors. Thanks to Mike Benoit
and Simon Kirby of NetNation for reporting this.
Version 2.6.1
Quick fix release for a big cache problem.
Version 2.6
Performance release. A lot of work has been done to raise PDNS performance to staggering levels in order to take part
in benchmarketing efforts. Together with our as yet unnamed partner, PDNS has been benchmarked at 60.000 mostly cached queries/second
on off the shelf PC hardware. Uncached performance was 17.000 uncached DNS queries/second on the .ORG domain.
Performance has been increased by both making PDNS itself quicker but also by lowering the number of backend queries typically needed. Operators
will typically see PDNS taking less CPU and the backend seeing less load.
Furthermore, some real bugs were fixed. A couple of undocumented performance switches may appear in --help output but you are advised to stay
away from these.
Developers: this version needs the pdns-2.5.1 development kit, available on
http://downloads.powerdns.com/releases/dev. See also .
Performance:
A big error in latency calculations - cached packets were weighed 50 times less, leading to inflated latency reporting. Latency calculations
are now correct and way lower - often in the microseconds range.
It is now possible to run with 0 second cache TTLs. This used to cause very frequent cache cleanups, leading
to performance degradation.
Many tiny performance improvements, removing duplicate cache key calculations, etc. The cache itself has also been reworked
to be more efficient.
First 'CNAME' backend query replaced by an 'ANY' query, which most of the time returns the actual record,
preventing the need for a separate CNAME lookup, halving query load.
Much of the same for same-level-NS records on queries needing delegation.
Bugs fixed:
Incidentally, the cache count would show 'unknown' packets, which was harmless but confusing. Thanks to Mike and Simon of
NetNation for reporting this.
SOA hostmaster with a . in the local-part would be cached wrongly, leading to a stray backslash
in case of multiple successively SOA queries. Thanks to Ascio Techologies for spotting this bug.
zone2sql did not parse Verisign zonefiles correctly as these contained a $TTL statement in mid-record.
Sometimes packets would not be accounted, leading to 'udp-queries' and 'udp-answers' divergence.
Features:
'cricket' command added to init.d scripts that provides unadorned output for parsing by 'Cricket'.
Version 2.5.1Brown paper bag release fixing
a huge memory leak in the new Query Cache.
Developers: this version needs the new pdns-2.5.1 development kit, available on
http://downloads.powerdns.com/releases/dev. See also .
And some small changes:
Added support for RFC2038 compliant negative-answer caching. This allows remotes to cache the fact that
a domain does not exist and will not exist for a while. Thanks to Chris Thompson for pointing out how tiny our minds are. This feature may cause a noticeable reduction
in query load.
Small speedup to non-packet-cached queries, incidentally fixing the huge memory leak.
pdns_control ccounts command outputs statistics on what is in the cache, which is
useful to help optimize your caching strategy.
Version 2.5
An important release which has seen quite a lot of trial and error testing. As a result, PDNS can now run with a huge cache
and concurrent invalidations. This is useful when running of a slower database or under high traffic load with a fast database.
Furthermore, the gpgsql2 backend has been validated for use and will soon supplant the gpgsql backend entirely. This also bodes
well for the gmysql backend which is the same code.
Also, a large amount of issues biting large scale slave operators were addressed. Most of these issues would only show up
after prolonged uptime.
New features:
Query cache. The old Packet Cache only cached entire questions and their answers. This is very CPU efficient but
does not lead to maximum hitrate. Two packets both needing to resolve smtp.you.com internally would not benefit
from any caching. Furthermore, many different DNS queries lead to the same backend queries, like 'SOA for .COM?'.
PDNS now also caches backend queries, but only those having no answer (the majority) and those having one answer
(almost the rest).
In tests, these additional caches appear to halve the database backend load numerically and perhaps even more in terms
of CPU load. Often, queries with no answer are more expensive than those having one.
The default ttls for the query-cache and negquery-cache are set to safe values (20 and 60 seconds
respectively), you should be seeing an improvement in behaviour without sacrificing a lot in terms of quick updates.
The webserver also displays the efficiency of the new Query Cache.
The old Packet Cache is still there (and useful) but see for more details.
There is now the ability to shut off some logging at a very early stage. High performance sites doing thousands of
queries/second may in fact spend most of their CPU time on attempting to write out logging, even though it is ignored
by syslog. The new flag log-dns-details, on by default, allows the operator to kill most
informative-only logging before it takes any cpu.
Flags which can be switched 'on' and 'off' can now also be set to 'off' instead of only to 'no' to turn them off.
Enhancements:
Packet Cache is now case insensitive, leading to a higher hitrate because identical queries only differing in case
now both match. Care is taken to restore the proper case in the answer sent out.
Packet Cache stores packets more efficiently now, savings are estimated at 50%.
The Packet Cache is now asynchronous which means that PDNS continues to answer questions while the cache
is busy being purged or queried. Incidentally this will mean a cache miss where previously the question would
wait until the cache became available again.
The upshot of this is that operators can call pdns_control purge as often as desired without
fearing performance loss. Especially the full, non-specific, purge was speeded up tremendously.
This optimization is of little merit for small sites but is very important when running with a large packetcache, such
as when using recursion under high load.
AXFR log messages now all contain the word 'AXFR' to ease grepping.
Linux static version now compiled with gcc 3.2 which is known to output better and faster code than the previously
used 3.0.4.
Bugs fixed:
Packetcache would sometimes send packets back with slightly modified flags if these differed from the flags
of the cached copy.
Resolver code did bad things with filedescriptors leading to fd exhaustion after prolonged uptimes and many slave
SOA currency checks.
Resolver code failed to properly log some errors, leading to operator uncertainty regarding to AXFR problems with
remote masters.
After prolonged uptime, slave code would try to use privileged ports for originating queries, leading to bad
replication efficiency.
Masters sending back answers in differing case from questions would lead to bogus
'Master tried to sneak in out-of-zone data' errors and failing AXFRs.
Version 2.4
Developers: this version is compatible with the pdns-2.1 development kit, available on
http://downloads.powerdns.com/releases/dev. See also .
This version fixes some stability issues with malformed or malcrafted packets. An upgrade is advised. Furthermore, there are interesting new
features.
New features:
Recursive queries are now also cached, but in a separate namespace so non-recursive queries don't get recursed answers and
vice versa. This should mean way lower database load for sites running with the current default lazy-recursion. Up to now,
each and every recursive query would lead to a large amount of SQL queries.
To prevent the packetcache from becoming huge, a separate recursive-cache-ttl can be specified.
The ability to change parameters at runtime was added. Currently, only the new query-logging flag
can be changed.
Added query-logging flag which hints a backend that it should output a textual representation of queries
it receives. Currently only gmysql and gpgsql2 honor this flag.
Gmysql backend can now also talk to PgSQL, leading to less code. Currently, the old postgresql driver ('gpgsql') is still the default,
the new driver is available as 'gpgsql2' and has the benefit that it does query logging. In the future, gpgsql2 will become the default
gpgsql driver.
DNS recursing proxy is now more verbose in logging odd events which may be caused by buggy recursing backends.
Webserver now displays peak queries/second 1 minute average.
Bugs fixed:
Failure to connect to database in master/slave communicator thread could lead to an unclean reload, fixed.
Documentation: added details for strict-rfc-axfrs. This feature can be used if very old clients need to be able
to do zone transfers with PDNS. Very slow.
Version 2.3
Developers: this version is compatible with the pdns-2.1 development kit, available on
http://downloads.powerdns.com/releases/dev. See also .
This release adds the Generic MySQL backend which allows full master/slave semantics with MySQL and InnoDB tables (or other tables that support
transactions). See .
Other new features:
Improved error messages in master/slave communicator will help down track problems.
slave-cycle-interval setting added. Very large sites with thousands of slave domains may need to raise this value
above the default of 60. Every cycle, domains in undeterminate state are checked for their condition. Depending on the health of the masters,
this may entail many SOA queries or attempted AXFRs.
Bugs fixed:
'pdns_control purge domain' and 'pdns_control purge domain$' were broken in version 2.2 and
did not in fact purge the cache. There is a slight risk that domain-specific purge commands could force a reload in previous version.
Thanks to Mike Benoit of NetNation for discovering this.
Master/slave communicator thread got confused in case of delayed answers from slow masters. While not causing harm, this caused inefficient
behaviour when testing large amounts of slave domains because additional 'cycles' had to pass before all domains would have their status
ascertained.
Backends implementing special SOA semantics (currently only the undocumented 'pdns express backend', or homegrown backends) would
under some circumstances not answer the SOA record in case of an ANY query. This should put an end to the last DENIC problems. Thanks to
DENIC for helping us find the problem.
Version 2.2
Developers: this version is compatible with the pdns-2.1 development kit, available on
http://downloads.powerdns.com/releases/dev. See also .
Again a big release. PowerDNS is seeing some larger deployments in more demanding environments and these are helping shake out remaining issues,
especially with recursing backends.
The big news is that wildcard CNAMEs are now supported, an oft requested feature and nearly the only part in which PDNS differed from BIND in
authoritative capabilities.
If you were seeing signal 6 errors in PDNS causing reloads and intermittent service disruptions, please upgrade to this version.
For operators of PowerDNS Express trying to host .DE domains, the very special soa-serial-offset feature has been added
to placate the new DENIC requirement that the SOA serial be at least six digits. PowerDNS Express uses the SOA serial as an actual serial and
not to insert dates and hence often has single digit soa serial numbers, causing big problems with .DE redelegations.
Bugs fixed:
Malformed or shortened TCP recursion queries would cause a signal 6 and a reload. Same for EOF from the TCP recursing backend.
Thanks to Simon Kirby and Mike Benoit of NetNation for helping debug this.
Timeouts on the TCP recursing backend were far too long, leading to possible exhaustion of TCP resolving threads.
pdns_control purge domain accidentally cleaned all packets with that name as a prefix. Thanks to Simon Kirby
for spotting this.
Improved exception error logging - in some circumstances PDNS would not properly log the cause of an exception, which hampered problem
resolution.
New features:
Wildcard CNAMEs now work as expected!
pdns_control purge can now also purge based on suffix, allowing operators to
purge an entire domain from the packet cache instead of only specific records. See also
Thanks to Mike Benoit for this suggestion.
soa-serial-offset for installations with small SOA serial numbers wishing to register .DE domains
with DENIC which demands six-figure SOA serial numbers. See also .
Version 2.1
This is a somewhat bigger release due to pressing demands from customers. An upgrade is advised for installations using Recursion.
If you are using recursion, it is vital that you are aware of changes in semantics. Basically, local data will now override data in your
recursing backend under most circumstances. Old behaviour can be restored by turning lazy-recursion off.
Developers: this version has a new pdns-2.1 development kit, available on
http://downloads.powerdns.com/releases/dev. See also .
Most users will run a static version of PDNS which has no dependencies on external libraries. However, some may need to run the dynamic version.
This warning applies to these users.
To run the dynamic version of PDNS, which is needed for backend drivers which are only available in source form, gcc 3.0 is required.
RedHat 7.2 comes with gcc 3.0 as an optional component, RedHat 7.3 does not. However, the RedHat 7.2 Update gcc rpms install just fine
on RedHat 7.3. For Debian, we suggest running 'woody' and installing the g++-3.0 package. We expect to release a FreeBSD dynamic version
shortly.
Bugs fixed:
RPM releases sometimes overwrote previous configuration files. Thanks to Jorn Ekkelenkamp of Hubris/ISP Services for reporting this.
TCP recursion sent out overly large responses due to a byteorder mistake, confusing some clients. Thanks to the capable engineers
of NetNation for bringing this to our attention.
TCP recursion in combination with a recursing backend on a non-standard port did not work, leading to a
non-functioning TCP listener. Thanks to the capable engineers of NetNation for bringing this to our attention.
Unexpected behaviour:
Wildcard URL records where not implemented because they are a performance penalty. To turn these on, enable
wildcard-url in the configuration.
Unlike other nameservers, local data did not override the internet for recursing queries. This has mostly been brought into conformance
with user expectations. If a recursive question can be answered entirely from local data, it is. To restore old behaviour, disable
lazy-recursion. Also see .
Features:
Oracle support has been tuned, leading to the first public release of the Oracle backend. Zone2sql now outputs better SQL
and the backend is now fully documented. Furthermore, the queries are compatible with the PowerDNS XML-RPC product, allowing
PowerDNS express to run off Oracle. See .
Zone2sql now accepts --transactions to wrap zones in a transaction for PostgreSQL and Oracle output. This is a major speedup and also
makes for better isolation of inserts. See .
pdns_control now has the ability to purge the PowerDNS cache or parts of it. This enables operators to
raise the TTL of the Packet Cache to huge values and only to invalidate the cache when changes are made. See also and
.
Version 2.0.1
Maintenance release, fixing three small issues.
Developers: this version is compatible with 1.99.11 backends.
PowerDNS ignored the logging-facility setting unless it was specified on the commandline.
Thanks to Karl Obermayer from WebMachine Technologies for noticing this.
Zone2sql neglected to preserve 'slaveness' of domains when converting to the slave capable PostgreSQL backend. Thanks
to Mike Benoit of NetNation for reporting this. Zone2sql now has a --slave option.
SOA Hostmaster addresses with dots in them before the @-sign were mis-encoded on the wire.
Version 2.0
Two bugfixes, one stability/security related. No new features.
Developers: this version is compatible with 1.99.11 backends.
Bugfixes:
zone2sql refused to work under some circumstances, taking 100% cpu and not functioning. Thanks to Andrew Clark and Mike Benoit
for reporting this.
Fixed a stability issue where malformed packets could force PDNS to reload. Present in all earlier 2.0 versions.
Version 2.0 Release Candidate 2
Mostly bugfixes, no really new features.
Developers: this version is compatible with 1.99.11 backends.
Bugs fixed:
chroot() works again - 2.0rc1 silently refused to chroot. Thanks to Hub Dohmen for noticing this.
setuid() and setgid() security features were silently not being performed in 2.0rc1. Thanks to Hub Dohmen for noticing this.
MX preferences over 255 now work as intended. Thanks to Jeff Crowe for noticing this.
IPv6 clients can now also benefit from the recursing backend feature. Thanks to Andy Furnell for proving beyond any doubt that this
did not work.
Extremely bogus code removed from DNS notification reception code - please test! Thanks to Jakub Jermar for working with us
in figuring out just how broken this was.
AXFR code improved to handle more of the myriad different zonetransfer dialects available. Specifically, interoperability
with Bind 4 was improved, as well as Bind 8 in 'strict rfc conformance' mode. Thanks again for Jakub Jermar for running many tests for us.
If your transfers failed with 'Unknown type 14!!' or words to that effect, this was it.
Features:
Win32 version now has a zone2sql tool.
Win32 version now has support for specifying how urgent messages should be before they go to the NT event log.
Remaining issues:
One persistent report of the default 'chroot=./' configuration not working.
One report of disable-axfr and allow-axfr-ips not working as intended.
Support for relative paths in zones and in Bind configuration is not bug-for-bug compatible with bind yet.
Version 2.0 Release Candidate 1
The MacOS X release! A very experimental OS X 10.2 build has been added. Furthermore, the Windows version is now in line with Unix with
respect to capabilities. The ODBC backend now has the code to function as both a master and a slave.
Developers: this version is compatible with 1.99.11 backends.
Implemented native packet response parsing code, allowing Windows to perform AXFR and NS and SOA queries.
This is the first version for which we have added support for Darwin 6.0, which is part of the forthcoming Mac OS X 10.2.
Please note that although this version is marked RC1, that we have not done extensive testing yet. Consider this a technology
preview.
The Darwin version has been developed on Mac OS X 10.2 (6C35). Other versions may or may not work.
Currently only the random, bind, mysql and pdns backends are included.
The menu based installer script does not work, you will have to edit pathconfig by hand as outlined in chapter 2.
On Mac OS X Client, PDNS will fail to start because a system service is already bound to port 53.
This version is distributed as a compressed tar file. You should follow the generic UNIX installation instructions.
Bugs fixed:
Zone2sql PostgreSQL mode neglected to lowercase $ORIGIN. Thanks to Maikel Verheijen of Ladot for spotting this.
Zone2sql PostgreSQL mode neglected to remove a trailing dot from $ORIGIN if present.
Thanks to Thanks to Maikel Verheijen of Ladot for spotting this.
Zonefile parser was not compatible with bind when $INCLUDING non-absolute filenames. Thanks to Jeff Miller for working out
how this should work.
Bind configuration parser was not compatible with bind when including non-absolute filenames. Thanks to Jeff Miller for working out
how this should work.
Documentation incorrectly listed the Bind backend as 'slave capable'. This is not yet true, now labeled 'experimental'.
Windows changes. We are indebted to Dimitry Andric who educated us in the ways of distributing Windows software.
pdns.conf is now read if available.
Console version responds to ^c now.
Default pdns.conf added to distribution
Uninstaller missed several files, leaving remnants behind
DLLs are now installed locally, with the pdns executable.
pdns_control is now also available on Windows
ODBC backend can now act as master and slave. Experimental.
The example zone missed indexes and had other faults.
A runtime DLL that is present on most windows systems (but not all!) was missing.
Version 1.99.12 Prerelease
The Windows release! See . Beware, windows support is still very fresh and untested. Feedback is very welcome.
Developers: this version is compatible with 1.99.11 backends.
Windows 2000 codebase merge completed. This resulted in quite some changes on the Unix end of things, so this may impact reliability
ODBC backend added for Windows. See .
IBM DB2 Universal Database backend available for Linux. See .
Zone2sql now understands $INCLUDE. Thanks to Amaze Internet for nagging about this
The SOA Mininum TTL now has a configurable default (soa-minimum-ttl)value to placate the DENIC requirements.
Added a limit on the simultaneous numbers of TCP connections to accept (max-tcp-connections). Defaults to 10.
Bugs fixed:
When operating in virtual hosting mode (See ), the additional init.d scripts would not function correctly
and interface with other pdns instances.
PDNS neglected to conserve case on answers. So a query for WwW.PoWeRdNs.CoM would get an answer listing the address of www.powerdns.com.
While this did not confuse resolvers, it is better to conserve case. This has semantical concequences for all backends, which the documentation
now spells out.
PostgreSQL backend was case sensitive and returned only answers in case an exact match was found. The Generic PostgreSQL backend is now
officially all lower case and zone2sql in PostgreSQL mode enforces this.
Documentation has been been updated to reflect the case change. Thanks to Maikel Verheijen of Ladot for
spotting this!
Documentation bug - postgresql create/index statements created a duplicate index. If you've previously copy pasted the commands and
not noticed the error, execute CREATE INDEX rec_name_index ON records(name) to remedy. Thanks to Jeff Miller for reporting
this. This also lead to depressingly slow 'ANY' lookups for those of you doing benchmarks.
Features:
pdns_control (see ) now opens the local end of its socket in /tmp instead of next to the
remote socket (by default /var/run). This eases the way for allowing non-root access to pdns_control. When running chrooted
(see ), the local socket again moves back to /var/run.
pdns_control now has a 'version' command. See .
Version 1.99.11 Prerelease
This release is important because it is the first release which is accompanied by an Open Source Backend Development Kit, allowing external
developers to write backends for PDNS. Furthermore, a few bugs have been fixed:
Lines with only whitespace in zone files confused PDNS (thanks Henk Wevers)
PDNS did not properly parse TTLs with symbolic sufixes in zone files, ie 2H instead of 7200 (thanks Henk Wevers)
Version 1.99.10 Prerelease
IMPORTANT: there has been a tiny license change involving free public webbased dns hosting, check out the changes before deploying!
PDNS is now feature complete, or very nearly so. Besides adding features, a lot of 'fleshing out' work is done now. There is an important
performance bug fix which may have lead to disappointing benchmarks - so if you saw any of that, please try either this version or 1.99.8 which
also does not have the bug.
This version has been very stable for us on multiple hosts, as was 1.99.9.
PostgreSQL users should be aware that while 1.99.10 works with the schema as presented in earlier versions, advanced features
such as master or slave support will not work unless you create the new 'domains' table as well.
Bugs fixed:
Wildcard AAAA queries sometimes received an NXDOMAIN error where they should have gotten an empty NO ERROR. Thanks to Jeroen Massar
for spotting this on the .TK TLD!
Do not disable the packetcache for 'recursion desired' packets unless a recursor was configured. Thanks to Greg Schueler for noticing this.
A failing backend would not be reinstated. Thanks to 'Webspider' for discovering this problem with PostgreSQL connections that die after
prolonged inactivity.
Fixed loads of IPv6 transport problems. Thanks to Marco Davids and others for testing. Considered ready for production now.
Zone2sql printed a debugging statement on range $GENERATE commands. Thanks to Rene van Valkenburg for spotting this.
Features:
PDNS can now act as a master, sending out notifications in case of changes and allowing slaves to AXFR. Big rewording of replication support,
domains are now either 'native', 'master' or 'slave'. See for lots of details.
Zone2sql in PostgreSQL mode now populates the 'domains' table for easy master, slave or native replication support.
Ability to disable those annoying Windows DNS Dynamic Update messages from appearing in the log. See log-failed-updates
in .
Ability to run on IPv6 transport only
Logging can now happen under a 'facility' so all PDNS messages appear in their own file. See .
Different OS releases of PDNS now get different install path defaults. Thanks to Mark Lastdrager for nagging about this and to Nero Imhard and
Frederique Rijsdijk for suggesting saner defaults.
Infrastructure for 'also-notify' statements added.
Version 1.99.9 Early Access Prerelease
This is again a feature and an infrastructure release. We are nearly feature complete and will soon start
work on the backends to make sure that they are all master, slave and 'superslave' capable.
Bugs fixed:
PDNS sometimes sent out duplicate replies for packets passed to the recursing backend. Mostly a problem on SMP systems. Thanks to Mike Benoit
for noticing this.
Out-of-bailiwick CNAMES (ie, a CNAME to a domain not in PDNS) caused a 'ServFail' packet in 1.99.8, indicating failure, leading to hosts not
resolving. Thanks to Martin Gillstrom for noticing this.
Zone2sql balked at zones editted under operating sytems terminating files with ^Z (Windows). Thanks Brian Willcott for reporting this.
PostgreSQL backend logged the password used to connect. Now only does so in case of failure to connect. Thanks to 'Webspider' for noticing this.
Debian unstable distribution wrongly depended on home compiled PostgreSQL libraries. Thanks to Konrad Wojas for noticing this.
Features:
When operating as a slave, AAAA records are now supported in the zone. They were already supported in master zones.
IPv6 transport support - PDNS can now listen on an IPv6 socket using the local-ipv6 setting.
Very silly randombackend added which appears in the documentation as a sample backend. See .
When transferring a slave zone from a master, out of zone data is now rejected. Malicious operators might try to insert bad records otherwise.
'Supermaster' support for automatic provisioning from masters. See .
Recursing backend can now live on a non-standard (!=53) port. See .
Slave zone retrieval is now queued instead of immediate, which scales better and is more resilient to temporary failures.
max-queue-length parameter. If this many packets are queued for database attention, consider the situation hopeless and
respawn.
Internal:
SOA records are now 'special' and each backend can optionally generate them in special ways. PostgreSQL backend does so
when operating as a slave.
Writing backends is now a lot easier. See .
Added Bindbackend to internal regression tests, confirming that it is compliant.
Version 1.99.8 Early Access Prerelease
A lot of infrastructure work gearing up to 2.0. Some stability bugs fixed and a lot of new features.
Bugs fixed:
Bindbackend was overly complex and crashed on some systems on startup. Simplified launch code.
SOA fields were not always properly filled in, causing default values to go out on the wire
Obscure bug triggered by malicious packets (we know who you are) in SOA finding code fixed.
Magic serial number calculation contained a double free leading to instability.
Standards violation, questions for domains for which PDNS was unauthoritative now get a SERVFAIL answer.
Thanks to the IETF Namedroppers list for helping out with this.
Slowly launching backends were being relaunched at a great rate when queries were coming in while launching backends.
MySQL-on-unix-domain-socket on SMP systems was overwhelmed by the quick connection rate on launch, inserted a small 50ms delay.
Some SMP problems appear to be compiler related. Shifted to GCC 3.0.4 for Linux.
Ran ispell on documentation.
Feature enhancements:
Recursing backend. See . Allows recursive and authoritative DNS on the same IP address.
NAPTR support, which is especially useful for the ENUM/E.164 community.
Zone transfers can now be allowed per netmask instead of only per IP address.
Preliminary support for slave operation included. Only for the adventurous right now! See
All record types now documented, see .
Known bugs
Wildcard CNAMES do not work as they do with bind.
Recursion sometimes sends out duplicate packets (fixed in 1.99.9 snapshots)
Some stability issues which are caught by the guardian
Missing features
Features present in this document, but disabled or withheld from the current release:
gmysqlbackend, oraclebackend
Version 1.99.7 Early Access Prerelease
Named.conf parsing got a lot of work and many more bind configurations can now be parsed. Furthermore, error reporting was improved.
Stability is looking good.
Bugs fixed:
Bind parser got confused by filenames with underscores and colons.
Bind parser got confused by spaces in quoted names
FreeBSD version now stops and starts when instructed to do so.
Wildcards were off by default, which violates standards. Now on by default.
--oracle was broken in zone2sql
Feature enhancements:
Line number counting goes on as it should when including files in named.conf
Added --no-config to enable users to start the pdns daemon without parsing the configuration file.
zone2sql now has --bare for unformatted output which can be used to generate insert statements for different database layouts
zone2sql now has --gpgsql, which is an alias for --mysql, to output in a format useful for the default Generic PgSQL backend
zone2sql is now documented.
Known bugs
Wildcard CNAMES do not work as they do with bind.
Missing features
Features present in this document, but disabled or withheld from the current release:
gmysqlbackend, oraclebackend
Some of these features will be present in newer releases.
Version 1.99.6 Early Access Prerelease
This version is now running on dns-eu1.powerdns.net and working very well for us. But please remain cautious before
deploying!
Bugs fixed:
Webserver neglected to show log messages
TCP question/answer miscounted multiple questions over one socket. Fixed misnaming of counter
Packetcache now detects clock skew and times out entries
named.conf parser now reports errors with line number and offending token
Filenames in named.conf can now contain :
Feature enhancements:
The webserver now by default does not print out configuration statements, which might contain database backends. Use
webserver-print-arguments to restore the old behaviour.
Generic PostgreSQL backend is now included. Still rather beta.
Known bugs
FreeBSD version does not stop when requested to do so.
Wildcard CNAMES do not work as they do with bind.
Missing features
Features present in this document, but disabled or withheld from the current release:
gmysqlbackend, oraclebackend
Some of these features will be present in newer releases.
Version 1.99.5 Early Access Prerelease
The main focus of this release is stability and TCP improvements. This is the first release PowerDNS-the-company actually considers for running
on its production servers!
Major bugs fixed:
Zone2sql received a floating point division by zero error on named.confs with less than 100 domains.
Huffman encoder failed without specific error on illegal characters in a domain
Fixed huge memory leaks in TCP code.
Removed further file descriptor leaks in guardian respawning code
Pipebackend was too chatty.
pdns_server neglected to close fds 0, 1 & 2 when daemonizing
Feature enhancements:
bindbackend can be instructed not to check the ctime of a zone by specifying bind-check-interval=0,
which is also the new default.
pdns_server --list-modules lists all available modules.
Performance enhancements:
TCP code now only creates a new database connection for AXFR.
TCP connections timeout rather quickly now, leading to less load on the server.
Known bugs
FreeBSD version does not stop when requested to do so.
Wildcard CNAMES do not work as they do with bind.
Missing features
Features present in this document, but disabled or withheld from the current release:
gmysqlbackend, oraclebackend, gpgsqlbackend
Some of these features will be present in newer releases.
Version 1.99.4 Early Access Prerelease
A lot of new named.confs can now be parsed, zone2sql & bindbackend have gained features and stability.
Major bugs fixed:
Label compression was not always enabled, leading to large reply packets sometimes.
Database errors on TCP server lead to a nameserver reload by the guardian.
MySQL backend neglected to close its connection properly.
BindParser miss parsed some IP addresses and netmasks.
Truncated answers were also truncated on the packetcache, leading to truncated TCP answers.
Feature enhancements:
Zone2sql and the bindbackend now understand the Bind $GENERATE{} syntax.
Zone2sql can optionally gloss over non-existing zones with --on-error-resume-next.
Zone2sql and the bindbackend now properly expand @ also on the right hand side of records.
Zone2sql now sets a default TTL.
DNS UPDATEs and NOTIFYs are now logged properly and sent the right responses.
Performance enhancements:
'Fancy records' are no longer queried for on ANY queries - this is a big speedup.
Known bugs
FreeBSD version does not stop when requested to do so.
Zone2sql refuses named.confs with less than 100 domains.
Wildcard CNAMES do not work as they do with bind.
Missing features
Features present in this document, but disabled or withheld from the current release:
gmysqlbackend, oraclebackend, gpgsqlbackend
Some of these features will be present in newer releases.
Version 1.99.3 Early Access Prerelease
The big news in this release is the BindBackend which is now capable of parsing many more named.conf Bind configurations.
Furthermore, PDNS has successfully parsed very large named.confs with large numbers of small domains, as well as small numbers of
large domains (TLD).
Zone transfers are now also much improved.
Major bugs fixed:
zone2sql leaked file descriptors on each domain, used wrong Bison recursion leading to
parser stack overflows. This limited the amount of domains that could be parsed to 1024.
zone2sql can now read all known zonefiles, with the exception of those containing $GENERATE
Guardian relaunching a child lost two file descriptors
Don't die on a connection reset by peer during zone transfer.
Webserver does not crash anymore on ringbuffer resize
Feature enhancements:
AXFR can now be disabled, and re-enabled per IP address
--help accepts a parameter, will then show only help items with that prefix.
zone2sql now accepts a --zone-name parameter
BindBackend maturing - 9500 zones parsed in 3.5 seconds. No longer case sensitive.
Performance enhancements:
Implemented RFC-breaking AXFR format (which is the industry standard). Zone transfers now zoom along
at wirespeed (many megabits/s).
Known bugs
FreeBSD version does not stop when requested to do so.
BindBackend cannot parse zones with $GENERATE statements.
Missing features
Features present in this document, but disabled or withheld from the current release:
gmysqlbackend, oraclebackend, gpgsqlbackend
Some of these features will be present in newer releases.
Version 1.99.2 Early Access Prerelease
Major bugs fixed:
Database backend reload does not hang the daemon anymore
Buffer overrun in local socket address initialisation may have caused binding problems
setuid changed the uid to the gid of the selected user
zone2sql doesn't coredump on invocation anymore. Fixed lots of small issues.
Don't parse configuration file when creating configuration file. This was a problem with reinstalling.
Performance improvements:
removed a lot of unnecessary gettimeofday calls
removed needless select(2) call in case of listening on only one address
removed 3 useless syscalls in the fast path
Having said that, more work may need to be done. Testing on a 486 saw packet rates in a simple setup
(question/wait/answer/question..) improve from 200 queries/second to over 400.
Usability improvements:
Fixed error checking in init.d script (show, mrtg)
Added 'uptime' to the mrtg output
removed further GNUisms from installer and init.d scripts for use on FreeBSD
Debian package and apt repository, thanks to Wichert Akkerman.
FreeBSD /usr/ports, thanks to Peter van Dijk (in progress).
Stability may be an issue as well as performance. This version has a tendency to log a bit too much which slows
the nameserver down a lot.
Known bugs
Decreasing a ringbuffer on the website is a sure way to crash the daemon. Zone2sql, while improved, still
has problems with a zone in the following format:
name IN A 1.2.3.4
IN A 1.2.3.5
To fix, add 'name' to the second line.
Zone2sql does not close filedescriptors.
FreeBSD version does not stop when requested via the init.d script.
Missing features
Features present in this document, but disabled or withheld from the current release:
gmysqlbackend, oraclebackend, gpgsqlbackend
fully functioning bindbackend - will try to parse named.conf, but probably fail
Some of these features will be present in newer releases.
Version 1.99.1 Early Access Prerelease
This is the first public release of what is going to become PDNS 2.0. As such, it is not of production quality.
Even PowerDNS-the-company does not run this yet.
Stability may be an issue as well as performance. This version has a tendency to log a bit too much which slows
the nameserver down a lot.
Known bugs
Decreasing a ringbuffer on the website is a sure way to crash the daemon. Zone2sql is very buggy.
Missing features
Features present in this document, but disabled or withheld from the current release:
gmysqlbackend, oraclebackend, gpgsqlbackend
fully functioning bindbackend - will not parse configuration files
Some of these features will be present in newer releases.
Security
As of the 8th of January 2003, no actual security problems with PowerDNS 2.9.4 or later are known about. This page
will be updated with all bugs which are deemed to be security problems, or could conceivably lead to those. Any such notifications
will also be sent to all PowerDNS mailinglists and BUGTRAQ.
All versions of PowerDNS before 2.9 are known to suffer from remote denial of service problems which can disrupt operation. Please upgrade
to 2.9.4 as this page will only contain detailed security information from 2.9.4 onwards.
If you have a security problem to report, please email us at both powerdns@powerdns.com and at
ahu@ds9a.nl. We adhere to the Rain Forest Puppy
Full Disclosure Policy (RFPolicy) v2.0 and we ask you to do the same.
We remind PowerDNS users that under the terms of the GNU General Public License, PowerDNS comes with ABSOLUTELY NO WARRANTY.
This license is included in the distribution and in this documentation, see .
Acknowledgements
PowerDNS is grateful for the help of the following people or institutions:
Dave AalderingWichert AkkermanAntony AntonyMike Benoit (NetNation Communication Inc.)Peter van DijkKoos van den HoutAndre KoopalEric VeldhuyzenPaul WoutersThomas WoutersIETF Namedroppers mailinglist
Thanks!
(these people don't share the blame for any errors or mistakes in powerdns - those are all ours)
Installing on Unix
You will typically install PDNS > 2.9 via source or via a package. Earlier versions used a clumsy binary installer.
Possible problems at this point
At this point some things may have gone wrong. Typical errors include:
error while loading shared libraries: libstdc++.so.x: cannot open shared object file: No such file or directory
Errors looking like this indicate a mismatch between your PDNS distribution and your Unix operating system. Download the static PDNS
distribution for your operating system and try again. Please contact pdns@powerdns.com if this is impractical.
Testing your install
After installing, it is a good idea to test the basic functionality of the software before configuring database backends.
For this purpose, PowerDNS contains the 'bindbackend' which has a domain built in example.com, which is
officially reserved for testing.
To test, edit pdns.conf and add the following if not already present:
launch=bind
bind-example-zones
This configures powerdns to 'launch' the bindbackend, and enable the example zones. To fire up PDNS in testing mode, execute:
/etc/init.d/pdns monitor, where you may have to substitute the location of your SysV init.d location you
specified earlier.
In monitor mode, the pdns process runs in the foreground and is very verbose, which is perfect for testing your install.
If everything went all right, you can query the example.com domain like this:
host www.example.com 127.0.0.1
www.example.com should now have IP address 1.2.3.4. The host command can usually be found in the dnsutils
package of your operating system. Alternate command is: dig www.example.com A @127.0.0.1 or even
nslookup www.example.com 127.0.0.1, although nslookup is not advised for DNS diagnostics.
example.com SOA record
example.com NS record pointing to ns1.example.com
example.com NS record pointing to ns2.example.com
example.com MX record pointing to mail.example.com
example.com MX record pointing to mail1.example.com
mail.example.com A record pointing to 4.3.2.1
mail1.example.com A record pointing to 5.4.3.2
ns1.example.com A record pointing to 4.3.2.1
ns2.example.com A record pointing to 5.4.3.2
host-0 to host-9999.example.com A record pointing to 2.3.4.5
When satisfied that basic functionality is there, type QUIT to exit the monitor mode.
The adventurous may also type SHOW * to see some internal statistics.
In case of problems, you will want to read the following section.
Typical errors
At this point some things may have gone wrong. Typical errors include:
binding to UDP socket: Address already in use
This means that another nameserver is listening on port 53 already. You can resolve this problem
by determining if it is safe to shutdown the nameserver already present, and doing so. If uncertain,
it is also possible to run PDNS on another port. To do so, add local-port=5300 to
pdns.conf, and try again. This however implies that you can only test your nameserver
as clients expect the nameserver to live on port 53.
binding to UDP socket: Permission denied
You must be superuser in order to be able to bind to port 53. If this is not a possibility,
it is also possible to run PDNS on another port. To do so, add local-port=5300 to
pdns.conf, and try again. This however implies that you can only test your nameserver
as clients expect the nameserver to live on port 53.
Unable to launch, no backends configured for querying
PDNS did not find the launch=bind instruction in pdns.conf.
Multiple IP addresses on your server, PDNS sending out answers on the wrong oneMassive amounts of 'recvfrom gave error, ignoring: Connection refused'
If you have multiple IP addresses on the internet on one machine, UNIX often sends out answers over another interface
than which the packet came in on. In such cases, use local-address to bind to specific IP addresses, which
can be comma separated. The second error comes from remotes disregarding answers to questions it didn't ask to that IP address
and sending back ICMP errors.
Running PDNS on unix
PDNS is normally controlled via a SysV-style init.d script, often located in /etc/init.d or
/etc/rc.d/init.d. This script accepts the following commands:
monitor
Monitor is a special way to view the daemon. It executes PDNS in the foreground with
a lot of logging turned on, which helps in determining startup problems.
Besides running in the foreground, the raw PDNS control socket is made available. All external
communication with the daemon is normally sent over this socket. While useful, the control console
is not an officially supported feature. Commands which work are: QUIT, SHOW *,
SHOW varname, RPING.
start
Start PDNS in the background. Launches the daemon but makes no special effort to determine success,
as making database connections may take a while. Use status to query success. You
can safely run start many times, it will not start additional PDNS instances.
restart
Restarts PDNS if it was running, starts it otherwise.
status
Query PDNS for status. This can be used to figure out if a launch was successful.
The status found is prefixed by the PID of the main PDNS process.
stop
Requests that PDNS stop. Again, does not confirm success. Success can be ascertained with the status command.
dump
Dumps a lot of statistics of a running PDNS daemon. It is also possible to single out specific variable by using
the show command.
show variable
Show a single statistic, as present in the output of the dump.
mrtg
See the performance monitoring .
Installing on Microsoft Windows
PowerDNS support for Windows is, as of 1.99.12, very recent and therefore quite 'beta'. For reliability, we currently advise the use of
the Unix versions. Furthermore there is no support for master or slave operation in the ODBC backend, which is the only one provided currently.
This will be fixed soon.
As of 1.99.12, PowerDNS supports Windows natively. PDNS can act as an NT service and works with any ODBC drivers you may have.
To install PowerDNS for Windows you should check if your PC meets the following requirements:
A PC running Microsoft NT (with a recent servicepack and at least mdac 2.5), 2000 or XP.
An ODBC source containing valid zone information (an example MS Access database is supplied in the form of powerdns.mdb).
If your system meets these requirements, download the installer from http://www.powerdns.com/pdns/.
After downloading the file begin the installation procedure by starting powerdns-VERSION.exe.
After installing the software you should create a valid ODBC source.
To do this you have open the ODBC sources dialog: Start->Settings->Control Panel->Administrative Tools->Data Sources (ODBC).
We'll use the example zone database that is included in the installation to explain how to create a source.
When you are in the ODBC sources dialog you activate the System DSN tab.
It is important to create a System DSN instead of an User DNS, otherwise the ODBC backend cannot function.
Press Add..., then you have to select a driver.
Select Microsoft Access Driver (*.mdb).
Use PowerDNS as the DSN name, you can leave the description empty.
Then press Select... to select the database (ie. C:\Program Files\PowerDNS\powerdns.mdb).
Press Ok and you should be done.
For more information, see .
Configuring PDNS on Microsoft Windows
You can specify program parameters in the pdns.conf file
which should be located in pdns directory (ie. C:\Program Files\PowerDNS\).
To see a list of available parameters you can run pdns.exe --help.
A default configuration file has been supplied with the installation.
Running PDNS on Microsoft Windows
If you installed pdns on Windows NT, 2000 or XP you can run pdns as a service.
This is how to do it:
Go to services (Start->Settings->Control Panel->Administrative Tools->Services) and locate PDNS (you should have registered the program as a NT service during the installation).
Double-click on PDNS and push the start button. You should now see a progress bar that gets to the end and see the status change to 'Started'.
This is the same as starting pdns like this:
pdns.exe --ntservice
If you haven't registered pdns as a service during the installation you can do so from the commandline by starting pdns like this:
pdns.exe --register-service
You can run pdns as a standard console program by using a command prompt or Start->Run...
This way you can specify command-line parameters (see the documentation for commandline options).
If you chose to add a PowerDNS menu to the start menu during the installation you can start pdns using the pdns shortcut in that menu.
Configure database connectivity
The default PDNS distribution comes with a simple MySQL backend built in, which we will now use for
demonstrating database connectivity. This backend is called 'mysql', and needs to be configured
in pdns.conf. Add the following lines, adjusted for your local setup:
launch=mysql
mysql-host=127.0.0.1
mysql-user=root
mysql-dbname=pdnstest
Remove any earlier launch statements. Also remove the bind-example-zones
statement as the bind module is no longer launched.
Make sure that you can actually resolve the hostname of your database without accessing the database! It is advised to supply
an IP address here to prevent chicken/egg problems!
This section describes the deprecated MySQL backend, which should no longer be used! Use the Generic MySQL backend! See
.
Now start PDNS using the monitor command:
# /etc/init.d/pdns monitor
(...)
15:31:30 PowerDNS 1.99.0 (Mar 12 2002, 15:00:28) starting up
15:31:30 About to create 3 backend threads
15:31:30 [MySQLbackend] Failed to connect to database: Error: Unknown database 'pdnstest'
15:31:30 [MySQLbackend] Failed to connect to database: Error: Unknown database 'pdnstest'
15:31:30 [MySQLbackend] Failed to connect to database: Error: Unknown database 'pdnstest'
This is as to be expected - we did not yet add anything to MySQL for PDNS to read from. At this point you may also see
other errors which indicate that PDNS either could not find your MySQL server or was unable to connect to it. Fix these
before proceeding.
General MySQL knowledge is assumed in this chapter, please do not interpret these commands as DBA advice!
Configuring MySQL
Connect to MySQL as a user with sufficient privileges and issue the following commands:
# mysql
mysql> CREATE DATABASE pdnstest;
mysql> use pdnstest;
mysql> CREATE TABLE records (
id int(11) NOT NULL auto_increment,
domain_id int(11) default NULL,
name varchar(255) default NULL,
type varchar(6) default NULL,
content varchar(255) default NULL,
ttl int(11) default NULL,
prio int(11) default NULL,
change_date int(11) default NULL,
PRIMARY KEY (id),
KEY name_index(name),
KEY nametype_index(name,type),
KEY domainid_index(domain_id)
);
Now we have a database and an empty table. PDNS should now be able to launch in monitor mode and display no errors:
# /etc/init.d/pdns monitor
(...)
15:31:30 PowerDNS 1.99.0 (Mar 12 2002, 15:00:28) starting up
15:31:30 About to create 3 backend threads
15:39:55 [MySQLbackend] MySQL connection succeeded
15:39:55 [MySQLbackend] MySQL connection succeeded
15:39:55 [MySQLbackend] MySQL connection succeeded
A sample query sent to the database should now return quickly without data:
$ host www.test.com 127.0.0.1
www.test.com A record currently not present at localhost
And indeed, the control console now shows:
Mar 12 15:41:12 We're not authoritative for 'www.test.com', sending unauth normal response
Now we need to add some records to our database:
# mysql pdnstest
mysql>
INSERT INTO records (domain_id, name, content, type,ttl,prio)
VALUES (1,'test.com','localhost ahu@ds9a.nl 1','SOA',86400,NULL);
INSERT INTO records (domain_id, name, content, type,ttl,prio)
VALUES (1,'test.com','dns-us1.powerdns.net','NS',86400,NULL);
INSERT INTO records (domain_id, name, content, type,ttl,prio)
VALUES (1,'test.com','dns-eu1.powerdns.net','NS',86400,NULL);
INSERT INTO records (domain_id, name, content, type,ttl,prio)
VALUES (1,'www.test.com','199.198.197.196','A',120,NULL);
INSERT INTO records (domain_id, name, content, type,ttl,prio)
VALUES (1,'mail.test.com','195.194.193.192','A',120,NULL);
INSERT INTO records (domain_id, name, content, type,ttl,prio)
VALUES (1,'localhost.test.com','127.0.0.1','A',120,NULL);
INSERT INTO records (domain_id, name, content, type,ttl,prio)
VALUES (1,'test.com','mail.test.com','MX',120,25);
If we now requery our database, www.test.com should be present:
$ host www.test.com 127.0.0.1
www.test.com A 199.198.197.196
$ host -v -t mx test.com 127.0.0.1
Address: 127.0.0.1
Aliases: localhost
Query about test.com for record types MX
Trying test.com ...
Query done, 1 answer, authoritative status: no error
test.com 120 IN MX 25 mail.test.com
Additional information:
mail.test.com 120 IN A 195.194.193.192
To confirm what happened, issue the command SHOW * to the control console:
% show *
corrupt-packets=0,latency=0,packetcache-hit=2,packetcache-miss=5,packetcache-size=0,
qsize-a=0,qsize-q=0,servfail-packets=0,tcp-answers=0,tcp-queries=0,
timedout-packets=0,udp-answers=7,udp-queries=7,
%
The actual numbers will vary somewhat. Now enter QUIT and start PDNS as a regular daemon, and check launch status:
# /etc/init.d/pdns start
pdns: started
# /etc/init.d/pdns status
pdns: 8239: Child running
# /etc/init.d/pdns dump
pdns: corrupt-packets=0,latency=0,packetcache-hit=0,packetcache-miss=0,
packetcache-size=0,qsize-a=0,qsize-q=0,servfail-packets=0,tcp-answers=0,
tcp-queries=0,timedout-packets=0,udp-answers=0,udp-queries=0,
You now have a working database driven nameserver! To convert other zones already present, use the zone2sql
described in Appendix A.
Common problems
Most problems involve PDNS not being able to connect to the database.
Can't connect to local MySQL server through socket '/tmp/mysql.sock' (2)
Your MySQL installation is probably defaulting to another location for its socket. Can be resolved
by figuring out this location (often /var/run/mysqld.sock), and specifying it
in the configuration file with the mysql-socket parameter.
Another solution is to not connect to the socket, but to 127.0.0.1, which can be achieved by specifying
mysql-host=127.0.0.1.
Host 'x.y.z.w' is not allowed to connect to this MySQL server
These errors are generic MySQL errors. Solve them by trying to connect to your MySQL database with the MySQL
console utility mysql with the parameters specified to PDNS. Consult the MySQL documentation.
Dynamic resolution using the PipeBackend
Also included in the PDNS distribution is the PipeBackend. The PipeBackend is primarily meant for
allowing rapid development of new backends without tight integration with PowerDNS. It allows
end-users to write PDNS backends in any language. A perl sample is provided.
The PipeBackend is also very well suited for dynamic resolution of queries. Example applications include
DNS based loadbalancing, geo-direction, DNS based failover with low TTLs.
The Pipe Backend also has a separate chapter in the backends appendix, see .
The Pipe Backend currently does not function under FreeBSD 4.x and 5.x, probably due to unfavorable interactions between
its threading implementation and the fork system call.
Interestingly, the Linux PowerDNS binary running under the Linuxulator on FreeBSD does work.
Deploying the PipeBackend with the BindBackend
Included with the PDNS distribution is the example.pl backend which has knowledge of the example.com zone, just like
the BindBackend. To install both, add the following to your pdns.conf:
launch=pipe,bind
bind-example-zones
pipe-command=location/of/backend.pl
Please adjust the pipe-command statement to the location of the unpacked PDNS distribution. If your backend is slow,
raise pipe-timeout from its default of 2000ms.
Now launch PDNS in monitor mode, and perform some queries. Note the difference with the earlier experiment where only the
BindBackend was loaded. The PipeBackend is launched first and thus gets queried first.
The sample backend.pl script knows about:
webserver.example.com A records pointing to 1.2.3.4, 1.2.3.5, 1.2.3.6
www.example.com CNAME pointing to webserver.example.com
MBOXFW (mailbox forward) records pointing to powerdns@example.com.
See the smtpredir documentation for information about MBOXFW.
For more information about how to write exciting backends with the PipeBackend, see Appendix A.
Logging & Monitoring PDNS performance
In a production environment, you will want to be able to monitor PDNS performance. For this purpose, currently
two methods are available, the webserver and the init.d
dump, show and
mrtg, commands. Furthermore, PDNS can perform a configurable amount of operational logging. This chapter
also explains how to configure syslog for best results.
Webserver
To launch the internal webserver, add a webserver statement to the pdns.conf. This
will instruct the PDNS daemon to start a webserver on localhost at port 8081, without password protection.
Only local users (on the same host) will be able to access the webserver by default.
The webserver lists a lot of information about the PDNS process, including frequent queries, frequently failing queries,
lists of remote hosts sending queries, hosts sending corrupt queries etc. The webserver does not allow
remote management of the daemon.
The following nameserver related configuration items are available:
webserver
If set to anything but 'no', a webserver is launched.
webserver-address
Address to bind the webserver to. Defaults to 127.0.0.1, which implies that only the local computer
is able to connect to the nameserver! To allow remote hosts to connect, change to 0.0.0.0 or the
physical IP address of your nameserver.
webserver-password
If set, viewers will have to enter this plaintext password in order to gain access to the statistics.
webserver-port
Port to bind the webserver to. Defaults to 8081.
Via init.d commands
As mentioned before, the init.d commands dump, show and
mrtg fetch data from a running PDNS process. Especially mrtg is powerful -
it outputs data in a format that is ready for processing by the MRTG graphing tool.
MRTG can make insightful graphics on the performance of your nameserver, enabling the operator to easily spot trends.
MRTG can be found on
http://people.ee.ethz.ch/~oetiker/webtools/mrtg/mrtg.html
A sample mrtg.conf:
Interval: 5
WorkDir: /var/www/mrtg
WriteExpires: yes
Options[_]: growright,nopercent
XSize[_]: 600
#---------------------------------------------------------------
Target[udp-queries]: `/etc/init.d/pdns mrtg udp-queries udp-answers`
Options[udp-queries]: growright,nopercent,perminute
MaxBytes[udp-queries]: 600000
AbsMax[udp-queries]: 600000
Title[udp-queries]: Queries per minute
PageTop[udp-queries]: <H2>Queries per minute</H2>
WithPeak[udp-queries]: ymwd
YLegend[udp-queries]: queries/minute
ShortLegend[udp-queries]: q/m
LegendI[udp-queries]: udp-questions
LegendO[udp-queries]: udp-answers
Target[perc-failed]: `/etc/init.d/pdns mrtg udp-queries udp-answers`
Options[perc-failed]: growright,dorelpercent,perminute
MaxBytes[perc-failed]: 600000
AbsMax[perc-failed]: 600000
Title[perc-failed]: Queries per minute, with percentage success
PageTop[perc-failed]: <H2>Queries per minute, with percentage success</H2>
WithPeak[perc-failed]: ymwd
YLegend[perc-failed]: queries/minute
ShortLegend[perc-failed]: q/m
LegendI[perc-failed]: udp-questions
LegendO[perc-failed]: udp-answers
Target[packetcache-rate]: `/etc/init.d/pdns mrtg packetcache-hit udp-queries`
Options[packetcache-rate]: growright,dorelpercent,perminute
Title[packetcache-rate]: packetcache hitrate
MaxBytes[packetcache-rate]: 600000
AbsMax[packetcache-rate]: 600000
PageTop[packetcache-rate]: <H2>packetcache hitrate</H2>
WithPeak[packetcache-rate]: ymwd
YLegend[packetcache-rate]: queries/minute
ShortLegend[packetcache-rate]: q/m
LegendO[packetcache-rate]: total
LegendI[packetcache-rate]: hit
Target[packetcache-missrate]: `/etc/init.d/pdns mrtg packetcache-miss udp-queries`
Options[packetcache-missrate]: growright,dorelpercent,perminute
Title[packetcache-missrate]: packetcache MISSrate
MaxBytes[packetcache-missrate]: 600000
AbsMax[packetcache-missrate]: 600000
PageTop[packetcache-missrate]: <H2>packetcache MISSrate</H2>
WithPeak[packetcache-missrate]: ymwd
YLegend[packetcache-missrate]: queries/minute
ShortLegend[packetcache-missrate]: q/m
LegendO[packetcache-missrate]: total
LegendI[packetcache-missrate]: MISS
Target[latency]: `/etc/init.d/pdns mrtg latency`
Options[latency]: growright,nopercent,gauge
MaxBytes[latency]: 600000
AbsMax[latency]: 600000
Title[latency]: Query/answer latency
PageTop[latency]: <H2>Query/answer latency</H2>
WithPeak[latency]: ymwd
YLegend[latency]: usec
ShortLegend[latency]: usec
LegendO[latency]: latency
LegendI[latency]: latency
Target[recursing]: `/etc/init.d/pdns mrtg recursing-questions recursing-answers`
Options[recursing]: growright,nopercent,gauge
MaxBytes[recursing]: 600000
AbsMax[recursing]: 600000
Title[recursing]: Recursive questions/answers
PageTop[recursing]: <H2>Recursing questions/answers</H2>
WithPeak[recursing]: ymwd
YLegend[recursing]: queries/minute
ShortLegend[recursing]: q/m
LegendO[recursing]: recursing-questions
LegendI[recursing]: recursing-answers
Operational logging using syslog(logging-facility is available from 1.99.10 and onwards)
This chapter assumes familiarity with syslog, the unix logging device. PDNS logs messages with different levels. The more urgent the
message, the lower the 'priority'. By default, PDNS will only log messages with an urgency of 3 or lower, but this can be changed
using the loglevel setting in the configuration file. Setting it to 0 will eliminate all logging, 9 will log
everything.
By default, logging is performed under the 'DAEMON' facility which is shared with lots of other programs. If you regard nameserving
as important, you may want to have it under a dedicated facility so PDNS can log to its own files, and not clutter generic files.
For this purpose, syslog knows about 'local' facilities, numbered from LOCAL0 to LOCAL7. To move PDNS logging to LOCAL0, add
logging-facility=0 to your configuration.
Furthermore, you may want to have separate files for the differing prioties - preventing lower priority messages from obscuring
important ones.
A sample syslog.conf might be:
local0.info -/var/log/pdns.info
local0.warn -/var/log/pdns.warn
local0.err /var/log/pdns.err
Where local0.err would store the really important messages. For performance and diskspace reasons, it is advised
to audit your syslog.conf for statements also logging PDNS activities. Many syslog.confs have a '*.*' statement to
/var/log/syslog, which you may want to remove.
For performance reasons, be especially certain that no large amounts of synchronous logging take place. Under Linux, this
is indicated by filenames not starting with a '-' - indicating a synchronous log, which hurts performance.
Security settings & considerationsSettingsPDNS has several options to easily allow it to run more securely. Most notable are the chroot,
setuid and setgid options which can be specified.Running as a less privileged identity
By specifying setuid and setgid, PDNS changes to this identity shortly after
binding to the privileged DNS ports. These options are highly recommended. It is suggested that a separate identity
is created for PDNS as the user 'nobody' is in fact quite powerful on most systems.
Both these parameters can be specified either numerically or as real names.
You should set these parameters immediately if they are not set!
Jailing the process in a chroot
The chroot option secures PDNS to its own directory so that even if it should become compromised and
under control of external influences, it will have a hard time affecting the rest of the system.
Even though this will hamper hackers a lot, chroot jails have been known to be broken.
When chrooting PDNS, take care that backends will be able to get to their files. Many databases need access to a UNIX
domain socket which should live within the chroot. It is often possible to hardlink such a socket into the chroot dir.
The default PDNS configuration is best chrooted to ./, which boils down to the configured location
of the controlsocket.
This is achieved by adding the following to pdns.conf: chroot=./, and restarting PDNS.
Considerations
In general, make sure that the PDNS process is unable to execute commands on your backend database.
Most database backends will only need SELECT privilege. Take care to not connect to your database as the 'root'
or 'sa' user, and configure the chosen user to have very slight privileges.
Databases empathic-ally do not need to run on the same machine that runs PDNS! In fact, in benchmarks
it has been discovered that having a separate database machine actually improves performance.
Separation will enhance your database security highly. Recommended.
Virtual hosting
It may be advantageous to run multiple separate PDNS installations on a single host, for example to make sure
that different customers cannot affect each others zones. PDNS fully supports running multiple instances on one host.
To generate additional PDNS instances, copy the init.d script pdns to pdns-name,
where name is the name of your virtual configuration. Must not contain a - as this will confuse the
script.
When you launch PDNS via this renamed script, it will seek configuration instructions not in pdns.conf
but in pdns-name.conf, allowing for separate specification of parameters.
Be aware however that the init.d force-stop will kill all PDNS instances!
Performance related settings
Different backends will have different characteristics - some will want to have more parallel
instances than others. In general, if your backend is latency bound, like most relational databases are,
it pays to open more backends.
This is done with the distributor-threads setting. Of special importance is the choice between 1
or more backends. In case of only 1 thread, PDNS reverts to unthreaded operation which may be a lot faster, depending
on your operating system and architecture.
Another very important setting cache-ttl. PDNS caches entire packets it sends out so as to save the
time to query backends to assemble all data. The default setting of 10 seconds may be low for high traffic sites, a value of
60 seconds rarely leads to problems.
Some PDNS operators set cache-ttl to many hours or even days, and use pdns_control purge to selectively
or globally notify PDNS of changes made in the backend. Also look at the Query Cache described in this chapter. It may
materially improve your performance.
To determine if PDNS is unable to keep up with packets, determine the value of the qsize-q variable.
This represents the number of packets waiting for database attention. During normal operations the queue should be small.
If it is known that backends will not contain CNAME records, the skip-cname setting can be used to prevent
the normally mandatory CNAME lookup that is needed at least once for each DNS query.
Much the same holds for the wildcards setting. On by default, each non-existent query will lead to a number of additional
wildcard queries. If it is known that the backends do not contain wildcard records, performance can be improved by adding wildcards=no
to pdns.conf.
Logging truly kills performance as answering a question from the cache is an order of magnitude less work than logging a
line about it. Busy sites will prefer to turn log-dns-details and log-failed-updates
off.
Packet Cache
PDNS by default uses the 'Packet Cache' to recognise identical questions and supply them with identical answers, without any further
processing. The default time to live is 10 seconds. It has been observed that the utility of the packet cache increases with the load on
your nameserver.
Not all backends may benefit from the packetcache. If your backend is memory based and does not lead to context switches, the packetcache
may actually hurt performance.
The size of the packetcache can be observed with /etc/init.d/pdns show packetcache-sizeQuery Cache
Besides entire packets, PDNS can also cache individual backend queries. Each DNS query leads to a number of backend queries,
the most obvious additional backend query is the check for a possible CNAME. So, when a query comes in for the 'A' record for
'www.powerdns.com', PDNS must first check for a CNAME for 'www.powerdns.com'.
The Query Cache caches these backend queries, many of which are quite repetitive. PDNS only caches queries with no answer,
or with exactly one. In the future this may be expanded but this lightweight solution is very simple and therefore fast.
Most gain is made from caching negative entries, ie, queries that have no answer. As these take little memory to store and
are typically not a real problem in terms of speed-of-propagation, the default TTL for negative queries is a rather high 60 seconds.
This only is a problem when first doing a query for a record, adding it, and immediately doing a query for that record again. It may
then take up to 60 seconds to appear. Changes to existing records however do not fall under the negative query ttl (
negquery-cache-ttl), but under the generic query-ttl which defaults to 20 seconds.
The default values should work fine for many sites. When tuning, keep in mind that the Query Cache mostly saves database access
but that the Packet Cache also saves a lot of CPU because 0 internal processing is done when answering a question from the
Packet Cache.
Migrating to PDNS
Before migrating to PDNS a few things should be considered.
PDNS is not a recursing nameserver on its own
If PDNS receives a question for which it is not authoritative, it can't go out on the net to figure out an answer. However,
because many installations are expected to be both authoritative and recursing, PDNS can use a separate recursing backend
to provide non-authoritative answers. See for more details.
PDNS does not operate as a 'slave' or 'master' server with all backends
Only the Generic PostgreSQL, Generic MySQL and BIND backends have the ability to act as master or slave.
To migrate, the zone2sql tool is provided.
Zone2sql
Zone2sql parses Bind named.conf files and zonefiles and outputs SQL
on standard out, which can then be fed to your database.
Zone2sql understands the Bind master file extension '$GENERATE' and will also honour '$ORIGIN' and '$TTL'.
For backends supporting slave operation (currently only the PostgreSQL backend), there is also an option to keep slave zones as slaves,
and not convert them to native operation.
By default, zone2sql outputs code suitable for the mysqlbackend, but it can also generate SQL for the Generic PostgreSQL and Oracle backends.
The following commands are available:
--bare
Output in a bare format, suitable for further parsing. The output is formatted as follows:
domain_id<TAB>'qname'<TAB>'qtype'<TAB>'content'<TAB>prio<TAB>ttl
--gmysql
Output in format suitable for the default configuration of the Generic MySQL backend.
--gpgsql
Output in format suitable for the default configuration of the Generic PostgreSQL backend.
--help
List options.
--mysql
Output in format suitable for the default configuration of the MySQL backend. Default.
--named-conf=...
Parse this named.conf to find locations of zones.
--on-error-resume-next
Ignore missing files during parsing. Dangerous.
--oracle
Output in format suitable for the default configuration of the Generic Oracle backend.
--slave
Maintain slave status of zones listed in named.conf as being slaves. The default behaviour is to convert all zones
to native operation.
--startid
Supply a value for the first domain_id generated. Defaults at 0.
--transactions
For Oracle and PostgreSQL output, wrap each domain in a transaction for higher speed and integrity.
--verbose
Be verbose during conversion.
--zone=...
Parse only this zone file. Conflicts with --named-conf parameter.
--zone-name=...
When parsing a single zone without $ORIGIN statement, set this as the zone name.
Recursion(only available from 1.99.8 and onwards)
PDNS is an authoritative nameserver. It answers questions with data from its backends. Besides handing out authoritative
answers, DNS also needs so called 'recursion', where a nameserver gets a question for which it has no authoritative answer available,
necessitating questions to other nameservers.
Although PDNS is an authoritative nameserver, a provision has been made to cater for installations that require both authoritative DNS
and recursion on one IP address.
By specifying the recursor option in the configuration file, questions requiring recursive treatment will be handed over
to the IP address specified. An example configuration might be recursor=130.161.180.1, which designates 130.161.180.1 as
the nameserver to handle recursive queries.
Any recursing nameserver is suitable but we highly advise the use of the DJBDNS dnscache (http://cr.yp.to/djbdns/dnscache.html).
Take care not to point recursor to PDNS, which leads to a very tight packet loop!
By specifying allow-recursion, recursion can be restricted to netmasks specified. The default is to allow
recursion from everywhere. Example: allow-recursion=192.168.0.0/24, 10.0.0.0/8, 1.2.3.4.
Details
Questions carry a number of flags. One of these is called 'Recursion Desired'. If PDNS is configured to allow recursion, AND such a flag
is seen, AND the IP address of the client is allowed to recurse via PDNS, then the packet is handed to the recursing backend.
If a Recursion Desired packet PDNS is configured to allow recursion, but not to the IP address of the client, resolution will proceed
as if the RD flag were unset and the answer will indicate that recursion was not available.
Recursive questions and answers are not stored in the Packet Cache as recursing backends are generally well equipped to cache questions
themselves.
It is also possible to use a resolver living on a different port. To do so, specify a recursor like this:
recursor=130.161.180.1:5300.
If the backend does not answer a question within a large amount of time, this is logged as 'Recursive query for remote 10.96.0.2 with internal id 0
was not answered by backend within timeout, reusing id'.
'Lazy recursion'
PowerDNS is an authoritative nameserver. Up to version 2.1, a packet indication that recursion was desired, coming from a host from which
recursion was allowed, would be handed sight unseen to the recursing backend. This means that older installations do not have the ability to 'override'
the internet with local data. Recursive queries would not be answered from the database.
This behaviour sufficed for many users but some installations have a pressing need to override the internet, for example to support recursive
queries for fake domains like 'powerdns.office' or '.internal'.
As of version 2.1, PowerDNS has a feature called 'lazy recursion' where a packet will only be handed to the recursing backend if it cannot be answered
completely from the database. 'Completely' in this case means that the original question has an answer in the local database and any additional processing
can also succeed from the database.
So for example, if you have the 'your.office' domain and a query comes in for its MX record, you should locally have the 'your.office' MX record
as well as the IP address of (for example) 'smtp.your.office'.
If any of these conditions fail, your packet is handed to the recursor anyhow. So to benefit from lazy-recursion, be very sure that all
data needed is present locally!.
To restore pre-2.1 behaviour, specify lazy-recursion=off.
Highly experimental internal resolver/recursing nameserver
As of 2.9.4, a small recursor comes with PowerDNS. The algorithm is influenced by the works of Dan J. Bernstein although
all mistakes are ours. Here are the current faults, so nobody can accuse us of false advertising:
Only operates on the foreground, it does not fork.
Can only answer queries for types and classes it knows about - it is not transparent as it should be.
Only ignores stale cache entries, does not actually clean them up. May replace them with newer data, however.
Not very IPv6 aware - does no AAAA additional processing.
Only compiles on Linux and possibly Solaris. FreeBSD 4.x decided not to support the
POSIX get/set/swapcontext functions. Bug your favorite FreeBSD kernel or libc maintainer for a fix,
or ask him to port MTasker (see below) to your operating system.
To compile, add --enable-recursor to configure and the file syncres will be
compiled. If you are lucky, that is. Send it queries like this:
dig ds9a.nl A @127.0.0.1 -p 5300. To run on a different port, use ./syncres --local-port=53.
To bind to another address, use the local-address setting.
PowerDNS author bert hubert has the pdns recursor in production and browsing with it works for him. Furthermore, the LARTC
mailinglist (2000 subscribers) is using the pdns recursing nameserver.
Good points:
Uses MTasker (homepage)
Can handle thousands of concurrent questions
Code is written linearly, sequentially, which means that there are no problems with 'query restart' or anything.
Relies heavily on Standard C++ Library infrastructure, which makes for little code (406 core lines).
Is very verbose in showing how recursion actually works.
The algorithm is simple and quite nifty.
We've figured out how to integrate this progam into PowerDNS, which will happen around 2.9.5.
Master/Slave operation & replication
PDNS offers full master and slave semantics for replicating domain information. Furthermore, PDNS can benefit from native
database replication.
Native replication
Native replication is the default, unless other operation is specifically configured. Native replication basically means that PDNS will
not send out DNS update notifications, nor will react to them. PDNS assumes that the backend is taking care of replication unaided.
MySQL replication has proven to be very robust and well suited, even over transatlantic connections between badly peering ISPs. Other PDNS
users employ Oracle replication which also works very well.
To use native replication, configure your backend storage to do the replication and do not configure PDNS to do so.
Slave operation
On launch, PDNS requests from all backends a list of domains which have not been checked recently for changes. This should happen every
'refresh' seconds, as specified in the SOA record. All domains that are unfresh are then checked for changes over at their
master. If the SOA serial number there is higher, the domain is retrieved and inserted into the database. In
any case, after the check the domain is declared 'fresh', and will only be checked again after 'refresh' seconds have passed.
PDNS also reacts to notifies by immediately checking if the zone has updated and if so, retransfering it.
All backends which implement this feature must make sure that they can handle transactions so as to not leave the zone in a half updated state.
MySQL configured with either BerkeleyDB or InnoDB meets this requirement, as do PostgreSQL and Oracle. The Bindbackend implements transaction
semantics by renaming files if and only if they have been retrieved completely and parsed correctly.
Slave operation can also be programmed using several pdns_control commands, see . The 'retrieve' command
is especially useful as it triggers an immediate retrieval of the zone from the configured master.
Supermaster automatic provisioning of slaves
PDNS can recognize so called 'supermasters'. A supermaster is a host which is master for domains and for which we are to be a slave. When
a master (re)loads a domain, it sends out a notification to its slaves. Normally, such a notification is only accepted if PDNS already
knows that it is a slave for a domain.
However, a notification from a supermaster carries more persuasion. When PDNS determines that a notification comes from a supermaster and it is
is bonafide, PDNS can provision the domain automatically, and configure itself as a slave for that zone.
To enable this feature, a backend needs to know about the IP address of the supermaster, and how PDNS will be listed in the set of
NS records remotely, and the 'account' name of your supermaster. There is no need to fill this out but it does help keep track of
where a domain comes from.
Master operation
When operating as a master, PDNS sends out notifications of changes to slaves, which react to these notifications by querying PDNS to see
if the zone changed, and transferring its contents if it has. Notifications are a way to promptly propagate zone changes to slaves, as
described in RFC 1996.
Left open by RFC 1996 is who is to be notified - which is harder to figure out than it sounds. All slaves for this domain must receive a notification
but the nameserver only knows the names of the slaves - not the IP addresses, which is where the problem lies. The nameserver itself might
be authoritative for the name of its secondary, but not have the data available.
To resolve this issue, PDNS tries multiple tactics to figure out the IP addresses of the slaves, and notifies everybody. In contrived configurations
this may lead to duplicate notifications being sent out, which shouldn't hurt.
Some backends may be able to detect zone changes, others may chose to let the operator indicate which zones have changed and which haven't.
Consult the documentation for your backend to see how it processes changes in zones.
To help deal with slaves that may have missed notifications, or have failed to respond to them, several override commands are available via
the pdns_control tool ():
pdns_control notify domain
This instructs PDNS to notify all IP addresses it considers to be slaves of this domain.
pdns_control notify-host domain ip-address
This is truly an override and sends a notification to an arbitrary IP address. Can be used in 'also-notify' situations
or when PDNS has trouble figuring out who to notify - which may happen in contrived configurations.
Fancy records for seamless email and URL integration
PDNS also supports so called 'fancy' records. A Fancy Record is actually not a DNS record, but it is translated into one. Currently,
two fancy records are implemented, but not very useful without additional unreleased software. For completeness, they are listed here.
The software will become available later on and is part of the Express and PowerMail suite of programs.
These records imply extra database lookups which has a performance impact. Therefore fancy records are only queried for if they are enabled
with the fancy-records command in pdns.conf.
MBOXFW
This record denotes an email forward. A typical entry looks like this:
support@yourdomain.com MBOXFW you@yourcompany.com
When PDNS encounters a request for an MX record for yourdomain.com it will, if fancy records are enabled, also check for the existence
of an MBOXFW record ending on '@yourdomain.com', in which case it will hand out a record containing the configured
smtpredirector. This server should then also be able to access the PDNS database to figure out where mail to
support@yourdomain.com should go to.
URL
URL records work in much the same way, but for HTTP. A sample record:
yourdomain.com URL http://somewhere.else.com/yourdomain
A URL record is converted into an A record containing the IP address configured with the urlredirector
setting. On that IP address a webserver should live that knows how to redirect yourdomain.com to
http://somewhere.else.com/yourdomain.
Index of all settings
All PDNS settings are listed here, excluding those that originate from backends, which are documented in the relevant chapters.
allow-axfr-ips=...When not allowing AXFR (disable-axfr), DO allow from these IP addresses or netmasks.
allow-recursion=...
By specifying allow-recursion, recursion can be restricted to netmasks specified. The default is to allow
recursion from everywhere. Example: allow-recursion=192.168.0.0/24, 10.0.0.0/8, 1.2.3.4.
cache-ttl=...
Seconds to store packets in the PacketCache. See .
chroot=...
If set, chroot to this directory for more security. See .
config-dir=...
Location of configuration directory (pdns.conf)
config-name=...
Name of this virtual configuration - will rename the binary image. See .
control-console=...
Debugging switch - don't use.
daemon=...
Operate as a daemon
default-soa-name=...
name to insert in the SOA record if none set in the backend
disable-axfr=...
Do not allow zone transfers
disable-tcp=...
Do not listen to TCP queries. Breaks RFC compliance.
distributor-threads=...
Default number of Distributor (backend) threads to start. See .
fancy-records=...
Process URL and MBOXFW records. See .
guardian | --guardian=yes | --guardian=no
Run within a guardian process. See .
help
Provide a helpful message
launch=...
Which backends to launch and order to query them in. See .
lazy-recursion=...
On by default as of 2.1. Checks local data first before recursing. See .
load-modules=...
Load this module - supply absolute or relative path. See .
local-address=...
Local IP address to which we bind. You can specify multiple addresses separated by commas or whitespace. 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 any.
local-port=...
The port on which we listen. Only one port possible.
log-failed-updates=...
If set to 'no', failed Windows Dynamic Updates will not be logged.
log-dns-details=...
If set to 'no', informative-only DNS details will not even be sent to syslog, improving performance. Available from 2.5
and onwards.
logging-facility=...
If set to a a digit, logging is performed under this LOCAL facility. See . Available from 1.99.9 and onwards.
loglevel=...
Amount of logging. Higher is more. Do not set below 3
max-queue-length=...
If this many packets are waiting for database attention, consider the situation hopeless and respawn.
module-dir=...
Default directory for modules. See .
negquery-cache-ttl=...
Seconds to store queries with no answer in the Query Cache. See .
no-config
Do not attempt to read the configuration file.
out-of-zone-additional-processing | --out-of-zone-additional-processing=yes | --out-of-zone-additional-processing=no
Do out of zone additional processing
query-cache-ttl=...
Seconds to store queries with an answer in the Query Cache. See .
queue-limit=...
Maximum number of miliseconds to queue a query. See .
query-logging | query-logging=yes | query-logging=no
Hints to a backend that it should log a textual representation of queries it performs. Can be set at runtime.
recursive-cache-ttl=...
Seconds to store recursive packets in the PacketCache. See .
recursor=...
If set, recursive queries will be handed to the recursor specified here. See .
setgid=...
If set, change group id to this gid for more security. See .
setuid=...
If set, change user id to this uid for more security. See .
skip-cname | --skip-cname=yes | --skip-cname=no
Do not perform CNAME indirection for each query. Has performance implications. See .
slave-cycle-interval=60
Schedule slave up-to-date checks of domains whose status is unknown every .. seconds. See .
smtpredirector=...
Our smtpredir MX host. See .
soa-serial-offset=...
If your database contains single-digit SOA serials and you need to host .DE domains, this setting can help
placate their 6-digit SOA serial requirements. Suggested value is to set this to 1000000 which adds 1000000 to all SOA Serials
under that offset.
socket-dir=...
Where the controlsocket will live. See .
strict-rfc-axfrs | --strict-rfc-axfrs=yes | --strict-rfc-axfrs=no
Perform strictly RFC conformant AXFRs, which are slow, but needed to placate some old client tools.
urlredirector=...
Where we send hosts to that need to be url redirected. See .
webserver | --webserver=yes | --webserver=no
Start a webserver for monitoring. See .
webserver-address=...
IP Address of webserver to listen on. See .
webserver-password=...
Password required for accessing the webserver. See .
webserver-port=...
Port of webserver to listen on. See .
wildcard-url=...
Check for wildcard URL records.
wildcards=...
Honor wildcards in the database. On by default. Turning this off has performance implications, see .
Index of all internal metricsCounters & variables
A number of counters and variables are set during PDNS operation. These can be queried with the init.d
dump, show and mrtg commands, or viewed with the
webserver.
corrupt-packetsNumber of corrupt packets receivedlatencyAverage number of microseconds a packet spends within PDNSpacketcache-hitNumber of packets which were answered out of the cachepacketcache-missNumber of times a packet could not be answered out of the cachepacketcache-sizeAmount of packets in the packetcacheqsize-aSize of the queue before the transmitting socket.qsize-qNumber of packets waiting for database attentionservfail-packetsAmount of packets that could not be answered due to database problemstcp-answersNumber of answers sent out over TCPtcp-questionsNumber of questions received over TCPtimedout-questionsAmount of packets that were dropped because they had to wait too long internallyudp-answersNumber of answers sent out over UDPudp-questionsNumber of questions received over UDPRing buffers
Besides counters, PDNS also maintains the ringbuffers. A ringbuffer records events, each new event gets a place
in the buffer until it is full. When full, earlier entries get overwritten, hence the name 'ring'.
By counting the entries in the buffer, statistics can be generated. These statistics can currently only be viewed
using the webserver and are in fact not even collected without the webserver running.
The following ringbuffers are available:
Log messages (logmessages)All messages loggedQueries for existing records but for a type we don't have (noerror-queries)Queries for, say, the AAAA record of a domain, when only an A is available.
Queries are listed in the following format: name/type. So an AAA query for pdns.powerdns.com looks like
pdns.powerdns.com/AAAA.Queries for non-existing records within existing domains(nxdomain-queries)If PDNS knows it is authoritative over a domain, and it sees a question for a record in that domain
that does not exist, it is able to send out an authoritative 'no such domain' message. Indicates that hosts are
trying to connect to services really not in your zone.UDP queries received (udp-queries)
All UDP queries seen.
Remote server IP addresses (remotes)
Hosts querying PDNS. Be aware that UDP is anonymous - person A can send queries that appear to be coming from
person B.
Remotes sending corrupt packets (remote-corrupts)
Hosts sending PDNS broken packets, possibly meant to disrupt service. Be aware that UDP is
anonymous - person A can send queries that appear to be coming from person B.
Remotes querying domains for which we are not auth (remote-unauth)
It may happen that there are misconfigured hosts on the internet which are configured to
think that a PDNS installation is in fact a resolving nameserver. These hosts will not
get useful answers from PDNS. This buffer lists hosts sending queries for domains which
PDNS does not know about.
Queries that could not be answered due to backend errors (servfail-queries)
For one reason or another, a backend may be unable to extract answers for a certain domain from
its storage. This may be due to a corrupt database or to inconsistent data. When this happens,
PDNS sends out a 'servfail' packet indicating that it was unable to answer the question. This buffer
shows which queries have been causing servfails.
Queries for domains that we are not authoritative for (unauth-queries)
If a domain is delegated to a PDNS instance, but the backend is not made aware of this fact, questions come
in for which no answer is available, nor is the authority. Use this ringbuffer to spot such queries.
Supported record types and their storage
This chapter lists all record types PDNS supports, and how they are stored in backends. The list is mostly alphabetical but
some types are grouped.
A
The A record contains an IP address. It is stored as a decimal dotted quad string,
for example: '213.244.168.210'.
AAAA
The AAAA record contains an IPv6 address. It is stored as a decimal dotted quad string,
for example: '3ffe:8114:2000:bf0::1'.
CNAME
The CNAME record specifies the canonical name of a record. It is stored plainly. Like all other records, it is not
terminated by a dot. A sample might be 'webserver-01.yourcompany.com'.
HINFO
Hardware Info record, used to specify CPU and operating system. Stored with a single space separating these two,
example: 'i386 Linux'.
MX
The MX record specifies a mail exchanger host for a domain. Each mail exchanger also has a priority or preference.
This should be specified in the separate field dedicated for that purpose, often called 'prio'.
NAPTR
Naming Authority Pointer, RFC 2915. Stored as follows:
'100 50 "s" "z3950+I2L+I2C" "" _z3950._tcp.gatech.edu'.
The fields are: order, preference, flags, service, regex,
replacement. Note that the replacement is not enclosed in quotes, and should not be. The replacement may be omitted, in which
case it is empty. See also RFC 2916 for how to use NAPTR for ENUM (E.164) purposes.
NS
Nameserver record. Specifies nameservers for a domain. Stored plainly: 'ns1.powerdns.com', as always without a terminating dot.
PTR
Reverse pointer, used to specify the host name belonging to an IP or IPv6 address. Name is stored plainly: 'www.powerdns.com'.
As always, no terminating dot.
RP
Responsible Person record, as described in RFC 1183. Stored with a single space between the mailbox name and the more-information
pointer. Example 'peter.powerdns.com peter.people.powerdns.com', to indicate that peter@powerdns.com is responsible and that more
information about peter is available by querying the TXT record of peter.people.powerdns.com.
SOA
The Start of Authority record is one of the most complex available. It specifies a lot about a domain: the name
of the master nameserver ('the primary'), the hostmaster and a set of numbers indicating how the data in this domain
expires and how often it needs to be checked. Further more, it contains a serial number which should rise on each change
of the domain.
The stored format is:
primary hostmaster serial refresh retry expire default_ttl
Besides the primary and the hostmaster, all fields are numerical. PDNS has a set of default values:
The fields have complicated and sometimes controversial meanings. The 'serial' field is special. If left at 0, the default,
PDNS will perform an internal list of the domain to determine highest change_date field of all records within the zone, and use
that as the zone serial number. This means that the serial number is always raised when changes are made to the zone, as long
as the change_date field is being set.
TXT
The TXT field can be used to attach textual data to a domain. Text is stored plainly.
HOWTO & Frequently Asked Questions
This chapter contains a number of FAQs and HOWTOs.
Using and Compiling PowerDNS FAQ
In the course of compiling and using PowerDNS, many questions may arise. Here are some we've heard earlier or questions
we expect people may have. Please read this list before mailing us!
Q: Can I launch multiple backends simultaneously?
A: You can. This might for example be useful to keep an existing BIND configuration around but to store new zones in, say
MySQL. The syntax to use is 'launch=bind,gmysql'.
Q: Which backend should I use? There are so many!
A: If you have no external constraints, the Generic MySQL (gmysql) and Generic PostgreSQL (gpgsql) ones are probably the
most used and complete. By all means do not use the non-generic MySQL backend, which is deprecated and only available for older
installations.
The Oracle backend also has happy users, we know of no deployments of the DB2 backend. The BIND backend is pretty capable
too in fact, but many prefer a relational database.
Q: I try to launch the pgmysqlbackend and it can't find it!
A: You did not read the changelog, nor the README. The 'pgmysql' backend is no more and has been split
into the gmysql and gpgsql backends, with the common code residing within PowerDNS itself.
Q: PowerDNS compiles under OpenBSD, but crashes immediately, now what?
A: Reasons behind this are somewhat unclear but we hear they go away if you use a more recent compiler. Let us know
on pdns-dev@mailman.powerdns.comQ: I'm trying to build from CVS but I get lots of weird errors!
A: Read the 'HACKING' file, it lists the build requirements (mostly autoconf, automake, libtool). In many cases,
it may be easier to build from the source distribution though.
Q: I'm on Solaris 7 and AAAA records do not work
A: Indeed, and this is pretty sad. Either upgrade to Solaris 8 or convince people to write the replacement functions
needed to encode AAAA if the host operating system does not offer them.
Q: When compiling I get errors about 'sstream' and 'ostringstream', or BITSPERCHAR
A: Your gcc is too old. Versions 2.95.2 and older are not supported. Many distributions have improved gcc 2.95.2
with an ostringstream implementation, in which case their 2.95.2 is also supported. We like gcc 3.2.1 best.
Q: Ok, I've installed gcc 3.2.1 but now the gpgsql backend won't link
A: Sadly, the gcc C++ on-disk object format has changed a few times since the 2.95 days. This means that
gcc 3.2.1 cannot link against libpq++.so compiled with 2.95. The trick is to recompile PostgreSQL with 3.2.1
too and have it install in a separate location. Then reconfigure the pdns compile to look there, with
./configure --with-pgsql-lib=/opt/postgresql-with-3.2.1/libQ: I've installed PostgreSQL 7.3 but it has no libpq++.so
A: As of 7.3, libpq++ has been split out of the main PostgreSQL distribution. See here.
It would in fact be a great idea to move the gpgsql backend to the C interface instead of the C++ one. On Debian 'Sid', libpq++.so
hides in the libpqpp-dev package.
Backend developer HOWTO
Writing backends without access to the full PDNS source means that you need to write code that can be loaded by PDNS at runtime.
This in turn means that you need to use the same compiler that we do. For linux, this is currently GCC 3.0.4, although any 3.0.x
compiler is probably fine. In tests, even 3.1 works.
For FreeBSD we use GCC 2.95.2.
Furthermore, your pdns_server executable must be dynamically linked. The default .rpm PDNS contains a static binary so you need to retrieve the
dynamic rpm or the dynamic tar.gz or the Debian unstable ('Woody') deb. FreeBSD dynamic releases are forthcoming.
Q: Will PDNS drivers work with other PDNS versions than they were compiled for?
A: 'Probably'. We make no guarantees. Efforts have been made to keep the interface between the backend and PDNS as thin
as possible. For example, a backend compiled with the 1.99.11 backend development kit works with 1.99.10. But don't count on it.
We will notify when we think an incompatible API change has occured but you are best off recompiling your driver for each
new PDNS release.
Q: What is in that DNSPacket * pointer passed to lookup!
A: For reasons outlined above, you should treat that pointer as opaque and only access it via the getRemote()
functions made available and documented above. The DNSPacket class changes a lot and this level of indirection allows for greater
changes to be made without changing the API to the backend coder.
Q: How is the PowerDNS Open Source Backend Development Kit licensed?
A: MIT X11, a very liberal license permitting basically everything.
Q: Can I release the backend I wrote?
A: Please do! If you tell us about it we will list you on our page.
Q: Can I sell backends I wrote?
A: You can. Again, if you tell us about them we will list your backend on the site. You can keep the source of your backend
secret if you want, or you can share it with the world under any license of your chosing.
Q: Will PowerDNS use my code in the PDNS distribution?
A: If your license permits it and we like your backend, we sure will. If your license does not permit it but we like your
backend anyway we may contact you.
Q: My backend compiles but when I try to load it, it says 'undefined symbol: _Z13BackendMakersv'
A: Your pdns_server binary is static and cannot load a backend driver at runtime. Get a dynamic version of pdns, or complain
to pdns@powerdns.com if one isn't available. To check what kind of binary you have, execute 'file $(which pdns_server)'.
Q: My backend compiles but when I try to load it, it says 'undefined symbol: BackendMakers__Fv'
A: You compiled with the wrong GCC. Use GCC 3.x for Linux, 2.95.x for FreeBSD. You may want to change g++ to g++-3.0 in the Makefile,
or change your path so that 3.x is used.
Q: I downloaded a dynamic copy of pdns_server but it doesn't run, even without my backend
A: Run 'ldd' on the pdns_server binary and figure out what libraries you are missing. Most likely you need to install gcc 3.0 libraries,
RedHat 7.1 and 7.2 have packages available, Debian installs these by default if you use the 'unstable deb' of PDNS.
Q: What I want can't be done from a backend - I need the whole PDNS source
A: If you require the source, please contact us (pdns@powerdns.com). All commercial licensees receive the source,
for others we may grant exceptions.
Q: What is this 'AhuException' I keep reading about?
A: This name has historical reasons and has no significance.
Q: I need a backend but I can't write it, can you help?
A: Yes, we also do custom development. Contact us at pdns@powerdns.com.
About PowerDNS.COM BV, 'the company'
As of 25 November 2002, the PowerDNS nameserver and its modules are open source. This has led to a lot of questions on the future
of both PowerDNS, the company and the products. This FAQ attempts to address these questions.
Q: Is PowerDNS 2.9 really open source? What license?
A: PowerDNS 2.9 is licensed under the GNU General Public License version two, the same license that covers the Linux kernel.
Q: Is the open source version crippled?
A: It is not. Not a single byte has been omitted.
Q: Is the nameserver abandoned?
A: Far from it. In fact, we expect development to speed up now that we have joined the open source community.
Q: Why is the nameserver now open source?
A: In the current economic climate and also the way the Internet is built up right now, selling software is very hard. Most potential
customers had never before bought a piece of software for their UNIX internet setup. Even though we know (from the recent survey) that
nameserver operators love PowerDNS, their suggested price for it is in the $100 range.
For us, it makes far more sense to open source PowerDNS than to ask $100 for it. It is expected that open sourcing PowerDNS will lead
to far higher adoption rates. We hope that PowerDNS will soon be included in major Linux and UNIX distributions.
Q: How does PowerDNS.COM BV expect to make money now that the nameserver is free?
A: In fact, we don't expect to in the near future. We also don't have a lot of expenses, basically
some hosting and a few domain names.
However, we are available for consulting work, for example to help a large registrar or registry migrate to PowerDNS, or to help
integrate our software in existing provisioning systems.
Furthermore, non-GPL licenses are available for those needing to do closed source modifications, or for customers
uncomfortable with the GPL. This is much like what MySQL AB is doing now.
In fact, their strategy is a lot like ours in general.
Q: Can I buy support contracts for PowerDNS?
Sure, to do so, please contact us at sales@powerdns.comQ: Will you accept patches? We've added a feature
Probably - in general, it is best to discuss your intentions and needs on the pdns-dev@mailman.powerdns.com (subscribe)
mailinglist
before doing the work. We may have suggestions or guidelines on how you should implement the feature.
Q: PowerDNS doesn't work on my platform, will you port it?Q: PowerDNS doesn't have feature I need, will you add it?
Be sure to ask on the pdns-dev@mailman.powerdns.com (subscribe) mailinglist. You can even hire us to do work on PowerDNS
if plain asking is not persuasive enough. This might be the case if we don't currently have time for your feature, but you
need it quickly anyhow, and are not in a position to submit a patch implementing it.
Q: Will PowerDNS Express be open sourced?
PowerMail?
Perhaps, we're not yet sure. PowerMail most probably.
Q: We are a Linux/Unix vendor, can we include PowerDNS?
A: Please do. In fact, we'd be very happy to work with you to make this happen. Contact ahu@ds9a.nl
if you have specific upstream needs.
Backends in detail
This appendix lists several of the available backends in more detail
PipeBackend
The PipeBackend allows for easy dynamic resolution based on a 'Coprocess' which can be written in any
programming language that can read a question on standard input and answer on standard output.
The Pipe Backend currently does not function under FreeBSD 4.x and 5.x, probably due to unfavorable interactions between
its threading implementation and the fork system call.
Interestingly, the Linux PowerDNS binary running under the Linuxulator on FreeBSD does work.
To configure, the following settings are available:
pipe-command
Command to launch as backend. Mandatory.
pipe-timeout
Number of milliseconds to wait for an answer from the backend. If this time is ever exceeded, the backend
is declared dead and a new process is spawned. Available since 2.7.
pipe-regex
If set, only questions matching this regular expression are even sent to the backend. This makes sure that
most of PowerDNS does not slow down if you you reploy a slow backend. A query for the A record of 'www.powerdns.com'
would be presented to the regex as 'www.powerdns.com;A'. A matching regex would be '^www.powerdns.com;.*$'.
To match only ANY and A queries for www.powerdns.com, use '^www.powerdns.com;(A|ANY)$'. Available since 2.8.
PipeBackend protocol
Questions come in over a file descriptor, by default standard input. Answers
are sent out over another file descriptor, standard output by default.
Handshake
PowerDNS sends out 'HELO\t1', indicating that it wants to speak the
protocol as defined in this document, version 1.
A PowerDNS CoProcess must then send out a banner, prefixed by 'OK\t',
indicating it launched successfully. If it does not support the indicated
version, it should respond with FAIL, but not exit. Suggested behaviour is
to try and read a further line, and wait to be terminated.
Questions
Questions come in three forms and are prefixed by a tag indicating the kind:
Q
Regular queries
AXFR
List requests, which mean that an entire zone should be listed
PING
Check if the coprocess is functioning
The question format:
type qname qclass qtype id ip-address
Fields are tab separated, and terminated with a single \n.
Type is the tag above, qname is the domain the question is about. qclass is
always 'IN' currently, denoting an INternet question. qtype is the kind of
information desired, the record type, like A, CNAME or AAAA. id can be
specified to help your backend find an answer if the id is already known
from an earlier query. You can ignore it.
ip-address is the ip-address of the nameserver asking the question.
Answers
Each answer starts with a tag, possibly followed by a TAB and more data.
DATA
Indicating a successful line of DATA
END
Indicating the end of an answer - no further data
FAIL
Indicating a lookup failure. Also serves as 'END'. No further data.
LOG
For specifying things that should be logged. Can only be sent after
a query and before an END line. After the tab, the message to be
logged
So letting it be known that there is no data consists if sending 'END'
without anything else.
The answer format:
DATA qname qclass qtype ttl id content
'content' is as specified in .
A sample dialogue may look like this:
Q www.ds9a.nl IN CNAME -1 213.244.168.210
DATA www.ds9a.nl IN CNAME 3600 1 ws1.ds9a.nl
Q ws1.ds9a.nl IN CNAME -1 213.244.168.210
END
Q wd1.ds9a.nl IN A -1 213.244.168.210
DATA ws1.ds9a.nl IN A 3600 1 1.2.3.4
DATA ws1.ds9a.nl IN A 3600 1 1.2.3.5
DATA ws1.ds9a.nl IN A 3600 1 1.2.3.6
END
This would correspond to a remote webserver 213.244.168.210 wanting to
resolve the IP address of www.ds9a.nl, and PowerDNS traversing the CNAMEs to
find the IP addresses of ws1.ds9a.nl
Another dialogue might be:
Q ds9a.nl IN SOA -1 213.244.168.210
DATA ds9a.nl IN SOA 86400 1 ahu.ds9a.nl ...
END
AXFR 1
DATA ds9a.nl IN SOA 86400 1 ahu.ds9a.nl ...
DATA ds9a.nl IN NS 86400 1 ns1.ds9a.nl
DATA ds9a.nl IN NS 86400 1 ns2.ds9a.nl
DATA ns1.ds9a.nl IN A 86400 1 213.244.168.210
DATA ns2.ds9a.nl IN A 86400 1 63.123.33.135
.
.
END
This is a typical zone transfer.
Sample perl backend
#!/usr/bin/perl -w
# sample PowerDNS Coprocess backend
#
use strict;
$|=1; # no buffering
my $line=<>;
chomp($line);
unless($line eq "HELO\t1") {
print "FAIL\n";
print STDERR "Recevied '$line'\n";
<>;
exit;
}
print "OK Sample backend firing up\n"; # print our banner
while(<>)
{
print STDERR "$$ Received: $_";
chomp();
my @arr=split(/\t/);
if(@arr<6) {
print "LOG PowerDNS sent unparseable line\n";
print "FAIL\n";
next;
}
my ($type,$qname,$qclass,$qtype,$id,$ip)=split(/\t/);
if(($qtype eq "A" || $qtype eq "ANY") && $qname eq "webserver.example.com") {
print STDERR "$$ Sent A records\n";
print "DATA $qname $qclass A 3600 -1 1.2.3.4\n";
print "DATA $qname $qclass A 3600 -1 1.2.3.5\n";
print "DATA $qname $qclass A 3600 -1 1.2.3.6\n";
}
elsif(($qtype eq "CNAME" || $qtype eq "ANY") && $qname eq "www.example.com") {
print STDERR "$$ Sent CNAME records\n";
print "DATA $qname $qclass CNAME 3600 -1 webserver.example.com\n";
}
elsif($qtype eq "MBOXFW") {
print STDERR "$$ Sent MBOXFW records\n";
print "DATA $qname $qclass MBOXFW 3600 -1 powerdns\@example.com\n";
}
print STDERR "$$ End of data\n";
print "END\n";
}
MySQL backend
This backend is deprecated! Use the Generic MySQL backend which is better in all respects.
It does support master/slave operation, this backend does not. See .
So stop reading here unless you already have a database filled with 'mysql' records.
MySQL backend capabilitiesNativeYesMasterNoSlaveNoSuperslaveNoAutoserialYesCaseInsensitiveModule namemysqlLauch namemysql
The MySQL Backend as present in PDNS is fixed - it requires a certain database schema to function. This schema corresponds to this create statement:
CREATE TABLE records (
id int(11) NOT NULL auto_increment,
domain_id int(11) default NULL,
name varchar(255) default NULL,
type varchar(6) default NULL,
content varchar(255) default NULL,
ttl int(11) default NULL,
prio int(11) default NULL,
change_date int(11) default NULL,
PRIMARY KEY (id),
KEY name_index(name),
KEY nametype_index(name,type),
KEY domainid_index(domain_id)
);
Every domain should have a unique domain_id, which should remain identical for all records in a domain. Records with a domain_id that
differs from that in the domain SOA record will not appear in a zone transfer.
The change_date may optionally
be updated to the time_t (the number of seconds since midnight UTC at the start of 1970), and is in that case used to auto calculate the
SOA serial number in case that is unspecified.
Configuration settings
WARNING! Make sure that you can actually resolve the hostname of your database without accessing the database! It is advised to supply
an IP address here to prevent chicken/egg problems!
mysql-dbname
Database name to connect to
mysql-host
Database host to connect to
mysql-password
Password to connect with
mysql-socket
MySQL socket to use for connecting
mysql-table
MySQL table name. Defaults to 'records'.
mysql-user
MySQL user to connect as
Notes
It has been observed that InnoDB tables outperform the default MyISAM tables by a large margin. Furthermore, the default
number of backends (3) should be raised to 10 or 15 for busy servers.
Random Backend
Random Backend capabilitiesNativeYesMasterNoSlaveNoSuperslaveNoAutoserialNoCaseDependsModule namebuilt inLauch namerandom
This is a very silly backend which is discussed in as a demonstration on
how to write a PowerDNS backend.
This backend knows about only one hostname, and only about its IP address at that. With every query,
a new random IP address is generated.
It only makes sense to load the random backend in combination with a regular backend. This can be done by prepending
it to the launch= instruction, such as launch=random,gmysql.
Variables:
random-hostname
Hostname for which to supply a random IP address.
MySQL PDNS backend
MySQL backend capabilitiesNativeYesMasterNoSlaveNoSuperslaveNoAutoserialYesCaseInsensitiveModule namepdnsLauch namepdns
This is the driver that corresponds to the set of XML-RPC tools available from PowerDNS. For database schemas, see there.
It takes a number of parameters:
pdns-dbname
Database name to connect to
pdns-host
Database host to connect to
pdns-password
Password to connect with
pdns-socket
MySQL socket to use for connecting
pdns-user
MySQL user to connect as
Notes
It has been observed that InnoDB tables outperform the default MyISAM tables by a large margin. Furthermore, the default
number of backends (3) should be raised to 10 or 15 for busy servers.
Generic MySQL and PgSQL backends
Generic PgSQL and MySQL backend capabilitiesNativeYes - but PostgreSQL does not replicateMasterYesSlaveYesSuperslaveYesAutoserialYesCaseAll lowerModule name < 2.9.3pgmysqlModule name > 2.9.2gmysql and gpgsqlLauch namegmysql and gpgsql2 and gpgsql
PostgreSQL and MySQL backend with easily configurable SQL statements, allowing you to graft PDNS on any PostgreSQL or MySQL database of your choosing.
Because all database schemas will be different, a generic backend is needed to cover all needs.
The template queries are expanded using the C function 'snprintf' which implies that substitutions are performed on the basis of %-place holders.
To place a a % in a query which will not be substituted, use %%. Make sure to fill out the search key, often called 'name' in lower case!
There are in fact two backends, one for PostgreSQL and one for MySQL but they accept the same settings and use almost exactly the same database schema.
MySQL specifics
If using MySQL with 'slave' support enabled in PowerDNS you must run MySQL with a table engine that supports transactions.
In practice, great results are achieved with the 'InnoDB' tables. PowerDNS will silently function with non-transaction aware MySQLs but at one point
this is going to harm your database, for example when an incoming zone transfer fails.
The default setup conforms to the following schema:
create table domains (
id INT auto_increment,
name VARCHAR(255) NOT NULL,
master VARCHAR(20) DEFAULT NULL,
last_check INT DEFAULT NULL,
type VARCHAR(6) NOT NULL,
notified_serial INT DEFAULT NULL,
account VARCHAR(40) DEFAULT NULL,
primary key (id)
)type=InnoDB;
CREATE UNIQUE INDEX name_index ON domains(name);
CREATE TABLE records (
id INT auto_increment,
domain_id INT DEFAULT NULL,
name VARCHAR(255) DEFAULT NULL,
type VARCHAR(6) DEFAULT NULL,
content VARCHAR(255) DEFAULT NULL,
ttl INT DEFAULT NULL,
prio INT DEFAULT NULL,
change_date INT DEFAULT NULL,
primary key(id)
)type=InnoDB;
CREATE INDEX rec_name_index ON records(name);
CREATE INDEX nametype_index ON records(name,type);
CREATE INDEX domain_id ON records(domain_id);
create table supermasters (
ip VARCHAR(25) NOT NULL,
nameserver VARCHAR(255) NOT NULL,
account VARCHAR(40) DEFAULT NULL
);
GRANT SELECT ON supermasters TO pdns;
GRANT ALL ON domains TO pdns;
GRANT ALL ON records TO pdns;
This schema contains all elements needed for master, slave and superslave operation. Depending on which features will be used, the 'GRANT' statements
can be trimmed to make sure PDNS cannot subvert the contents of your database.
Zone2sql with the --gmysql flag also assumes this layout is in place.
PostgresSQL specifics
The default setup conforms to the following schema:
create table domains (
id SERIAL PRIMARY KEY,
name VARCHAR(255) NOT NULL,
master VARCHAR(20) DEFAULT NULL,
last_check INT DEFAULT NULL,
type VARCHAR(6) NOT NULL,
notified_serial INT DEFAULT NULL,
account VARCHAR(40) DEFAULT NULL
);
CREATE UNIQUE INDEX name_index ON domains(name);
CREATE TABLE records (
id SERIAL PRIMARY KEY,
domain_id INT DEFAULT NULL,
name VARCHAR(255) DEFAULT NULL,
type VARCHAR(6) DEFAULT NULL,
content VARCHAR(255) DEFAULT NULL,
ttl INT DEFAULT NULL,
prio INT DEFAULT NULL,
change_date INT DEFAULT NULL,
CONSTRAINT domain_exists
FOREIGN KEY(domain_id) REFERENCES domains(id)
ON DELETE CASCADE
);
CREATE INDEX rec_name_index ON records(name);
CREATE INDEX nametype_index ON records(name,type);
CREATE INDEX domain_id ON records(domain_id);
create table supermasters (
ip VARCHAR(25) NOT NULL,
nameserver VARCHAR(255) NOT NULL,
account VARCHAR(40) DEFAULT NULL
);
GRANT SELECT ON supermasters TO pdns;
GRANT ALL ON domains TO pdns;
GRANT ALL ON domains_id_seq TO pdns;
GRANT ALL ON records TO pdns;
GRANT ALL ON records_id_seq TO pdns;
This schema contains all elements needed for master, slave and superslave operation. Depending on which features will be used, the 'GRANT' statements
can be trimmed to make sure PDNS cannot subvert the contents of your database.
Zone2sql with the --gpgsql flag also assumes this layout is in place.
Basic functionality
4 queries are needed for regular lookups, 4 for 'fancy records' which are disabled by default and 1 is needed for zone transfers.
The 4+4 regular queries must return the following 6 fields, in this exact order:
content
This is the 'right hand side' of a DNS record. For an A record, this is the IP address for example.
ttl
TTL of this record, in seconds. Must be a real value, no checking is performed.
prio
For MX records, this should be the priority of the mail exchanger specified.
qtype
The ASCII representation of the qtype of this record. Examples are 'A', 'MX', 'SOA', 'AAAA'. Make sure that this
field returns an exact answer - PDNS won't recognise 'A ' as 'A'. This can be achieved by using a VARCHAR instead
of a CHAR.
domain_id
Each domain must have a unique domain_id. No two domains may share a domain_id, all records in a domain should have the same. A number.
name
Actual name of a record. Must not end in a '.' and be fully qualified - it is not relative to the name of the domain!
Please note that the names of the fields are not relevant, but the order is!
As said earlier, there are 8 SQL queries for regular lookups. To configure them, set 'gmysql-basic-query' or 'gpgsql-basic-query', depending on your
choice of backend. If so called 'MBOXFW' fancy records are not used, four queries remain:
basic-query
Default: select content,ttl,prio,type,domain_id,name from records where qtype='%s' and name='%s'
This is the most used query, needed for doing 1:1 lookups of qtype/name values. First %s is replaced by the ASCII representation
of the qtype of the question, the second by the name.
id-query
Default: select content,ttl,prio,type,domain_id,name from records where qtype='%s' and name='%s' and domain_id=%d
Used for doing lookups within a domain. First %s is replaced by the qtype, the %d which should appear after the %s by the numeric
domain_id.
any-query
For doing ANY queries. Also used internally.
Default: select content,ttl,prio,type,domain_id,name from records where name='%s'
The %s is replaced by the qname of the question.
any-id-query
For doing ANY queries within a domain. Also used internally.
Default: select content,ttl,prio,type,domain_id,name from records where name='%s' and domain_id=%d
The %s is replaced by the name of the domain, the %d by the numerical domain id.
The last query is for listing the entire contents of a zone. This is needed when performing a zone transfer, but sometimes also internally:
list-query
To list an entire zone.
Default: select content,ttl,prio,type,domain_id,name from records where domain_id=%dMaster/slave queries
Most installations will have zero need to change the following settings, but should the need arise, here they are:
master-zone-query
Called to determine the master of a zone.
Default: select master from domains where name='%s' and type='SLAVE'info-zone-query
Called to retrieve (nearly) all information for a domain:
Default: select id,name,master,last_check,notified_serial,type from domains where name='%s'info-all-slaves-query
Called to retrieve all slave domains
Default: select id,name,master,last_check,type from domains where type='SLAVE'supermaster-query
Called to determine if a certain host is a supermaster for a certain domain naeme.
Default:
select account from supermasters where ip='%s' and nameserver='%s'");
insert-slave-query
Called to add a domain as slave after a supermaster notification.
Default:
insert into domains (type,name,master,account) values('SLAVE','%s','%s','%s')
insert-record-query
Called during incoming AXFR.
Default:
insert into records (content,ttl,prio,type,domain_id,name) values ('%s',%d,%d,'%s',%d,'%s')
update-serial-query
Called to update the last notified serial of a master domain.
Default:
update domains set notified_serial=%d where id=%d
update-lastcheck-query
Called to update the last time a slave domain was checked for freshness.
Default:
update domains set notified_serial=%d where id=%d
info-all-master-query
Called to get data on all domains for which the server is master.
Default:
select id,name,master,last_check,notified_serial,type from domains where type='MASTER'
delete-zone-query
Called to delete all records of a zone. Used before an incoming AXFR.
Default:
delete from records where domain_id=%d
Fancy records
If PDNS is used with so called 'Fancy Records', the 'MBOXFW' record exists which specifies an email address forwarding instruction,
wildcard queries are sometimes needed. This is not enabled by default. A wildcard query is
an internal concept - it has no relation to *.domain-type lookups. You can safely leave these queries blank.
wildcard-query
Can be left blank. See above for an explanation.
Default: select content,ttl,prio,type,domain_id,name from records where qtype='%s' and name like '%s'wildcard-id-query
Can be left blank. See above for an explanation.
Default: select content,ttl,prio,type,domain_id,name from records where qtype='%s' and name like '%s' and domain_id=%d
Used for doing lookups within a domain.
wildcard-any-query
For doing wildcard ANY queries.
Default: select content,ttl,prio,type,domain_id,name from records where name like '%s'wildcard-any-id-query
For doing wildcard ANY queries within a domain.
Default: select content,ttl,prio,type,domain_id,name from records where name like '%s' and domain_id=%dSettings and specifying queries
The queries above are specified in pdns.conf. For example, the basic-query would appear as:
gpgsql-basic-query=select content,ttl,prio,type,domain_id,name from records where qtype='%s' and name='%s'
When using the Generic PostgreSQL backend, they appear as above. When using the generic MySQL backend, change the
"gpgsql-" prefix to "gmysql-".
Queries can span multiple lines, like this:
gpgsql-basic-query=select content,ttl,prio,type,domain_id,name from records \
where qtype='%s' and name='%s'
Do not wrap statements in quotes as this will not work.
Besides the query related settings, the following configuration options are available:
gpgsql-dbname
Database name to connect to
gpgsql-host
Database host to connect to. WARNING: When specified as a hostname a chicken/egg situation might arise where the database
is needed to resolve the IP address of the database. It is best to supply an IP address of the database here.
gpgsql-password
Password to connect with
gpgsql-user
PgSQL user to connect as
Native operation
For native operation, either drop the FOREIGN KEY on the domain_id field, or (recommended), make sure
the domains table is filled properly. To add a domain, issue the following:
insert into domains (name,type) values ('powerdns.com','NATIVE');
The records table can now be filled by with the domain_id set to the id of the domains table row just inserted.
Slave operation
The PostgreSQL backend is fully slave capable. To become a slave of the 'powerdns.com' domain, execute this:
insert into domains (name,master,type) values ('powerdns.com','213.244.168.217','SLAVE');
And wait a while for PDNS to pick up the addition - which happens within one minute. There is no need to inform PDNS that a new domain
was added.
Typical output is:
Apr 09 13:34:29 All slave domains are fresh
Apr 09 13:35:29 1 slave domain needs checking
Apr 09 13:35:29 Domain powerdns.com is stale, master serial 1, our serial 0
Apr 09 13:35:30 [gPgSQLBackend] Connected to database
Apr 09 13:35:30 AXFR started for 'powerdns.com'
Apr 09 13:35:30 AXFR done for 'powerdns.com'
Apr 09 13:35:30 [gPgSQLBackend] Closing connection
From now on, PDNS is authoritative for the 'powerdns.com' zone and will respond accordingly for queries within that zone.
Periodically, PDNS schedules checks to see if domains are still fresh. The default slave-cycle-interval is 60 seconds, large installations may need to raise this value. Once a domain has been checked, it will not be checked before its SOA refresh timer has expired. Domains whose status is unknown get checked every 60 seconds by default.
Superslave operation
To configure a supermaster with IP address 10.0.0.11 which lists this installation as 'autoslave.powerdns.com', issue the following:
insert into supermasters ('10.0.0.11','autoslave.powerdns.com','internal');
From now on, valid notifies from 10.0.0.11 that list a NS record containing 'autoslave.powerdns.com' will lead to the
provisioning of a slave domain under the account 'internal'. See for details.
Master operation
The PostgreSQL backend is fully master capable with automatic discovery of serial changes. Raising the serial number of a domain
suffices to trigger PDNS to send out notifications. To configure a domain for master operation instead of the default native replication,
issue:
insert into domains (name,type) values ('powerdns.com','MASTER');
Make sure that the assigned id in the domains table matches the domain_id field in the records table!
Generic Oracle backend
Oracle backend with easily configurable SQL statements, allowing you to graft PDNS on any Oracle database of your choosing.
PowerDNS is currently ascertaining if this backend can be distributed in binary form without violating Oracle licensing. In the meantime,
the source code to the Oracle backend is available in the pdns distribution.
The following configuration settings are available:
oracle-debug-queries
Output all queries to disk for debugging purposes.
oracle-time-queries
Output all queries to disk for timing purposes.
oracle-uppercase-database
Change all domain names to uppercase before querying database.
oracle-database
Oracle database name to connect to.
oracle-home
PDNS can set the ORACLE_HOME environment variable from within the executable, allowing execution of
the daemon from init.d scripts where ORACLE_HOME may not yet be set.
oracle-sid
PDNS can set the ORACLE_SID environment variable from within the executable, allowing execution of
the daemon from init.d scripts where ORACLE_SID may not yet be set.
oracle-username
Oracle username to connect as.
oracle-password
Oracle password to connect with.
The generic Oracle backend can be configured to use user-specified queries. The following are the default queries
and their names:
oracle-forward-query
select content, TimeToLive, Priority, type, ZoneId, nvl(ChangeDate,0) from Records where name = :name and type = :type
oracle-forward-query-by-zone
select content, TimeToLive, Priority, type, ZoneId, nvl(ChangeDate,0) from records where name = :name and type = :type and ZoneId = :id
oracle-forward-any-query
select content, TimeToLive, Priority, type, ZoneId, nvl(ChangeDate,0) from records where name = :name
oracle-list-query
select content, TimeToLive, Priority, type, ZoneId, nvl(ChangeDate, 0), name from records where ZoneId = :id
Setting up Oracle for use with PowerDNS
To setup a database that corresponds to these default queries, issue the following as Oracle user sys:
create user powerdns identified by YOURPASSWORD;
grant connect to powerdns;
create tablespace powerdns datafile '/opt/oracle/oradata/oracle/powerdns.dbf'
size 256M extent management local autoallocate;
alter user powerdns quota unlimited on powerdns;
As user 'powerdns' continue with:
create table Domains (
ID number(11) NOT NULL,
NAME VARCHAR(255) NOT NULL,
MASTER VARCHAR(20) DEFAULT NULL,
LAST_CHECK INT DEFAULT NULL,
TYPE VARCHAR(6) NOT NULL,
NOTIFIED_SERIAL INT DEFAULT NULL,
ACCOUNT VARCHAR(40) DEFAULT NULL,
primary key (ID)
)tablespace POWERDNS;
create index DOMAINS$NAME on Domains (NAME) tablespace POWERDNS;
create sequence DOMAINS_ID_SEQUENCE;
create table Records
(
ID number(11) NOT NULL,
ZoneID number(11) default NULL REFERENCES Domains(ID) ON DELETE CASCADE,
NAME varchar2(255) default NULL,
TYPE varchar2(6) default NULL,
CONTENT varchar2(255) default NULL,
TimeToLive number(11) default NULL,
Priority number(11) default NULL,
CreateDate number(11) default NULL,
ChangeDate number(11) default NULL,
primary key (ID)
)tablespace POWERDNS;
create index RECORDS$NAME on RECORDS (NAME) tablespace POWERDNS;
create sequence RECORDS_ID_SEQUENCE;
To insert records, either use zone2sql with the --oracle setting, or execute sql
along the lines of:
insert into domains (id,name,type) values (domains_id_sequence.nextval,'netherlabs.nl','NATIVE');
insert into Records (id,ZoneId, name,type,content,TimeToLive,Priority) select RECORDS_ID_SEQUENCE.nextval,id ,'netherlabs.nl', 'SOA', 'ahu.casema.net. hostmaster.ds9a.nl. 2000081401 28800 7200 604800 86400', 3600, 0 from Domains where name='netherlabs.nl';
insert into Records (id,ZoneId, name,type,content,TimeToLive,Priority) select RECORDS_ID_SEQUENCE.nextval,id ,'netherlabs.nl', 'NS', 'ahu.casema.net', 3600, 0 from Domains where name='netherlabs.nl';
insert into Records (id,ZoneId, name,type,content,TimeToLive,Priority) select RECORDS_ID_SEQUENCE.nextval,id ,'netherlabs.nl', 'NS', 'ns1.pine.nl', 3600, 0 from Domains where name='netherlabs.nl';
insert into Records (id,ZoneId, name,type,content,TimeToLive,Priority) select RECORDS_ID_SEQUENCE.nextval,id ,'netherlabs.nl', 'NS', 'ns2.pine.nl', 3600, 0 from Domains where name='netherlabs.nl';
insert into Records (id,ZoneId, name,type,content,TimeToLive,Priority) select RECORDS_ID_SEQUENCE.nextval,id ,'netherlabs.nl', 'A', '213.244.168.210', 3600, 0 from Domains where name='netherlabs.nl';
insert into Records (id,ZoneId, name,type,content,TimeToLive,Priority) select RECORDS_ID_SEQUENCE.nextval,id ,'netherlabs.nl', 'MX', 'outpost.ds9a.nl', 3600, 10 from Domains where name='netherlabs.nl';
For performance reasons it is best to specify --transactions too!
DB2 backend
PowerDNS is currently ascertaining if this backend can be distributed in binary form without violating IBM DB2 licensing.
The DB2 backend executes the following queries:
Forward Query
select Content, TimeToLive, Priority, Type, ZoneId, 0 as ChangeDate, Name from Records where Name = ? and type = ?
Forward By Zone Query
select Content, TimeToLive, Priority, Type, ZoneId, 0 as ChangeDate, Name from Records where Name = ? and Type = ? and ZoneId = ?
Forward Any Query
select Content, TimeToLive, Priority, Type, ZoneId, 0 as ChangeDate, Name from Records where Name = ?
List Query
select Content, TimeToLive, Priority, Type, ZoneId, 0 as ChangeDate, Name from Records where ZoneId = ?
Configuration settings:
db2-server
Server name to connect to. Defaults to 'powerdns'. Make sure that your nameserver is not needed to resolve an IP address needed to connect as
this might lead to a chicken/egg situation.
db2-user
Username to connect as. Defaults to 'powerdns'.
db2-password
Password to connect with. Defaults to 'powerdns'.
Bind zone file backend
Bind zone file backend capabilitiesNativeYesMasterYesSlaveYesSuperslaveNoAutoserialNoModule namenone (built in)Launchbind
The BindBackend started life as a demonstration of the versatility of PDNS but quickly gained in importance when there appeared to be demand
for a Bind 'workalike'.
The BindBackend parses a Bind-style named.conf and extracts information about zones from it. It makes no attempt to honour other configuration flags,
which you should configure (when available) using the PDNS native configuration.
--help=bind
Outputs all known parameters related to the bindbackend
bind-example-zones
Loads the 'example.com' zone which can be queried to determine if PowerDNS is functioning without configuring
database backends.
bind-config=
Location of the Bind configuration file to parse.
bind-check-interval=
How often to check for zone changes. See 'Operation' section.
bind-enable-huffman
Enable Huffman compression on zone data. Currently saves around 20% of memory actually used, but slows down operation
somewhat.
Operation
On launch, the BindBackend first parses the named.conf to determine which zones need to be loaded. These will then be parsed
and made available for serving, as they are parsed. So a named.conf with 100.000 zones may take 20 seconds to load, but after 10 seconds,
50.000 zones will already be available. While a domain is being loaded, it is not yet available, to prevent incomplete answers.
Reloading is currently done only when a request for a zone comes in, and then only after bind-check-interval seconds have passed
after the last check. If a change occurred, access to the zone is disabled, the file is reloaded, access is restored, and the question is answered.
For regular zones, reloading is fast enough to answer the question which lead to the reload within the DNS timeout.
If bind-check-interval is specified as zero, no checks will be performed until the pdns_control reload
is given.
Pdns_control commandsbind-domain-status domain [domain]
Output status of domain or domains. Can be one of 'seen in named.conf, not parsed', 'parsed successfully at <time;>' or
'error parsing at line ... at <time>'.
bind-list-rejects
Lists all zones that have problems, and what those problems are.
bind-reload-now domain
Reloads a zone from disk NOW, reporting back results.
Performance
The BindBackend does not benefit from the packet cache as it is fast enough on its own. Furthermore, on most systems, there will
be no benefit in using multiple CPUs for the packetcache, so a noticeable speedup can be attained by specifying
distributor-threads=1 in pdns.conf.
Master/slave configurationMaster
Works as expected. At startup, no notification storm is performed as this is generally not useful. Perhaps in the future the Bind Backend
will attempt to store zone metadata in the zone, allowing it to determine if a zone has changed its serial since the last time
notifications were sent out.
Changes which are discovered when reloading zones do lead to notifications however.
Slave
Also works as expected. The Bind backend expects to be able to write to a directory where a slave domain lives. The incoming zone is stored
as 'zonename.RANDOM' and atomically renamed if it is retrieved successfully, and parsed only then.
In the future, this may be improved so the old zone remains available should parsing fail.
Commandspdns_control offers commands to communicate instructions to PowerDNS. These are detailed here.
rediscover
Reread the bind configuration file (named.conf). If parsing fails, the old configuration
remains in force and pdns_control reports the error. Any newly discovered domains are read, discarded domains
are removed from memory.
Except that with 2.9.3, they are not removed from memory.
bind-reload
All zones with a changed timestamp are reloaded at the next incoming query for them.
ODBC backend
The ODBC backend can retrieve zone information from any source that has a ODBC driver available.
This backend is only available on PowerDNS for Windows.
The ODBC backend needs data in a fixed schema which is the same as the data needed by the MySQL backend. The create statement
will resemble this:
CREATE TABLE records (
id int(11) NOT NULL auto_increment,
domain_id int(11) default NULL,
name varchar(255) default NULL,
type varchar(6) default NULL,
content varchar(255) default NULL,
ttl int(11) default NULL,
prio int(11) default NULL,
change_date int(11) default NULL,
PRIMARY KEY (id),
KEY name_index(name),
KEY nametype_index(name,type),
KEY domainid_index(domain_id)
);
To use the ODBC backend an ODBC source has to be created, to do this see the section Installing PowerDNS on Microsoft Windows, .
The following configuration settings are available:
odbc-datasource
Specifies the name of the data source to use.
odbc-user
Specifies the username that has to be used to log into the datasource.
odbc-pass
Specifies the user's password.
odbc-table
Specifies the name of the table containing the zone information.
The ODBC backend has been tested with Microsoft Access, MySQL (via MyODBC) and Microsoft SQLServer. As the SQL statements used are very basic,
it is expected to work with many ODBC drivers.
XDB Backend
Special purpose backend for grandiose performance. Can talk to Tridge's Trivial Database, or to regular *db tables on disk. Currently only sparsely
documented. Very useful if you need to do >50.000 queries/second, which we actually measured on the .ORG zone.
More documentation will follow.
PDNS internals
PDNS is normally launched by the init.d script but is actually a binary called pdns_server. This
file is started by the start and monitor commands to the init.d script. Other commands
are implemented using the controlsocket.
Controlsocket
The controlsocket is the means to contact a running PDNS daemon, or as we now know, a running pdns_server.
Over this sockets, instructions can be sent using the pdns_control program. Like the pdns_server,
this program is normally accessed via the init.d script.
pdns_control
To communicate with PDNS over the controlsocket, the pdns_control command is used. The init.d script also calls
pdns_control. The syntax is simple: pdns_control command arguments. Currently this is most useful for telling backends
to rediscover domains or to force the transmission of notifications. See .
Besides the commands implemented by the init.d script, for which see , the following pdns_control commands
are available:
ccounts
Returns counts on the contents of the cache.
notify domain
Adds a domain to the notification list, causing PDNS to send out notifications to the nameservers of a domain. Can be used if
a slave missed previous notifications or is generally hard of hearing.
notify-host domainhost
Same as above but with operator specified IP address as destination, to be used if you know better than PowerDNS.
purge
Purges the entire Packet Cache - see .
purge record
Purges all entries for this exact record name - see .
purge record$
Purges all cache entries ending on this name, effectively purging an entire domain - see .
purge
Purges the entire Packet Cache - see .
purge record
Purges all entries for this exact record name - see .
rediscover
Instructs backends that new domains may have appeared in the database, or, in the case of the Bind backend, in
named.conf.
reload
Instructs backends that the contents of domains may have changed. Many backends ignore this, the Bind backend will check
timestamps for all zones (once queries come in for it) and reload if needed.
retrieve domain
Retrieve a slave domain from its master. Done nearly immediatly.
set variable value
Set a configuration parameter. Currently only the 'query-logging' parameter can be set.
uptime
Reports the uptime of the daemon in human readable form.
version
returns the version of a running pdns daemon.
Guardian
When launched by the init.d script, pdns_server wraps itself inside a 'guardian'. This guardian monitors the
performance of the inner pdns_server instance which shows up in the process list of your OS as
pdns_server-instance.
It is also this guardian that pdns_control talks to. A STOP is interpreted by the guardian,
which causes the guardian to sever the connection to the inner process and terminate it, after which it terminates itself.
The init.d script DUMP and SHOW commands need to access the inner process, because
the guardian itself does not run a nameserver. For this purpose, the guardian passes controlsocket requests to the control console of the
inner process. This is the same console as seen with init.d MONITOR.
Modules & Backends
PDNS has the concept of backends and modules. Non-static PDNS distributions have the ability to load new modules at runtime, while the
static versions come with a number of modules built in, but cannot load more.
Related parameters are:
--help
Outputs all known parameters, including those of launched backends, see below.
--launch=backend,backend1,backend1:name
Launches backends. In its most simple form, supply all backends that need to be launched. If you find
that you need to launch single backends multiple times, you can specify a name for later instantiations.
In this case, there are 2 instances of backend1, and the second one is called 'name'.
This means that --backend1-setting is available to configure the first or main instance, and
--backend1-name-setting for the second one.
--load-modules=/directory/libyourbackend.so
If backends are available in nonstandard directories, specify their location here. Multiple files
can be loaded if separated by commas. Only available in non-static PDNS distributions.
--list-modules
Will list all available modules, both compiled in and in dynamically loadable modules.
To run on the commandline, use the pdns_server binary. For example, to see options for the gpgsql backend,
use the following:
$ /usr/sbin/pdns_server --launch=gpgsql --help=gpgsql
How PDNS translates DNS queries into backend queries
A DNS query is not a straightforward lookup. Many DNS queries need to check the backend for additional data, for example to
determine of an unfound record should lead to an NXDOMAIN ('we know about this domain, but that record does not exist') or an
unauthoritative response.
Simplified, without CNAME processing and wildcards, the algorithm is like this:
When a query for a qname/qtype tuple comes in, it is requested directly from the backend.
If present, PDNS adds the contents of the reply to the list of records to return. A question tuple may generate multiple answer
records.
Each of these records is now investigated to see if it needs 'additional processing'. This holds for example for MX records which may
point to hosts for which the PDNS backends also contain data. This involves further lookups for A or AAAA records.
After all additional processing has been performed, PDNS sieves out all double records which may well have appeared. The resulting set of
records is added to the answer packet, and sent out.
A zone transfer works by looking up the domain_id of the SOA record of the name and then listing all records of that
domain_id. This is why all records in a domain need to have the same domain_id.
When a query comes in for an unknown domain, PDNS starts looking for SOA records of all subdomains of the qname, so
no.such.powerdns.com turns into a SOA query for no.such.powerdns.com, such.powerdns.com, powerdns.com, com, ''. When a SOA is found,
that zone is consulted for relevant NS instructions which lead to a referral. If nothing is found within the zone, an authoritative
NXDOMAIN is sent out.
If no SOA was found, an unauthoritative no-error is returned.
In reality, each query for a question tuple first involves checking for a CNAME, unless that resolution has been disabled with the
skip-cname option.
PDNS breaks strict RFC compatability by not always checking for the presence of a SOA record first. This is unlikely to lead to
problems though.
Backend writers' guide
PDNS backends are implemented via a simple yet powerful C++ interface. If your needs are not met by the PipeBackend, you
may want to write your own. Doing so requires a copy of the PowerDNS Open Source Backend Development kit which can be found on http://downloads.powerdns.com/releases/dev.
A backend contains zero DNS logic. It need not look for CNAMES, it need not return NS records unless explicitly asked for, etcetera.
All DNS logic is contained within PDNS itself - backends should simply return records matching the description asked for.
However, please note that your backend can get queries in aNy CAsE! If your database is case sensitive, like most are (with the notable
exception of MySQL), you must make sure that you do find answers which differ only in case.
Simple read-only native backends
Implementing a backend consists of inheriting from the DNSBackend class. For read-only backends, which do not support slave operation,
only the following methods are relevant:
class DNSBackend
{
public:
virtual bool lookup(const QType &qtype, const string &qdomain, DNSPacket *pkt_p=0, int zoneId=-1)=0;
virtual bool list(int domain_id)=0;
virtual bool get(DNSResourceRecord &r)=0;
virtual bool getSOA(const string &name, SOAData &soadata);
};
Note that the first three methods must be implemented. getSOA() has a useful default implementation.
The semantics are simple. Each instance of your class only handles one (1) query at a time. There is no need for locking as PDNS guarantees
that your backend will never be called reentrantly.
Some examples, a more formal specification is down below. A normal lookup starts like this:
YourBackend yb;
yb.lookup(QType::CNAME,"www.powerdns.com");
Your class should now do everything to start this query. Perform as much preparation as possible - handling errors at this stage is better for PDNS
than doing so later on. A real error should be reported by throwing an exception.
PDNS will then call the get() method to get DNSResourceRecords back. The following code illustrates
a typical query:
yb.lookup(QType::CNAME,"www.powerdns.com");
DNSResourceRecord rr;
while(yb.get(rr))
cout<<"Found cname pointing to '"+rr.content+"'"<<endl;
}
Each zone starts with a Start of Authority (SOA) record. This record is special so many backends will choose to implement it
specially. The default getSOA() method performs a regular lookup on your backend to figure out the SOA,
so if you have no special treatment for SOA records, where is no need to implement your own getSOA().
Besides direct queries, PDNS also needs to be able to list a zone, to do zone transfers for example. Each zone has an id which should be
unique within the backend. To list all records belonging to a zone id, the list() method is used. Conveniently,
the domain_id is also available in the SOAData structure.
The following lists the contents of a zone called "powerdns.com".
SOAData sd;
if(!yb.getSOA("powerdns.com",sd)) // are we authoritative over powerdns.com?
return RCode::NotAuth; // no
yb.list(sd.domain_id);
while(yb.get(rr))
cout<<rr.qname<<"\t IN "<<rr.qtype.getName()<<"\t"<<rr.content<<endl;
Please note that when so called 'fancy records' (see ) are enabled, a backend can receive
wildcard lookups. These have a % as the first character of the qdomain in lookup.
A sample minimal backend
This backend only knows about the host "random.powerdns.com", and furthermore, only about its A record:
/* FIRST PART */
class RandomBackend : public DNSBackend
{
public:
bool list(int id) {
return false; // we don't support AXFR
}
void lookup(const QType &type, const string &qdomain, DNSPacket *p, int zoneId)
{
if(type.getCode()!=QType::A || qdomain!="random.powerdns.com") // we only know about random.powerdns.com A
d_answer=""; // no answer
else {
ostringstream os;
os<<random()%256<<"."<<random()%256<<"."<<random()%256<<"."<<random()%256;
d_answer=os.str(); // our random ip address
}
}
bool get(DNSResourceRecord &rr)
{
if(!d_answer.empty()) {
rr.qname="random.powerdns.com"; // fill in details
rr.qtype=QType::A; // A record
rr.ttl=86400; // 1 day
rr.content=d_answer;
d_answer=""; // this was the last answer
return true;
}
return false; // no more data
}
private:
string d_answer;
};
/* SECOND PART */
class RandomFactory : public BackendFactory
{
public:
RandomFactory() : BackendFactory("random") {}
DNSBackend *make(const string &suffix)
{
return new RandomBackend();
}
};
/* THIRD PART */
class RandomLoader
{
public:
Loader()
{
BackendMakers().report(new RandomFactory);
L<<Logger::Info<<" [RandomBackend] This is the randombackend ("__DATE__", "__TIME__") reporting"<<endl;
}
};
static RandomLoader randomloader;
This simple backend can be used as an 'overlay'. In other words, it only knows about a single record, another loaded backend would have
to know about the SOA and NS records and such. But nothing prevents us from loading it without another backend.
The first part of the code contains the actual logic and should be pretty straightforward. The second part is a boilerplate
'factory' class which PDNS calls to create randombackend instances. Note that a 'suffix' parameter is passed. Real life backends
also declare parameters for the configuration file; these get the 'suffix' appended to them. Note that the "random" in the
constructor denotes the name by which the backend will be known.
The third part registers the RandomFactory with PDNS. This is a simple C++ trick which makes sure that this function
is called on execution of the binary or when loading the dynamic module.
Please note that a RandomBackend is actually in most PDNS releases. By default it lives on random.example.com, but you can change
that by setting random-hostname.
NOTE: this simple backend neglects to handle case properly! For a more complete example, see the full pdns-dev distribution as found on
the website.
Interface definition
Classes:
DNSResourceRecord classQType qtypeQType of this recordstring qnamename of this recordstring contentASCII representation of right hand sideu_int16_t prioritypriority of an MX record.u_int32_t ttlTime To Live of this recordint domain_idID of the domain this record belongs totime_t last_modifiedIf unzero, last time_t this record was changed
SOAData structstring nameserverName of the master nameserver of this zonestring hostmasterHostmaster of this domain. May contain an @u_int32_t serialSerial number of this zoneu_int32_t refreshHow often this zone should be refreshedu_int32_t retryHow often a failed zone pull should be retried.u_int32_t expireIf zone pulls failed for this long, retire recordsu_int32_t default_ttlDifficultint domain_idThe ID of the domain within this backend. Must be filled!DNSBackend *dbPointer to the backend that feels authoritative for a domain and can act as a slave
Methods:
void lookup(const QType &qtype, const string &qdomain, DNSPacket *pkt=0, int zoneId=-1)
This function is used to initiate a straight lookup for a record of name 'qdomain' and type 'qtype'.
A QType can be converted into an integer by invoking its getCode() method and into
a string with the getCode().
The original question may or may not be passed in the pointer p. If it is, you can retrieve (from 1.99.11 onwards)
information about who asked the question with the getRemote(DNSPacket *) method. Alternatively,
bool getRemote(struct sockaddr *sa, socklen_t *len) is available.
Note that qdomain can be of any case and that your backend should make sure it is in effect case
insensitive. Furthermore, the case of the original question should be retained in answers returned by get()!
Finally, the domain_id might also be passed indicating that only answers from the indicated zone need apply. This
can both be used as a restriction or as a possible speedup, hinting your backend where the answer might be found.
If initiated succesfully, as indicated by returning true, answers should be made available over the
get() method.
Should throw an AhuException if an error occured accessing the database. Returning otherwise indicates that the query
was started succesfully. If it is known that no data is available, no exception should be thrown! An exception indicates
that the backend considers itself broken - not that no answers are available for a question.
It is legal to return here, and have the first call to get() return false. This is interpreted as 'no data'
bool list(int domain_id)
Initiates a list of the indicated domain. Records should then be made available via the get() method.
Need not include the SOA record. If it is, PDNS will not get confused.
Should return false if the backend does not consider itself authoritative for this zone.
Should throw an AhuException if an error occured accessing the database. Returning true indicates that data is or should be available.
bool get(DNSResourceRecord &rr)
Request a DNSResourceRecord from a query started by get() of list(). If this functions returns
true, rr has been filled with data. When it returns false, no more data is available,
and rr does not contain new data. A backend should make sure that it either fills out all fields of the
DNSResourceRecord or resets them to their default values.
The qname field of the DNSResourceRecord should be filled out with the exact qdomain passed to lookup, preserving
its case. So if a query for 'CaSe.yourdomain.com' comes in and your database contains dat afor 'case.yourdomain.com', the qname field of rr
should contin 'CaSe.yourdomain.com'!
Should throw an AhuException in case a database error occurred.
bool getSOA(const string &name, SOAData &soadata)
If the backend considers itself authoritative over domain name, this method should fill out
the passed SOAData structure and return a positive number. If the backend is functioning correctly, but
does not consider itself authoritative, it should return 0. In case of errors, an AhuException should be thrown.
Reporting errors
To report errors, the Logger class is available which works mostly like an iostream. Example usage is as shown above in the RandomBackend.
Note that it is very important that each line is ended with endl as your message won't be visible otherwise.
To indicate the importance of an error, the standard syslog errorlevels are available. They can be set by outputting
Logger::Critical,
Logger::Error,
Logger::Warning,
Logger::Notice,
Logger::Info or
Logger::Debug to L, in descending order of graveness.
Declaring and reading configuration details
It is highly likely that a backend needs configuration details. On launch, these parameters need to be declared with PDNS so it knows it
should accept them in the configuration file and on the commandline. Furthermore, they will be listed in the output of
--help.
Declaring arguments is done by implementing the member function declareArguments() in the factory class of your
backend. PDNS will call this method after launching the backend.
In the declareArguments() method, the function declare() is available. The exact definitions:
void declareArguments(const string &suffix="")
This method is called to allow a backend to register configurable parameters. The suffix is the sub-name of this module. There is
no need to touch this suffix, just pass it on to the declare method.
void declare(const string &suffix, const string ¶m, const string &explanation, const string &value)The suffix is passed to your method, and can be passed on to declare. param is the name of your parameter.
explanation is what will appear in the output of --help. Furthermore, a default value can be supplied in the
value parameter.
A sample implementation:
void declareArguments(const string &suffix)
{
declare(suffix,"dbname","Pdns backend database name to connect to","powerdns");
declare(suffix,"user","Pdns backend user to connect as","powerdns");
declare(suffix,"host","Pdns backend host to connect to","");
declare(suffix,"password","Pdns backend password to connect with","");
}
After the arguments have been declared, they can be accessed from your backend using the mustDo(),
getArg() and getArgAsNum() methods. The are defined as follows in the DNSBackend class:
void setArgPrefix(const string &prefix)
Must be called before any of the other accessing functions are used. Typical usage is 'setArgPrefix("mybackend"+suffix)'
in the constructor of a backend.
bool mustDo(const string &key)
Returns true if the variable key is set to anything but 'no'.
const string& getArg(const string &key)
Returns the exact value of a parameter.
int getArgAsNum(const string &key)
Returns the numerical value of a parameter. Uses atoi() internally
Sample usage from the BindBackend, using the bind-example-zones and bind-config
parameters.
if(mustDo("example-zones")) {
insert(0,"www.example.com","A","1.2.3.4");
/* ... */
}
if(!getArg("config").empty()) {
BindParser BP;
BP.parse(getArg("config"));
}
Read/write slave-capable backends
The backends above are 'natively capable' in that they contain all data relevant for a domain and do not pull in data from other nameservers.
To enable storage of information, a backend must be able to do more.
Before diving into the details of the implementation some theory is in order. Slave domains are pulled from the master. PDNS needs to
know for which domains it is to be a slave, and for each slave domain, what the IP address of the master is.
A slave zone is pulled from a master, after which it is 'fresh', but this is only temporary. In the SOA record of a zone there is a field
which specifies the 'refresh' interval. After that interval has elapsed, the slave nameserver needs to check at the master ff the serial
number there is higher than what is stored in the backend locally.
If this is the case, PDNS dubs the domain 'stale', and schedules a transfer of data from the remote. This transfer remains scheduled
until the serial numbers remote and locally are identical again.
This theory is implemented by the getUnfreshSlaveInfos method, which is called on all backends periodically.
This method fills a vector of SlaveDomains with domains that are unfresh and possibly stale.
PDNS then retrieves the SOA of those domains remotely and locally and creates a list of stale domains. For each of these domains, PDNS
starts a zonetransfer to resynchronise. Because zone transfers can fail, it is important that the interface to the backend allows
for transaction semantics because a zone might otherwise be left in a halfway updated situation.
The following excerpt from the DNSBackend shows the relevant functions:
class DNSBackend {
public:
/* ... */
virtual bool getDomainInfo(const string &domain, DomainInfo &di);
virtual bool isMaster(const string &name, const string &ip);
virtual bool startTransaction(const string &qname, int id);
virtual bool commitTransaction();
virtual bool abortTransaction();
virtual bool feedRecord(const DNSResourceRecord &rr);
virtual void getUnfreshSlaveInfos(vector<DomainInfo>* domains);
virtual void setFresh(int id);
/* ... */
}
The mentioned DomainInfo struct looks like this:
DomainInfo structint idID of this zone within this backendstring masterIP address of the master of this domain, if anyu_int32_t serialSerial number of this zoneu_int32_t notified_serialLast serial number of this zone that slaves have seentime_t last_checkLast time this zone was checked over at the master for changesenum {Master,Slave,Native} kindType of zoneDNSBackend *backendPointer to the backend that feels authoritative for a domain and can act as a slave
These functions all have a default implementation that returns false - which explains that these methods can be omitted in simple backends.
Furthermore, unlike with simple backends, a slave capable backend must make sure that the 'DNSBackend *db' field of the SOAData record is filled
out correctly - it is used to determine which backend will house this zone.
bool isMaster(const string &name, const string &ip);
If a backend considers itself a slave for the domain name and if the IP address in ip
is indeed a master, it should return true. False otherwise. This is a first line of checks to guard against reloading a domain
unnecessarily.
void getUnfreshSlaveInfos(vector<DomainInfo>* domains)
When called, the backend should examine its list of slave domains and add any unfresh ones to the domains vector.
bool getDomainInfo(const string &name, DomainInfo & di)
This is like getUnfreshSlaveInfos, but for a specific domain. If the backend considers itself authoritative for the named
zone, di should be filled out, and 'true' be returned. Otherwise return false.
bool startTransaction(const string &qname, int id)
When called, the backend should start a transaction that can be committed or rolled back atomically later on.
In SQL terms, this function should BEGIN a transaction and DELETE all
records.
bool feedRecord(const DNSResourceRecord &rr)
Insert this record.
bool commitTransaction();
Make the changes effective. In SQL terms, execute COMMIT.
bool abortTransaction();
Abort changes. In SQL terms, execute ABORT.
bool setFresh()
Indicate that a domain has either been updated or refreshed without the need for a retransfer. This causes
the domain to vanish from the vector modified by getUnfreshSlaveInfos().
PDNS will always call startTransaction() before making calls to feedRecord().
Although it is likely that abortTransaction() will be called in case of problems, backends should also
be prepared to abort from their destructor.
The actual code in PDNS is currently (1.99.9):
Resolver resolver;
resolver.axfr(remote,domain.c_str());
db->startTransaction(domain, domain_id);
L<<Logger::Error<<"AXFR started for '"<<domain<<"'"<<endl;
Resolver::res_t recs;
while(resolver.axfrChunk(recs)) {
for(Resolver::res_t::const_iterator i=recs.begin();i!=recs.end();++i) {
db->feedRecord(*i);
}
}
db->commitTransaction();
db->setFresh(domain_id);
L<<Logger::Error<<"AXFR done for '"<<domain<<"'"<<endl;
Supermaster/Superslave capability
A backend that wants to act as a 'superslave' for a master should implement the following method:
class DNSBackend
{
virtual bool superMasterBackend(const string &ip, const string &domain, const vector<DNSResourceRecord>&nsset, string *account, DNSBackend **db)
};
This function gets called with the IP address of the potential supermaster, the domain it is sending a notification for and the set of NS records
for this domain at that IP address.
Using the supplied data, the backend needs to determine if this is a bonafide 'supernotification' which should be honoured. If it decides that it
should, the supplied pointer to 'account' needs to be filled with the configured name of the supermaster (if accounting is desired), and the
db needs to be filled with a pointer to your backend.
Supermaster/superslave is a complicated concept, if this is all unclear see .
Read/write master-capable backends
In order to be a useful master for a domain, notifies must be sent out whenever a domain is changed. Periodically, PDNS
queries backends for domains that may have changed, and sends out notifications for slave nameservers.
In order to do so, PDNS calls the getUpdatedMasters() method. Like the getUnfreshSlaveInfos()
function mentioned above, this should add changed domain names to the vector passed.
The following excerpt from the DNSBackend shows the relevant functions:
class DNSBackend {
public:
/* ... */
virtual void getUpdatedMasters(vector<DomainInfo>* domains);
virtual void setNotifed(int id, u_int32_t serial);
/* ... */
}
These functions all have a default implementation that returns false - which explains that these methods can be omitted in simple backends.
Furthermore, unlike with simple backends, a slave capable backend must make sure that the 'DNSBackend *db' field of the SOAData record is filled
out correctly - it is used to determine which backend will house this zone.
void getUpdatedMasters(vector<DomainInfo>* domains)
When called, the backend should examine its list of master domains and add any changed ones to the DomainInfo vector
bool setNotified(int domain_id, u_int32_t serial)
Indicate that notifications have been queued for this domain and that it need not be considered 'updated' anymore
Compiling PowerDNSCompiling PowerDNS on Unix
For now, see the Open Source PowerDNS site.
./configure ; make ; make install will do The Right Thing for most people.
PowerDNS can becompiled with modules built in, or with modules designed to be loaded at runtime. All that is configured
before compiling using the well known autoconf/automake system.
To compile in modules, specify them as --with-modules="mod1 mod2 mod3", substituting the desired module names.
Each backend has a module name in the table at the beginning of its section.
To compile a module for inclusion at runtime, which is great if you are a unix vendor, use --with-dynmodules="mod1 mod2 mod3".
These modules then end up as .so files in the compiled libdir.
FreeBSD
Works fine, but use gmake. Pipe backend is currently broken, for reasons, see . Due to the threading model
of FreeBSD, PowerDNS does not benefit from additional CPUs on the system.
Linux
Linux is probably the best supported platform as most of the main coders are Linux users. The static DEB distribution is known to have
problems on Debian 'Sid', but that doesn't matter as PowerDNS is a native part of Debian 'Sid'. Just apt-get!
OpenBSD
Compiles but then does not work. We hear that it may work with more recent versions of gcc, please let us know on
pdns-dev@mailman.powerdns.com.
Solaris
Solaris 7 is supported, but only just. AAAA records do not work on Solaris 7. Solaris 8 and 9 work fine. The 'Sunpro' compiler
has not been tried but is reported to be lacking large parts of the Standard Template Library, which PowerDNS relies on heavily.
Use gcc and gmake (if available). Regular Solaris make has some issues with some PowerDNS Makefile constructs.
Compiling PowerDNS on Windows
By Michel Stol (michel@powerdns.com).
Assumptions
I will assume these things from you:
You have the PowerDNS sources.
There's not much to compile without the source files, eh? :)
You are using Microsoft Visual C++. If you get it to compile using a free compiler, please let us know!
From the day that we began porting the UNIX PowerDNS sources to Microsoft Windows
we used Microsoft Visual C++ as our development environment of choice.
We used Visual C++ 6.0 to compile all sources (both standard version and SP5). Other versions
(including Visual C++ .NET) are untested.
You are using Microsoft Windows NT, 2000 or XP
I will assume that the system where you want to compile the sources on is running
Microsoft Windows NT, 2000 or XP. These are the operating systems that where found
running PowerDNS for Windows.
You probably can compile the sources on other Windows versions too, but that is currently untested.
You are using an English Windows version.
Troughout this document I will use the English names for menu items, names etc., so if you are
running a non-English Windows or MSVC version you have to translate those things yourself. But
I don't think that would be a big problem.
Prequisites
Although we tried to keep PowerDNS for Windows' dependencies down to a minimum, you will still need some
programs and libraries to be able to compile the sources.
pthreads for Windows
The pthreads for Windows library is a Windows implementation of the POSIX threads
specification, which is used a lot in UNIX programs.
PowerDNS uses pthreads too, and to ease the porting process we decided not to reinvent the wheel,
but to use pthreads for Windows instead.
Getting pthreads for Windows
Pthreads for Windows is available from anonymous ftp at ftp://sources.redhat.com/pub/pthreads-win32/.
You should download the latest pthreads-YYYY-MM-DD.exe file.
PowerDNS for Windows was tested with the snapshot of 2002-03-02 of the library.
For more information you can visit the pthreads for Windows homepage at http://sources.redhat.com/pthreads-win32/Installing pthreads for Windows
To install the pthreads for Windows library you have to locate your pthreads-YYYY-MM-DD.exe
file and start it.
After starting the executable a self-extractor dialog will show up where you can specify where to extract
the contents of the file. When you selected a location you can press the Extract button
to extract all content to the target directory.
The library is now installed, we still have to tell Visual C++ where it's located though, more
on that later.
Nullsoft Installer
For our installation program we used Nullsoft's Installer System (NSIS). We used
NSIS because it's easy to use, versatile and free (and it uses SuperPiMP technology, but
they refuse to tell us what it is ;)). If the name Nullsoft rings a bell, it's because they're the guys who made
winamp.
Getting the Nullsoft Installer
The Nullsoft Installer can be downloaded at their website, which is
located at http://www.nullsoft.com/free/nsis/.
The file that you should download is called nsisXXX.exe (where XXX is the latest version).
You can find the NSIS documentation at that website too.
Installing the Nullsoft Installer
Installing NSIS is easy. All there is to it is locating the installer and execute it.
Then just follow the installation steps.
Setting up the build-environment
Before starting Microsoft Visual C++ and compile PowerDNS for Windows, you first
have to set up your build environment.
Make Microsoft Visual C++ recognize *.cc and *.hh (optional)
All PowerDNS source files are in the form name.cc, and all header files in the form
name.hh. These extensions aren't recognized by MSVC by default, so
you might want to change that first.
Only perform this step if you want to be able to edit the *.cc
and *.hh files in MSVC.
If you decide to perform this step, remember that it requires modification of the Windows registry,
always make a backup before modifying!
Ok, after that word of caution we can now proceed. You have to follow these steps:
Start the registry editor by entering regedit.exe in the run prompt
(Start->Run...).
Right click on HKEY_CLASSES_ROOT and select New->Key.
A new key will appear, change that key to .cc, then change the default
value to cppfile
Then perform the same step for .hh (use hfile instead of cppfile).
Go to HKEY_CURRENT_USER\Software\Microsoft\DevStudio\6.0\Build System\Components\Platforms\Win32 (x86)\Tools\32-bit C/C++ Compiler for 80x86. And
add ;*.cc to the Input_Spec value (so that it becomes *.c;*.cpp;*.cxx;*.cc).
If you happen to use another platform (like alpha) to compile the sources, you have to do the step above for that platform.
Go to HKEY_CURRENT_USER\Software\Microsoft\DevStudio\6.0\Search. And
add ;*.cc;*.hh to the FIF_Filter value (so that it becomes *.c;*.cpp;*.cxx;*.tli;*.h;*.tlh;*.inl;*.rc;*.cc;*.hh).
Finally change HKEY_CURRENT_USER\Software\Microsoft\DevStudio\6.0\Text Editor\Tabs/Language Settings\C/C++. And
add ;cc;hh to the FileExtensions value (so that it becomes cpp;cxx;c;h;hxx;hpp;inl;tlh;tli;rc;rc2;hh;cc).
Close the registry editor.
Now should MSVC properly recognize the files as being C++.
Setting Microsoft Visual C++'s directories
MSVC needs to locate some include files, libraries and executables
when it has to build PowerDNS for Windows. We are now going to tell MSVC where
to find those.
To enter the directory dialog you have to go to Tools->Options...->Directories.
Setting the pthreads directories
When you are in the directory dialog you can add the pthreads for Windows directory.
First add the include directory, to do this you have to select Include files
from the Show directories for: combobox. Then press the New
button and browse to the include directory of pthreads (ie. C:\pthreads\include).
Then switch to Library files and add the library directory
(ie. C:\pthreads\lib) using the same method as above.
Setting the Nullsoft Installer directory
While still being in the directory dialog, switch to Executable files
and add the Nullsoft Installer directory (ie. C:\Program Files\NSIS) to the list.
Compilation
Finally, after all the reading, installing and configuring we are ready to start compiling
PowerDNS for Windows.
Starting the compilation
To start the compilation you first have to open the PowerDNS workspace (powerdns.dsw) using explorer or
from the File->Open Workspace... menu in MSVC.
After you opened the workspace you can start compiling. Check all the checkboxes in the
Build->Batch Build... menu and press the Build button.
Now cross your fingers and go make some coffee or tea while compiling PowerDNS for Windows. :)
Yay! It compiled
Congratulations, you have now compiled PowerDNS for Windows!
All the release builds of the binaries are in the Release directory (including the
generated installer). The debug builds are in the, guess what, Debug directory.
Now you can start installing PowerDNS, but that's beyond the scope of this document. See
the online documentation for
more information about that.
What if it went wrong?
If the compilation fails, then try reading this article again, and again to see if you did something wrong.
If you are pretty sure that it's a bug, either in the PowerDNS sources, the build
system or in this article, then please send an e-mail to pdns-dev@mailman.powerdns.com describing your
problem. We will then try to fix it.
Miscellaneous
Some miscellaneous information.
CreditsMichel Stol would like to thank these people:
Bert Hubert
For writing the wonderfull PowerDNS software and learning me stuff
that I'd otherwise never had learned.
PowerDNS B.V.
For being great colleagues.
The pthreads-win32 crew (see the pthreads-win32 CONTRIBUTORS file).
For easing our porting process by writing a great Windows implementation of pthreads.
The guys over at Nullsoft.
For creating the Nullsoft Installer System (NSIS), and Winamp, the program we use every
day to make a lot of noise in the office.
Contact information
If you have a comment, or a bug report concerning either this document or the PowerDNS sources
you can contact pdns-dev@mailman.powerdns.com
For general information about PowerDNS, the pdns server, express, documentation etc. I advice you to visit
http://www.powerdns.com/
If you are interested in buying PowerDNS you can send a mail to sales@powerdns.com
or you can visit the PowerDNS website at http://www.powerdns.com/pdns/
If you want to praise my work, ask me to marry you, deposit $1.000.000 on my bank account or flame me to death, then
you can mail me at michel@powerdns.com :)
Legal information
Microsoft, Visual C++, Windows, Windows NT, Windows 2000, Windows XP and Win32 are
either registered trademarks or trademarks of Microsoft Corporation in the U.S.A. and/or other countries.
Other product and company names mentioned herein may be the trademarks of their respective owners.
PowerDNS license (GNU General Public License version 2)
GNU GENERAL PUBLIC LICENSE
TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION
0. This License applies to any program or other work which contains
a notice placed by the copyright holder saying it may be distributed
under the terms of this General Public License. The "Program", below,
refers to any such program or work, and a "work based on the Program"
means either the Program or any derivative work under copyright law:
that is to say, a work containing the Program or a portion of it,
either verbatim or with modifications and/or translated into another
language. (Hereinafter, translation is included without limitation in
the term "modification".) Each licensee is addressed as "you".
Activities other than copying, distribution and modification are not
covered by this License; they are outside its scope. The act of
running the Program is not restricted, and the output from the Program
is covered only if its contents constitute a work based on the
Program (independent of having been made by running the Program).
Whether that is true depends on what the Program does.
1. You may copy and distribute verbatim copies of the Program's
source code as you receive it, in any medium, provided that you
conspicuously and appropriately publish on each copy an appropriate
copyright notice and disclaimer of warranty; keep intact all the
notices that refer to this License and to the absence of any warranty;
and give any other recipients of the Program a copy of this License
along with the Program.
You may charge a fee for the physical act of transferring a copy, and
you may at your option offer warranty protection in exchange for a fee.
2. You may modify your copy or copies of the Program or any portion
of it, thus forming a work based on the Program, and copy and
distribute such modifications or work under the terms of Section 1
above, provided that you also meet all of these conditions:
a) You must cause the modified files to carry prominent notices
stating that you changed the files and the date of any change.
b) You must cause any work that you distribute or publish, that in
whole or in part contains or is derived from the Program or any
part thereof, to be licensed as a whole at no charge to all third
parties under the terms of this License.
c) If the modified program normally reads commands interactively
when run, you must cause it, when started running for such
interactive use in the most ordinary way, to print or display an
announcement including an appropriate copyright notice and a
notice that there is no warranty (or else, saying that you provide
a warranty) and that users may redistribute the program under
these conditions, and telling the user how to view a copy of this
License. (Exception: if the Program itself is interactive but
does not normally print such an announcement, your work based on
the Program is not required to print an announcement.)
These requirements apply to the modified work as a whole. If
identifiable sections of that work are not derived from the Program,
and can be reasonably considered independent and separate works in
themselves, then this License, and its terms, do not apply to those
sections when you distribute them as separate works. But when you
distribute the same sections as part of a whole which is a work based
on the Program, the distribution of the whole must be on the terms of
this License, whose permissions for other licensees extend to the
entire whole, and thus to each and every part regardless of who wrote it.
Thus, it is not the intent of this section to claim rights or contest
your rights to work written entirely by you; rather, the intent is to
exercise the right to control the distribution of derivative or
collective works based on the Program.
In addition, mere aggregation of another work not based on the Program
with the Program (or with a work based on the Program) on a volume of
a storage or distribution medium does not bring the other work under
the scope of this License.
3. You may copy and distribute the Program (or a work based on it,
under Section 2) in object code or executable form under the terms of
Sections 1 and 2 above provided that you also do one of the following:
a) Accompany it with the complete corresponding machine-readable
source code, which must be distributed under the terms of Sections
1 and 2 above on a medium customarily used for software interchange; or,
b) Accompany it with a written offer, valid for at least three
years, to give any third party, for a charge no more than your
cost of physically performing source distribution, a complete
machine-readable copy of the corresponding source code, to be
distributed under the terms of Sections 1 and 2 above on a medium
customarily used for software interchange; or,
c) Accompany it with the information you received as to the offer
to distribute corresponding source code. (This alternative is
allowed only for noncommercial distribution and only if you
received the program in object code or executable form with such
an offer, in accord with Subsection b above.)
The source code for a work means the preferred form of the work for
making modifications to it. For an executable work, complete source
code means all the source code for all modules it contains, plus any
associated interface definition files, plus the scripts used to
control compilation and installation of the executable. However, as a
special exception, the source code distributed need not include
anything that is normally distributed (in either source or binary
form) with the major components (compiler, kernel, and so on) of the
operating system on which the executable runs, unless that component
itself accompanies the executable.
If distribution of executable or object code is made by offering
access to copy from a designated place, then offering equivalent
access to copy the source code from the same place counts as
distribution of the source code, even though third parties are not
compelled to copy the source along with the object code.
4. You may not copy, modify, sublicense, or distribute the Program
except as expressly provided under this License. Any attempt
otherwise to copy, modify, sublicense or distribute the Program is
void, and will automatically terminate your rights under this License.
However, parties who have received copies, or rights, from you under
this License will not have their licenses terminated so long as such
parties remain in full compliance.
5. You are not required to accept this License, since you have not
signed it. However, nothing else grants you permission to modify or
distribute the Program or its derivative works. These actions are
prohibited by law if you do not accept this License. Therefore, by
modifying or distributing the Program (or any work based on the
Program), you indicate your acceptance of this License to do so, and
all its terms and conditions for copying, distributing or modifying
the Program or works based on it.
6. Each time you redistribute the Program (or any work based on the
Program), the recipient automatically receives a license from the
original licensor to copy, distribute or modify the Program subject to
these terms and conditions. You may not impose any further
restrictions on the recipients' exercise of the rights granted herein.
You are not responsible for enforcing compliance by third parties to
this License.
7. If, as a consequence of a court judgment or allegation of patent
infringement or for any other reason (not limited to patent issues),
conditions are imposed on you (whether by court order, agreement or
otherwise) that contradict the conditions of this License, they do not
excuse you from the conditions of this License. If you cannot
distribute so as to satisfy simultaneously your obligations under this
License and any other pertinent obligations, then as a consequence you
may not distribute the Program at all. For example, if a patent
license would not permit royalty-free redistribution of the Program by
all those who receive copies directly or indirectly through you, then
the only way you could satisfy both it and this License would be to
refrain entirely from distribution of the Program.
If any portion of this section is held invalid or unenforceable under
any particular circumstance, the balance of the section is intended to
apply and the section as a whole is intended to apply in other
circumstances.
It is not the purpose of this section to induce you to infringe any
patents or other property right claims or to contest validity of any
such claims; this section has the sole purpose of protecting the
integrity of the free software distribution system, which is
implemented by public license practices. Many people have made
generous contributions to the wide range of software distributed
through that system in reliance on consistent application of that
system; it is up to the author/donor to decide if he or she is willing
to distribute software through any other system and a licensee cannot
impose that choice.
This section is intended to make thoroughly clear what is believed to
be a consequence of the rest of this License.
8. If the distribution and/or use of the Program is restricted in
certain countries either by patents or by copyrighted interfaces, the
original copyright holder who places the Program under this License
may add an explicit geographical distribution limitation excluding
those countries, so that distribution is permitted only in or among
countries not thus excluded. In such case, this License incorporates
the limitation as if written in the body of this License.
9. The Free Software Foundation may publish revised and/or new versions
of the General Public License from time to time. Such new versions will
be similar in spirit to the present version, but may differ in detail to
address new problems or concerns.
Each version is given a distinguishing version number. If the Program
specifies a version number of this License which applies to it and "any
later version", you have the option of following the terms and conditions
either of that version or of any later version published by the Free
Software Foundation. If the Program does not specify a version number of
this License, you may choose any version ever published by the Free Software
Foundation.
10. If you wish to incorporate parts of the Program into other free
programs whose distribution conditions are different, write to the author
to ask for permission. For software which is copyrighted by the Free
Software Foundation, write to the Free Software Foundation; we sometimes
make exceptions for this. Our decision will be guided by the two goals
of preserving the free status of all derivatives of our free software and
of promoting the sharing and reuse of software generally.
NO WARRANTY
11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY
FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN
OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES
PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED
OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS
TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE
PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING,
REPAIR OR CORRECTION.
12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING
WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR
REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES,
INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING
OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED
TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY
YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER
PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE
POSSIBILITY OF SUCH DAMAGES.
END OF TERMS AND CONDITIONS