- configparser now strips leading spaces in arguments
- improved chroot error reporting
- lots of bind backend work
+ - we now ignore 'hint' 'forward' whatever zones
Changes since 2.9.1:
- removed debugging output from the webserver (found by Paul Wouters)
-reset yacc/lex in bindparser
+don't read 'hint' and 'forward' sections
bugs:
pdns.conf-dist contains old descriptions
along with this program; if not, write to the Free Software
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
-// $Id: bindbackend.cc,v 1.4 2002/12/18 09:30:13 ahu Exp $
+// $Id: bindbackend.cc,v 1.5 2002/12/18 16:22:20 ahu Exp $
#include <errno.h>
#include <string>
#include <map>
if(d_checknow)
return false;
- if(!d_checkinterval || (time(0)-d_lastcheck<d_checkinterval) || d_filename.empty())
+ if(!d_checknow && !d_checkinterval || (time(0)-d_lastcheck<d_checkinterval) || d_filename.empty())
return true;
return (getCtime()==d_ctime);
return ret;
}
-
+/** This function adds a record to a domain with a certain id. */
void BindBackend::insert(int id, const string &qnameu, const string &qtype, const string &content, int ttl=300, int prio=25)
{
static int s_count;
else {
s_count--;
}
-
-
}
-
+/** Helper function that creates a BBResourceRecord and does s_content housekeeping */
BBResourceRecord BindBackend::resourceMaker(int id, const string &qtype, const string &content, int ttl, int prio)
{
BBResourceRecord make;
}
static BindBackend *us;
-static int domain_id;
-BindBackend *self;
+
string BindBackend::DLReloadHandler(const vector<string>&parts, Utility::pid_t ppid)
{
- for(map<u_int32_t,BBDomainInfo>::iterator i=self->d_bbds.begin();i!=self->d_bbds.end();++i)
+ for(map<u_int32_t,BBDomainInfo>::iterator i=us->d_bbds.begin();i!=us->d_bbds.end();++i)
i->second.d_checknow=true;
return "queued";
}
-static void callback(const string &domain, const string &qtype, const string &content, int ttl, int prio)
+static void callback(unsigned int domain_id, const string &domain, const string &qtype, const string &content, int ttl, int prio)
{
us->insert(domain_id,domain,qtype,content,ttl,prio);
}
bbd.d_filename="";
bbd.d_id=0;
d_bbds[0]=bbd;
-
d_bbds[0].d_loaded=true;
}
extern DynListener *dl;
- self=this;
+ us=this;
dl->registerFunc("BIND-RELOAD", &DLReloadHandler);
}
-void BindBackend::rediscover()
+void BindBackend::rediscover(string *status)
{
- loadConfig();
+ loadConfig(status);
}
-void BindBackend::loadConfig()
+void BindBackend::loadConfig(string* status)
{
- static int s_confcount;
+ static int domain_id;
if(!getArg("config").empty()) {
BindParser BP;
int rejected=0;
int newdomains=0;
- s_confcount++;
map<unsigned int, BBDomainInfo> nbbds;
++i)
{
BBDomainInfo bbd;
- bbd.d_name=i->name;
- bbd.d_filename=i->filename;
- bbd.d_master=i->master;
-
- bbd.setCtime();
- bbd.setCheckInterval(getArgAsNum("check-interval"));
-
+ if(i->type!="master" && i->type!="slave") {
+ L<<Logger::Warning<<d_logprefix<<" Warning! Skipping '"<<i->type<<"' zone '"<<i->name<<"'"<<endl;
+ continue;
+ }
map<unsigned int, BBDomainInfo>::const_iterator j=d_bbds.begin();
for(;j!=d_bbds.end();++j)
- if(j->second.d_name==bbd.d_name) {
- bbd.d_id=j->second.d_id;
+ if(j->second.d_name==i->name) {
+ bbd=j->second;
break;
}
- if(j==d_bbds.end())
+ if(j==d_bbds.end()) { // entirely new
bbd.d_id=domain_id++;
+ bbd.setCtime();
+ bbd.setCheckInterval(getArgAsNum("check-interval"));
+ nbbds[bbd.d_id].d_loaded=false;
+ }
+
+ bbd.d_name=i->name;
+ bbd.d_filename=i->filename;
+ bbd.d_master=i->master;
nbbds[bbd.d_id]=bbd;
- L<<Logger::Info<<d_logprefix<<" parsing '"<<i->name<<"' from file '"<<i->filename<<"'"<<endl;
- nbbds[bbd.d_id].d_loaded=false;
- try {
- ZP.parse(i->filename,i->name); // calls callback for us
- nbbds[bbd.d_id].d_loaded=true;
- }
- catch(AhuException &ae) {
- L<<Logger::Warning<<d_logprefix<<" error parsing '"<<i->name<<"' from file '"<<i->filename<<"': "<<ae.reason<<endl;
- rejected++;
+ if(!bbd.d_loaded) {
+ L<<Logger::Info<<d_logprefix<<" parsing '"<<i->name<<"' from file '"<<i->filename<<"'"<<endl;
+
+ try {
+ ZP.parse(i->filename,i->name,bbd.d_id); // calls callback for us
+ nbbds[bbd.d_id].d_loaded=true; // does this perform locking for us?
+ }
+ catch(AhuException &ae) {
+ ostringstream msg;
+ msg<<" error parsing '"<<i->name<<"' from file '"<<i->filename<<"': "<<ae.reason;
+ if(status)
+ *status+=msg.str();
+
+ L<<Logger::Warning<<d_logprefix<<msg.str()<<endl;
+ rejected++;
+ }
}
vector<vector<BBResourceRecord> *>&tmp=d_zone_id_map[bbd.d_id]; // shrink trick
int remdomains=0;
- vector<string> oldnames, newnames;
- for(map<unsigned int, BBDomainInfo>::const_iterator j=d_bbds.begin();j!=d_bbds.end();++j)
- oldnames.push_back(j->second.d_name);
- for(map<unsigned int, BBDomainInfo>::const_iterator j=nbbds.begin();j!=nbbds.end();++j)
- newnames.push_back(j->second.d_name);
+ set<string> oldnames, newnames;
+ for(map<unsigned int, BBDomainInfo>::const_iterator j=d_bbds.begin();j!=d_bbds.end();++j) {
+ oldnames.insert(j->second.d_name);
+ }
+ for(map<unsigned int, BBDomainInfo>::const_iterator j=nbbds.begin();j!=nbbds.end();++j) {
+ newnames.insert(j->second.d_name);
+ }
+
+ vector<string> diff;
+ set_difference(oldnames.begin(), oldnames.end(), newnames.begin(), newnames.end(), back_inserter(diff));
+ remdomains=diff.size();
+
+ vector<string> diff2;
+ set_difference(newnames.begin(), newnames.end(), oldnames.begin(), oldnames.end(), back_inserter(diff2));
+ newdomains=diff2.size();
d_bbds.swap(nbbds); // commit
+ ostringstream msg;
+ msg<<" Done parsing domains, "<<rejected<<" rejected, "<<newdomains<<" new, "<<remdomains<<" removed";
+ if(status)
+ *status=msg.str();
- L<<Logger::Error<<d_logprefix<<" Done parsing domains, "<<rejected<<" rejected, "<<newdomains<<" new, "<<remdomains<<" removed"<<endl; // XXX add how many were rejected
+ L<<Logger::Error<<d_logprefix<<msg.str()<<endl;
L<<Logger::Info<<d_logprefix<<" Number of hash buckets: "<<d_qnames.bucket_count()<<", number of entries: "<<d_qnames.size()<< endl;
}
}
//cout<<"locked, start nuking records"<<endl;
bbd->d_loaded=0; // block further access
- // now nuke all records with our id
- for(vector<vector<BBResourceRecord> *>::const_iterator i=d_zone_id_map[bbd->d_id].begin();
- i!=d_zone_id_map[bbd->d_id].end();++i)
- {
- (*i)->clear();
- }
- // cout<<"Now clearing the list of records"<<endl;
- // now zonk the list with all records for our id
- d_zone_id_map[bbd->d_id].clear();
- // now reload
+ // this emtpies all d_qnames vectors belonging to this domain. We find these vectors via d_zone_id_map
+ for(vector<vector<BBResourceRecord> *>::iterator i=d_zone_id_map[bbd->d_id].begin();
+ i!=d_zone_id_map[bbd->d_id].end();++i) {
+ (*i)->clear();
+ }
+ // empty our d_zone_id_map of the references to the now empty vectors (which are not gone from d_qnames, btw)
+ d_zone_id_map[bbd->d_id].clear();
ZoneParser ZP;
us=this;
- domain_id=bbd->d_id;
ZP.setCallback(&callback);
- ZP.parse(bbd->d_filename,bbd->d_name);
+ ZP.parse(bbd->d_filename,bbd->d_name,bbd->d_id);
bbd->setCtime();
// and raise d_loaded again!
bbd->d_loaded=1;
public:
BBDomainInfo();
-#if 0
- BBDomainInfo(const BBDomainInfo &orig) {
- d_name=orig.d_name;
- d_loaded=orig.d_loaded;
- d_rwlock=orig.d_rwlock;
- cout<<"Copied "<<(void*)d_rwlock<<"/"<<getpid()<<endl;
- }
- BBDomainInfo &operator=(const BBDomainInfo &orig) {
- d_loaded=orig.d_loaded;
- d_rwlock=orig.d_rwlock;
- cout<<"Assigned "<<(void*)d_rwlock<<"/"<<getpid()<<endl;
- return *this;
- }
-#endif
-
void setCtime();
bool current();
/** The BindBackend is a DNSBackend that can answer DNS related questions. It looks up data
- in a Bind-style zone file */
+ in a Bind-style zone file
+
+ How this all works is quite complex and prone to change. There are a number of containers involved which,
+ together, contain everything we need to know about a domain or a record.
+
+ A domain consists of records. So, 'example.com' has 'www.example.com' as a record.
+
+ All record names are stored in the hash_map d_qnames, with their name as index. Attached to that index
+ is a vector of BBResourceRecords ('BindBackend') belonging to that qname. Each record contains a d_domainid,
+ which is the ID of the domain it belongs to.
+
+ Then there is the map called d_bbds which has as its key the Domain ID, and attached a BBDomainInfo object, which
+ tells us domain metadata (place on disk, if it is a master or a slave etc).
+
+ To allow for AXFRs, there is yet another container, the d_zone_id_map, which contains per domain_id a vector
+ of pointers to vectors of BBResourceRecords. When read in sequence, these deliver all records of a domain_id.
+
+ As there is huge repitition in the right hand side of records, many records point to the same thing (IP address, nameserver),
+ a list of these is kept in s_contents, and each BBResourceRecord only contains a pointer to a record in s_contents.
+
+ So, summarizing:
+
+ class BBResourceRecord:
+ Everything you need to know about a record. In this context we call the name of a BBResourceRecord 'qname'
+
+ class BBDomainInfo:
+ Domain metadata, like location on disk, last time zone was checked
+
+ d_qnames<qname,vector<BBResourceRecord> >:
+ If you know the qname of a record, this gives you all records under that name.
+
+ set<string>s_contents:
+ Set of all 'contents' of records, the right hand sides.
+
+ map<int,vector<vector<BBResourceRecord>* > > d_zone_id_map:
+ If you know the zone_id, this has a vector of pointers to vectors in d_qnames, for AXFR
+
+ map<unsigned int, BBDomainInfo>d_bbds:
+ Map of all domains we know about and metadata about them.
+
+
+*/
class BindBackend : public DNSBackend
{
public:
bool feedRecord(const DNSResourceRecord &r);
bool commitTransaction();
void insert(int id, const string &qname, const string &qtype, const string &content, int ttl, int prio);
- void rediscover();
+ void rediscover(string *status=0);
static HuffmanCodec s_hc;
private:
class handle
void queueReload(BBDomainInfo *bbd);
BBResourceRecord resourceMaker(int id, const string &qtype, const string &content, int ttl, int prio);
static string DLReloadHandler(const vector<string>&parts, Utility::pid_t ppid);
- void loadConfig();
+ void loadConfig(string *status=0);
};
125, 132, 142, 144, 148, 149, 152, 155, 156, 160,
164, 165, 169, 169, 172, 179, 180, 184, 184, 184,
186, 190, 194, 195, 199, 199, 199, 199, 202, 205,
- 206, 210, 216, 224, 233, 240
+ 206, 210, 216, 224, 232, 239
};
#endif
case 43:
#line 226 "bindparser.yy"
{
- // printf("Found a filename: '%s'\n",$2);
- // ztype=$2;
+ s_di.type=yyvsp[0];
}
break;
case 44:
-#line 235 "bindparser.yy"
+#line 234 "bindparser.yy"
{
yyval=yyvsp[0];
}
#endif
return yyresult;
}
-#line 241 "bindparser.yy"
+#line 240 "bindparser.yy"
public:
void clear()
{
- name=filename=master="";
+ name=filename=master=type="";
}
string name;
string filename;
string master;
+ string type;
};
extern const char *bind_directory;
;
zone_type_command:
- TYPETOK WORD
+TYPETOK WORD
{
- // printf("Found a filename: '%s'\n",$2);
- // ztype=$2;
+ s_di.type=$2;
}
;
*/
/* accepts a named.conf as parameter and outputs heaps of sql */
-// $Id: zone2sql.cc,v 1.3 2002/11/29 23:09:08 ahu Exp $
+// $Id: zone2sql.cc,v 1.4 2002/12/18 16:22:20 ahu Exp $
#ifdef WIN32
# pragma warning ( disable: 4786 )
# include <unistd.h>
static int num_records;
static string lastsoa_qname;
-static void callback(const string &domain, const string &qtype, const string &content, int ttl, int prio)
+static void callback(unsigned int domain_id,const string &domain, const string &qtype, const string &content, int ttl, int prio)
{
static int lastsoa_domain_id=-1;
}
lastsoa_qname=i->name;
}
- ZP.parse(i->filename,i->name);
+ ZP.parse(i->filename,i->name,0);
}
catch(AhuException &ae) {
if(!arg().mustDo("on-error-resume-next"))
ZoneParser ZP;
ZP.setDirectory(".");
ZP.setCallback(&callback);
- ZP.parse(zonefile,arg()["zone-name"]);
+ ZP.parse(zonefile,arg()["zone-name"],0);
dirty_hack_num++;
+
}
cerr<<"Parsed "<<num_records<<" records"<<endl;
};
ZoneParser() : d_ttl(3600) {}
~ZoneParser();
- void parse(const string &fname,const string &origin);
+ void parse(const string &fname,const string &origin, unsigned int domain_id);
void parse(const string &fname,const string &origin, vector<Record>&records);
- typedef void callback_t(const string &domain, const string &qtype, const string &content, int ttl, int prio);
+ typedef void callback_t(unsigned int domain_id, const string &domain, const string &qtype, const string &content, int ttl, int prio);
void setCallback(callback_t *callback);
callback_t *d_callback;
bool parseLine(const vector<string>&words, vector<Record> &);
}
-void ZoneParser::parse(const string &fname, const string &origin)
+void ZoneParser::parse(const string &fname, const string &origin, unsigned int domain_id)
{
d_filename=fname.c_str();
}
if(eatLine(line,rec))
for(vector<Record>::const_iterator i=rec.begin();i!=rec.end();++i)
- d_callback(i->name, i->qtype,i->content,i->ttl,i->prio);
+ d_callback(domain_id,i->name, i->qtype,i->content,i->ttl,i->prio);
}
fclose(fds.top());
fds.pop();
along with this program; if not, write to the Free Software
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
-// $Id: dnsbackend.hh,v 1.1 2002/11/27 15:18:32 ahu Exp $
+// $Id: dnsbackend.hh,v 1.2 2002/12/18 16:22:20 ahu Exp $
/* (C) 2002 POWERDNS.COM BV */
#ifndef DNSBACKEND_HH
#define DNSBACKEND_HH
-class DNSPacket;\r
-\r
+class DNSPacket;
+
#include "utility.hh"
#include <string>
#include <vector>
#include <map>
#include <sys/types.h>
-#include <set>\r
-\r
-#ifndef WIN32\r
-# include <sys/socket.h>\r
-# include <dirent.h>\r
-#endif // WIN32\r
+#include <set>
+
+#ifndef WIN32
+# include <sys/socket.h>
+# include <dirent.h>
+#endif // WIN32
#include "qtype.hh"
#include "dns.hh"
{
}
- virtual void rediscover()
+ virtual void rediscover(string* status=0)
{
}
</affiliation>
</author>
- <PubDate>v2.1 $Date: 2002/12/13 15:22:33 $</PubDate>
+ <PubDate>v2.1 $Date: 2002/12/18 16:22:20 $</PubDate>
<Abstract>
<para>
Before proceeding, it is advised to check the release notes for your PDNS version, as specified in the name of the distribution
file.
</para>
+ <sect2 id="changelog-2-9-3"><title>Version 2.9.3</title>
+ <para>
+ Broad range of 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
+ quite a bit.
+ </para>
+ <para>
+ <warning>
+ <para>
+ 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
+ <command>--with-modules="pgmysql" --enable-mysql --enable-pgsql</command> but that you should now use:
+ <command>--with-modules="gmysql gpgsql"</command>. The old launch-names remain available.
+ </para>
+ <para>
+ If you launch the Generic PgSQL backend as gpgsql2, all parameters will have gpsql2 as a prefix, for example
+ <command>pgsql2-dbname</command>. If launched as gpsql, the regular names are in effect.
+ </para>
+ </warning>
+ </para>
+ <para>
+ Improvements:
+ <itemizedlist>
+ <listitem>
+ <para>
+ Bind backend can now deal with missing files and try to find them later.
+ </para>
+ </listitem>
+ <listitem>
+ <para>
+ General robustness improvements in Bind backend - many errors are now non-fatal.
+ </para>
+ </listitem>
+ <listitem>
+ <para>
+ Added support for retrieving RP (Responsible Person) records from remote masters. Serving them was already possible.
+ </para>
+ </listitem>
+ <listitem>
+ <para>
+ 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).
+ </para>
+ </listitem>
+ <listitem>
+ <para>
+ 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).
+ </para>
+ </listitem>
+ </itemizedlist>
+ </para>
+ <para>
+ Changes:
+ <itemizedlist>
+ <listitem>
+ <para>
+ gpgsql and gmysql backends split out of the hybdid pgmysqlbackend. This again changed compilation instructions!
+ </para>
+ </listitem>
+ </itemizedlist>
+ </para>
+ <para>
+ Bugfixes:
+ <itemizedlist>
+ <listitem>
+ <para>
+ Windows version did not compile without minor changes.
+ </para>
+ </listitem>
+ <listitem>
+ <para>
+ Confusing error reporting on Windows 98 (which does not support PowerDNS) fixed
+ </para>
+ </listitem>
+ <listitem>
+ <para>
+ Potential crashes with shortened packets addressed. An upgrade is advised!
+ </para>
+ </listitem>
+ <listitem>
+ <para>
+ 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.
+ </para>
+ </listitem>
+ </itemizedlist>
+ </para>
+ </sect2>
<sect2 id="changelog-2-9-2"><title>Version 2.9.2</title>
<para>
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
<row><entry>Superslave</entry><entry>Yes</entry></row>
<row><entry>Autoserial</entry><entry>Yes</entry></row>
<row><entry>Case</entry><entry>All lower</entry></row>
- <row><entry>Module name</entry><entry>pgmysql</entry></row>
- <row><entry>Lauch name</entry><entry>gmysql and gpgsql2</entry></row>
+ <row><entry>Module name < 2.9.3</entry><entry>pgmysql</entry></row>
+ <row><entry>Module name > 2.9.2</entry><entry>gmysql and gpgsql</entry></row>
+ <row><entry>Lauch name</entry><entry>gmysql and gpgsql2 and gpgsql</entry></row>
</tbody>
</tgroup>
</table>
Currently disabled in prereleases. But see <xref linkend="slave">.
</para>
</sect2>
+ <sect2><title>Commands</title>
+ <para>
+ <command>pdns_control</command> offers commands to communicate instructions to PowerDNS. These are detailed here.
+ <variablelist>
+ <varlistentry>
+ <term>rediscover</term>
+ <listitem>
+ <para>
+ Reread the bind configuration file (<filename>named.conf</filename>). 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.
+ <note>
+ <para>
+ Except that with 2.9.3, they are not removed from memory.
+ </para>
+ </note>
+ </para>
+ </listitem>
+ </varlistentry>
+ <varlistentry>
+ <term>bind-reload</term>
+ <listitem>
+ <para>
+ All zones with a changed timestamp are reloaded at the next incoming query for them.
+ </para>
+ </listitem>
+ </varlistentry>
+ </variablelist>
+ </para>
+ </sect2>
</sect1>
<sect1 id="odbc">
PacketHandler P;
try {
L<<Logger::Error<<"Rediscovery was requested"<<endl;
- P.getBackend()->rediscover();
- return "Ok";
+ string status="Ok";
+ P.getBackend()->rediscover(&status);
+ return status;
}
catch(AhuException &ae) {
return ae.reason;
along with this program; if not, write to the Free Software
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
-// $Id: ueberbackend.cc,v 1.5 2002/12/16 12:51:20 ahu Exp $
+// $Id: ueberbackend.cc,v 1.6 2002/12/18 16:22:20 ahu Exp $
/* (C) Copyright 2002 PowerDNS.COM BV */
#include "utility.hh"
}
}
-void UeberBackend::rediscover()
+void UeberBackend::rediscover(string *status)
{
for ( vector< DNSBackend * >::iterator i = backends.begin(); i != backends.end(); ++i )
{
- ( *i )->rediscover();
+ string tmpstr;
+ ( *i )->rediscover(&tmpstr);
+ if(status)
+ *status+=tmpstr + (i!=backends.begin() ? "\n" : "");
}
}
#include <string>
#include <algorithm>
#include <pthread.h>
-#include <semaphore.h>\r
-\r
-#ifndef WIN32\r
-#include <sys/un.h>\r
-#include <dlfcn.h>\r
-#include <unistd.h>\r
-#include <sys/socket.h>\r
-#include <netinet/in.h>\r
-#include <sys/stat.h>\r
-#include <fcntl.h>\r
-#include <unistd.h>\r
-#endif // WIN32\r
+#include <semaphore.h>
+
+#ifndef WIN32
+#include <sys/un.h>
+#include <dlfcn.h>
+#include <unistd.h>
+#include <sys/socket.h>
+#include <netinet/in.h>
+#include <sys/stat.h>
+#include <fcntl.h>
+#include <unistd.h>
+#endif // WIN32
#include "dnspacket.hh"
#include "dnsbackend.hh"
void getUnfreshSlaveInfos(vector<DomainInfo>* domains);
void getUpdatedMasters(vector<DomainInfo>* domains);
bool getDomainInfo(const string &domain, DomainInfo &di);
- void rediscover();
+ void rediscover(string* status=0);
void reload();
private:
DNSResourceRecord lastrr;