From fe1ce82e3fd3d0f98b8532bba126903eb204ffb8 Mon Sep 17 00:00:00 2001 From: Bert Hubert Date: Sat, 17 Jan 2004 13:18:22 +0000 Subject: [PATCH] hmf, part of 2.9.14 is only committed now plus work on 2.9.15 git-svn-id: svn://svn.powerdns.com/pdns/trunk/pdns@217 d19b8d6e-7fed-0310-83ef-9ca221ded41b --- ChangeLog | 29 +- build-scripts/rpm-build-instruction | 4 +- configure.in | 6 +- debian/changelog | 30 +- debian/control | 11 +- debian/pdns.postinst | 2 + debian/rules | 5 +- modules/gpgsqlbackend/OBJECTLIBS | 2 +- modules/gpgsqlbackend/spgsql.cc | 66 ++-- modules/gpgsqlbackend/spgsql.hh | 8 +- modules/ldapbackend/ldapbackend.cc | 447 ++++++++++++++++++---------- modules/ldapbackend/powerldap.hh | 33 +- pdns.spec | 2 +- pdns/Makefile.am | 4 +- pdns/backends/bind/zone2sql.cc | 6 +- pdns/backends/bind/zoneparser2.cc | 8 +- pdns/common_startup.cc | 2 +- pdns/docs/pdns.sgml | 10 +- pdns/logger.cc | 16 +- pdns/packethandler.cc | 5 +- 20 files changed, 480 insertions(+), 216 deletions(-) diff --git a/ChangeLog b/ChangeLog index 43944f9a6..486bdcde3 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,7 +1,34 @@ +changes since 2.9.14: + - you can now do this: + dig axfr ds9a.nl @213.244.168.210 | \ + /usr/bin/zone2sql --gmysql --zone=- | \ + mysql -u pdns pdns + - the '-' is new + - there is now better duplicate zone detection + - allow-recursion-override works but was on by default + - logging was off + - debian/rules forgot sqllite + - removed libpqpp from build-depends + + changes since 2.9.13: - - speed improvements (norbert) - logging to syslog can now be restricted (norbert) - SOA canonic + - zone2ldap cleanup + - LDAP: +> A big patch for the ldapbackend: +> - - Changes to support different lookup methods +> - - Better exception handling +> - - Better support for load distribution +> - - Many cleanups + - errno compilation fixes in LDAP code (Norbert) + - pdns_recursor was too chatty with TCP (noticed by Mathew Walker) + - Generic SQL backend used doQuery where it meant doCommand on set notified (Georg Bauer) + - experimental feature 'recursion-check-nxdomain' + - 2^30 + - postgresql de-c++fiscation + - efficiency increases (chomp), reworking argumentparsing (spaces) + - loglevel fixes changes since 2.9.12: - pdns_recursor can now survive being disconnected from the net for long diff --git a/build-scripts/rpm-build-instruction b/build-scripts/rpm-build-instruction index 5d916796f..f1d0a65a1 100755 --- a/build-scripts/rpm-build-instruction +++ b/build-scripts/rpm-build-instruction @@ -1,5 +1,7 @@ #!/bin/sh -LIBS="-lkrb5 -lkrb -lcrypto -lroken -lcom_err -lasn1 -lresolv" \./configure --with-modules="mysql gmysql gpgsql gsqlite pipe pdns xdb" \ +./configure --with-modules="mysql gmysql gpgsql gsqlite pipe pdns xdb" \ + --with-pgsql-lib=/opt/postgresql/lib/ \ + --with-pgsql-includes=/opt/postgresql/include/ \ --with-dynmodules="" \ --enable-static-binaries --enable-recursor \ --prefix=/usr \ diff --git a/configure.in b/configure.in index 858ae6b27..6ec3b750e 100644 --- a/configure.in +++ b/configure.in @@ -1,6 +1,6 @@ dnl intro AC_INIT(pdns/receiver.cc) -AM_INIT_AUTOMAKE(pdns, 2.9.13) +AM_INIT_AUTOMAKE(pdns, 2.9.15) AC_CANONICAL_HOST AM_CONFIG_HEADER(config.h) AC_C_BIGENDIAN @@ -277,7 +277,7 @@ then PGSQL_libdir= for m in $PGSQL_lib_check; do if test -d "$m" && \ - (test -f "$m/libpq++.so" || test -f "$m/libpq++.a") + (test -f "$m/libpq.a" || test -f "$m/libpq++.a") then PGSQL_libdir=$m break @@ -299,7 +299,7 @@ then AC_MSG_CHECKING([for PgSQL include directory]) PGSQL_incdir= for m in $PGSQL_inc_check; do - if test -d "$m" && test -f "$m/libpq++.h" + if test -d "$m" && test -f "$m/libpq-fe.h" then PGSQL_incdir=$m break diff --git a/debian/changelog b/debian/changelog index 596b3c530..f69b440a7 100644 --- a/debian/changelog +++ b/debian/changelog @@ -1,15 +1,41 @@ +pdns (2.9.14-1) unstable; urgency=medium + + * New upstream version. Postgres support rewritten to use the C interface + instead of the deprectaed libpqpp + + -- Wichert Akkerman Fri, 16 Jan 2004 23:23:33 +0100 + +pdns (2.9.13-3) unstable; urgency=medium + + * Fix pdns postinst so pdns is properly restart on upgrade + + -- Wichert Akkerman Sat, 10 Jan 2004 17:21:18 +0100 + +pdns (2.9.13-2) unstable; urgency=critical + + * Fix a bug in calculation of early timestamps: 1<<31-1 is not the + same as (1<<31)-1. This made all pdns servers consume all possible + CPU when UNIX time went through 2^30 two hours ago. + + -- Wichert Akkerman Sat, 10 Jan 2004 16:53:09 +0100 + pdns (2.9.13-1) unstable; urgency=low * New upstream release + * Stop using my debian.org email address + * Change init scripts to conform to Debian policy - -- Wichert Akkerman Sun, 21 Sep 2003 14:59:46 +0200 + -- Wichert Akkerman Thu, 25 Dec 2003 13:33:40 +0100 pdns (2.9.12-1) unstable; urgency=low * New upstream release * Fix dependency generation. Closes: Bug#210256 + * Check if pdns is installed in init script. Closes: Bug#217402 + * Create a SQLite backend package + * Add versioned dpkg-dev Build-Depends so ${dpkg:Version} works properly - -- Wichert Akkerman Sun, 21 Sep 2003 14:59:46 +0200 + -- Wichert Akkerman Mon, 27 Oct 2003 18:52:53 +0100 pdns (2.9.11-2) unstable; urgency=low diff --git a/debian/control b/debian/control index f4605a6d4..762c0ae91 100644 --- a/debian/control +++ b/debian/control @@ -2,8 +2,8 @@ Source: pdns Section: net Priority: extra Standards-Version: 3.5.8 -Maintainer: Wichert Akkerman -Build-Depends: autoconf, libtool, flex, bison, docbook-utils, libmysqlclient-dev, postgresql-dev, tdb-dev, libgdbm-dev, libpqpp-dev, libldap2-dev +Maintainer: Wichert Akkerman +Build-Depends: autoconf, libtool, flex, bison, docbook-utils, libmysqlclient-dev, postgresql-dev, tdb-dev, libgdbm-dev, libldap2-dev, libsqlite0-dev, dpkg-dev (> 1.10.17) Package: pdns Architecture: any @@ -66,6 +66,13 @@ Description: Generic PostgreSQL backend for pDNS This package contains a generic PostgreSQL backend for the PowerDNS nameserver. It has configurable SQL statements. +Package: pdns-backend-sqlite +Architecture: any +Depends: pdns (= ${dpkg:Version}), ${shlibs:Depends} +Provides: pdns-backend +Description: SQLite backend for pDNS + This package contains a generic SQLite backend for SQLite. + Package: pdns-backend-xdb Architecture: any Depends: pdns (= ${dpkg:Version}), ${shlibs:Depends} diff --git a/debian/pdns.postinst b/debian/pdns.postinst index 5879a2a07..0161f22f2 100755 --- a/debian/pdns.postinst +++ b/debian/pdns.postinst @@ -12,6 +12,8 @@ update_init() { update_pdns() { if [ -n "$2" ] ; then /etc/init.d/pdns start + else + /etc/init.d/pdns restart fi } diff --git a/debian/rules b/debian/rules index 8eab5d430..5bf7dd03b 100755 --- a/debian/rules +++ b/debian/rules @@ -3,7 +3,7 @@ tmpdir := $(shell pwd)/debian/tmp be_tmpdir := $(shell pwd)/debian/tmp-backend backends := ldap mysql pipe xdb gmysql gpgsql gsqlite -debs := ldap mysql pipe xdb pgsql +debs := ldap mysql pipe xdb pgsql sqlite binary-doc: -make -C pdns/docs html/index.html @@ -42,8 +42,9 @@ binary-doc: build-static stamp-build-static: - LIBS="-lkrb5 -lkrb -lcrypto -lroken -lcom_err -lasn1 -lresolv" \ ./configure \ + --with-pgsql-lib=/opt/postgresql/lib/ \ + --with-pgsql-includes=/opt/postgresql/include/ \ --prefix=/usr \ --libexecdir='$${prefix}/lib' \ --libdir='$${prefix}/lib/powerdns' \ diff --git a/modules/gpgsqlbackend/OBJECTLIBS b/modules/gpgsqlbackend/OBJECTLIBS index 5798704ba..f77e7166e 100644 --- a/modules/gpgsqlbackend/OBJECTLIBS +++ b/modules/gpgsqlbackend/OBJECTLIBS @@ -1,3 +1,3 @@ --lpq -lpq++ -lpq -lssl -lcrypto -lcrypt -lresolv -lnsl +-lpq -lssl -lcrypto -lcrypt -lresolv -lnsl diff --git a/modules/gpgsqlbackend/spgsql.cc b/modules/gpgsqlbackend/spgsql.cc index 5cade0611..df3e6950b 100644 --- a/modules/gpgsqlbackend/spgsql.cc +++ b/modules/gpgsqlbackend/spgsql.cc @@ -1,12 +1,13 @@ /* Copyright 2003 Netherlabs BV, bert.hubert@netherlabs.nl. See LICENSE for more information. - $Id: spgsql.cc,v 1.3 2003/10/11 19:57:19 ahu Exp $ */ + $Id: spgsql.cc,v 1.4 2004/01/17 13:18:22 ahu Exp $ */ #include #include "spgsql.hh" #include #include "pdns/logger.hh" #include "pdns/dns.hh" + using namespace std; bool SPgSQL::s_dolog; @@ -14,6 +15,7 @@ bool SPgSQL::s_dolog; SPgSQL::SPgSQL(const string &database, const string &host, const string &msocket, const string &user, const string &password) { + d_db=0; string connectstr; connectstr="dbname="; @@ -27,11 +29,17 @@ SPgSQL::SPgSQL(const string &database, const string &host, const string &msocket if(!password.empty()) connectstr+=" password="+password; - d_db=new PgDatabase(connectstr.c_str()); - // L<ConnectionBad() ) { - throw sPerrorException("Unable to connect to database, connect string: "+connectstr); + d_db=PQconnectdb(connectstr.c_str()); + + if (!d_db || PQstatus(d_db)==CONNECTION_BAD) { + try { + throw sPerrorException("Unable to connect to database, connect string: "+connectstr); + } + catch(...) { + if(d_db) + PQfinish(d_db); + throw; + } } } @@ -43,12 +51,12 @@ void SPgSQL::setLog(bool state) SPgSQL::~SPgSQL() { - delete d_db; + PQfinish(d_db); } SSqlException SPgSQL::sPerrorException(const string &reason) { - return SSqlException(reason+string(": ")+d_db->ErrorMessage()); + return SSqlException(reason+string(": ")+(d_db ? PQerrorMessage(d_db) : "no connection")); } int SPgSQL::doCommand(const string &query) @@ -56,10 +64,16 @@ int SPgSQL::doCommand(const string &query) if(s_dolog) L<ExecCommandOk(query.c_str())) { - throw sPerrorException("PostgreSQL failed to execute command"); + if(!(d_result=PQexec(d_db,query.c_str())) || PQresultStatus(d_result)!=PGRES_COMMAND_OK) { + string error("unknown reason"); + if(d_result) { + error=PQresultErrorMessage(d_result); + PQclear(d_result); + } + throw SSqlException("PostgreSQL failed to execute command: "+error); } - + if(d_result) + PQclear(d_result); d_count=0; return 0; } @@ -70,8 +84,13 @@ int SPgSQL::doQuery(const string &query) if(s_dolog) L<ExecTuplesOk(query.c_str())) { // was Exec, without TuplesOk - throw sPerrorException("PostgreSQL failed to execute command"); + if(!(d_result=PQexec(d_db,query.c_str())) || PQresultStatus(d_result)!=PGRES_TUPLES_OK) { + string error("unknown reason"); + if(d_result) { + error=PQresultErrorMessage(d_result); + PQclear(d_result); + } + throw SSqlException("PostgreSQL failed to execute command: "+error); } d_count=0; @@ -84,8 +103,15 @@ int SPgSQL::doQuery(const string &query, result_t &result) if(s_dolog) L<ExecTuplesOk(query.c_str())) - throw sPerrorException("gPgSQLBackend failed to execute command that expected results"); + if(!(d_result=PQexec(d_db,query.c_str())) || PQresultStatus(d_result)!=PGRES_TUPLES_OK) { + string error("unknown reason"); + if(d_result) { + error=PQresultErrorMessage(d_result); + PQclear(d_result); + } + throw SSqlException("PostgreSQL failed to execute command: "+error); + } + d_count=0; row_t row; @@ -98,12 +124,14 @@ int SPgSQL::doQuery(const string &query, result_t &result) bool SPgSQL::getRow(row_t &row) { row.clear(); - - if(d_count>=d_db->Tuples()) + + if(d_count>=PQntuples(d_result)) { + PQclear(d_result); return false; + } - for(int i=0;iFields();i++) - row.push_back(d_db->GetValue(d_count,i) ?: ""); + for(int i=0;i -#include #include "pdns/backends/gsql/ssql.hh" +#include class SPgSQL : public SSql { public: @@ -25,7 +24,8 @@ public: string escape(const string &str); void setLog(bool state); private: - PgDatabase *d_db; + PGconn* d_db; + PGresult* d_result; int d_count; static bool s_dolog; }; diff --git a/modules/ldapbackend/ldapbackend.cc b/modules/ldapbackend/ldapbackend.cc index aa15959a5..a5ba7efc1 100644 --- a/modules/ldapbackend/ldapbackend.cc +++ b/modules/ldapbackend/ldapbackend.cc @@ -25,170 +25,344 @@ LdapBackend::LdapBackend( const string &suffix ) { - unsigned int i; - setArgPrefix( "ldap" + suffix ); - string hosts = getArg( "host" ); + string hoststr; + unsigned int i, idx; + string::size_type end, begin = 0; + vector hosts; - m_msgid = 0; - m_qname = ""; - m_default_ttl = arg().asNum( "default-ttl" ); - m_pldap = NULL; - for( i = 0; i < hosts.length(); i++ ) + try { - if( hosts[i] == ',' ) { hosts[i] = ' '; } - } + m_msgid = 0; + m_qname = ""; + m_default_ttl = arg().asNum( "default-ttl" ); + m_myname = "[LdapBackend]"; + m_pldap = NULL; - L << Logger::Info << backendname << " LDAP servers = " << hosts << endl; + setArgPrefix( "ldap" + suffix ); + hoststr = getArg( "host" ); - try - { - m_pldap = new PowerLDAP( hosts.c_str(), atoi( getArg( "port" ).c_str() ), mustDo( "starttls" ) ); + m_getdn = false; + m_list_fcnt = &LdapBackend::list_simple; + m_lookup_fcnt = &LdapBackend::lookup_simple; + m_prepare_fcnt = &LdapBackend::prepare_simple; + + if( getArg( "method" ) == "tree" ) + { + m_lookup_fcnt = &LdapBackend::lookup_tree; + } + + if( getArg( "method" ) == "strict" || mustDo( "disable-ptrrecord" ) ) + { + m_lookup_fcnt = &LdapBackend::lookup_strict; + m_prepare_fcnt = &LdapBackend::prepare_strict; + } + + while( ( end = hoststr.find_first_of( ", \t\n", begin ) ) != string::npos ) + { + hosts.push_back( hoststr.substr( begin, end - begin ) ); + begin = end + 1; + } + hosts.push_back( hoststr.substr( begin, hoststr.length() - begin ) ); + + idx = Utility::random() % hosts.size(); + hoststr = hosts[idx]; + + for( i = 1; i < hosts.size(); i++ ) + { + hoststr += " " + hosts[ ( idx + i ) % hosts.size() ]; + } + + L << Logger::Info << m_myname << " LDAP servers = " << hoststr << endl; + + m_pldap = new PowerLDAP( hoststr.c_str(), LDAP_PORT, mustDo( "starttls" ) ); m_pldap->setOption( LDAP_OPT_DEREF, LDAP_DEREF_ALWAYS ); m_pldap->simpleBind( getArg( "binddn" ), getArg( "secret" ) ); } - catch( LDAPException &e ) + catch( LDAPException &le ) { - L << Logger::Error << backendname << " Initialization failed: " << e.what() << endl; if( m_pldap != NULL ) { delete( m_pldap ); } + L << Logger::Error << m_myname << " Ldap connection to server failed: " << le.what() << endl; + throw( AhuException( "Unable to connect to ldap server" ) ); + } + catch( exception &e ) + { + L << Logger::Error << m_myname << " Caught STL exception: " << e.what() << endl; throw( AhuException( "Unable to connect to ldap server" ) ); } - L << Logger::Notice << backendname << " Ldap connection succeeded" << endl; + L << Logger::Notice << m_myname << " Ldap connection succeeded" << endl; } + LdapBackend::~LdapBackend() { delete( m_pldap ); - L << Logger::Notice << backendname << " Ldap connection closed" << endl; + L << Logger::Notice << m_myname << " Ldap connection closed" << endl; +} + + + +bool LdapBackend::list( const string& target, int domain_id ) +{ + try + { + m_qname = target; + m_axfrqlen = target.length(); + m_adomain = m_adomains.end(); // skip loops in get() first time + + return (this->*m_list_fcnt)( target, domain_id ); + } + catch( LDAPTimeout < ) + { + L << Logger::Warning << m_myname << " Unable to get zone " + target + " from LDAP directory: " << lt.what() << endl; + throw( DBException( "LDAP server timeout" ) ); + } + catch( LDAPException &le ) + { + L << Logger::Error << m_myname << " Unable to get zone " + target + " from LDAP directory: " << le.what() << endl; + throw( AhuException( "LDAP server unreachable" ) ); // try to reconnect to another server + } + catch( exception &e ) + { + L << Logger::Error << m_myname << " Caught STL exception for target " << target << ": " << e.what() << endl; + throw( DBException( "STL exception" ) ); + } + + return false; } -bool LdapBackend::list( const string &target, int domain_id ) + +inline bool LdapBackend::list_simple( const string& target, int domain_id ) { string filter; + filter = "(|(associatedDomain=" + target + ")(associatedDomain=*." + target + "))"; + m_msgid = m_pldap->search( getArg("basedn"), LDAP_SCOPE_SUBTREE, filter, (const char**) ldap_attrany ); + + return true; +} + + +void LdapBackend::lookup( const QType &qtype, const string &qname, DNSPacket *dnspkt, int zoneid ) +{ try { - m_qname = target; - m_axfrqlen = target.length(); + m_axfrqlen = 0; + m_qtype = qtype; + m_qname = qname; m_adomain = m_adomains.end(); // skip loops in get() first time - filter = "(|(associatedDomain=" + target + ")(associatedDomain=*." + target + "))"; - m_msgid = m_pldap->search( getArg("basedn"), LDAP_SCOPE_SUBTREE, filter, (const char**) attrany ); + (this->*m_lookup_fcnt)( qtype, qname, dnspkt, zoneid ); } catch( LDAPTimeout < ) { - L << Logger::Warning << backendname << " Unable to get zone " + target + " from LDAP directory: " << lt.what() << endl; - return false; + L << Logger::Warning << m_myname << " Unable to search LDAP directory: " << lt.what() << endl; + throw( DBException( "LDAP server timeout" ) ); } catch( LDAPException &le ) { - L << Logger::Error << backendname << " Unable to get zone " + target + " from LDAP directory: " << le.what() << endl; + L << Logger::Error << m_myname << " Unable to search LDAP directory: " << le.what() << endl; throw( AhuException( "LDAP server unreachable" ) ); // try to reconnect to another server } catch( exception &e ) { - L << Logger::Error << backendname << " Caught STL exception for target " << target << ": " << e.what() << endl; - return false; + L << Logger::Error << m_myname << " Caught STL exception for qname " << qname << ": " << e.what() << endl; + throw( DBException( "STL exception" ) ); } - catch( ... ) +} + + + +void LdapBackend::lookup_simple( const QType &qtype, const string &qname, DNSPacket *dnspkt, int zoneid ) +{ + string filter, attr, qesc; + char** attributes = ldap_attrany + 1; // skip associatedDomain + char* attronly[] = { NULL, "dNSTTL", NULL }; + + + qesc = toLower( m_pldap->escape( qname ) ); + filter = "(associatedDomain=" + qesc + ")"; + + if( qtype.getCode() != QType::ANY ) { - L << Logger::Critical << backendname << " Caught unknown exception for target " << target << endl; - return false; + attr = qtype.getName() + "Record"; + filter = "(&" + filter + "(" + attr + "=*))"; + attronly[0] = (char*) attr.c_str(); + attributes = attronly; } - return true; + DLOG( L << Logger::Debug << m_myname << " Search = basedn: " << getArg( "basedn" ) << ", filter: " << filter << ", qtype: " << qtype.getName() << endl ); + m_msgid = m_pldap->search( getArg("basedn"), LDAP_SCOPE_SUBTREE, filter, (const char**) attributes ); } -void LdapBackend::lookup( const QType &qtype, const string &qname, DNSPacket *dnspkt, int zoneid ) + +void LdapBackend::lookup_strict( const QType &qtype, const string &qname, DNSPacket *dnspkt, int zoneid ) { int len; vector parts; string filter, attr, qesc; - char** attributes = attrany + 1; // skip associatedDomain + char** attributes = ldap_attrany + 1; // skip associatedDomain char* attronly[] = { NULL, "dNSTTL", NULL }; - try - { - m_axfrqlen = 0; - m_qtype = qtype; - m_qname = qname; - qesc = toLower( m_pldap->escape( qname ) ); + qesc = toLower( m_pldap->escape( qname ) ); + stringtok( parts, qesc, "." ); + len = qesc.length(); - if( mustDo( "disable-ptrrecord" ) ) // PTRRecords will be derived from aRecords or aAAARecords + if( parts.size() == 6 && len > 13 && qesc.substr( len - 13, 13 ) == ".in-addr.arpa" ) // IPv4 reverse lookups + { + filter = "(aRecord=" + ptr2ip4( parts ) + ")"; + attronly[0] = "associatedDomain"; + attributes = attronly; + } + else if( parts.size() == 34 && len > 9 && ( qesc.substr( len - 9, 9 ) == ".ip6.arpa" ) ) // IPv6 reverse lookups + { + filter = "(aAAARecord=" + ptr2ip6( parts ) + ")"; + attronly[0] = "associatedDomain"; + attributes = attronly; + } + else // IPv4 and IPv6 lookups + { + filter = "(associatedDomain=" + qesc + ")"; + if( qtype.getCode() != QType::ANY ) { - stringtok( parts, qesc, "." ); - len = qesc.length(); - - if( parts.size() == 6 && len > 13 && qesc.substr( len - 13, 13 ) == ".in-addr.arpa" ) // IPv4 reverse lookups - { - filter = "(aRecord=" + ptr2ip4( parts ) + ")"; - attronly[0] = "associatedDomain"; - attributes = attronly; - } - else if( parts.size() == 34 && len > 9 && ( qesc.substr( len - 9, 9 ) == ".ip6.arpa" ) ) // IPv6 reverse lookups - { - filter = "(aAAARecord=" + ptr2ip6( parts ) + ")"; - attronly[0] = "associatedDomain"; - attributes = attronly; - } - else // IPv4 and IPv6 lookups - { - filter = "(associatedDomain=" + qesc + ")"; - if( qtype.getCode() != QType::ANY ) - { - attr = qtype.getName() + "Record"; - filter = "(&" + filter + "(" + attr + "=*))"; - attronly[0] = (char*) attr.c_str(); - attributes = attronly; - } - } + attr = qtype.getName() + "Record"; + filter = "(&" + filter + "(" + attr + "=*))"; + attronly[0] = (char*) attr.c_str(); + attributes = attronly; } - else // requires additional ldap objects for reverse lookups + } + + DLOG( L << Logger::Debug << m_myname << " Search = basedn: " << getArg( "basedn" ) << ", filter: " << filter << ", qtype: " << qtype.getName() << endl ); + m_msgid = m_pldap->search( getArg("basedn"), LDAP_SCOPE_SUBTREE, filter, (const char**) attributes ); +} + + + +void LdapBackend::lookup_tree( const QType &qtype, const string &qname, DNSPacket *dnspkt, int zoneid ) +{ + string filter, attr, qesc, dn; + char** attributes = ldap_attrany + 1; // skip associatedDomain + char* attronly[] = { NULL, "dNSTTL", NULL }; + vector::reverse_iterator i; + vector parts; + + + qesc = toLower( m_pldap->escape( qname ) ); + filter = "(associatedDomain=" + qesc + ")"; + + if( qtype.getCode() != QType::ANY ) + { + attr = qtype.getName() + "Record"; + filter = "(&" + filter + "(" + attr + "=*))"; + attronly[0] = (char*) attr.c_str(); + attributes = attronly; + } + + stringtok( parts, qesc, "." ); + for( i = parts.rbegin(); i != parts.rend(); i++ ) + { + dn = "dc=" + *i + "," + dn; + } + + DLOG( L << Logger::Debug << m_myname << " Search = basedn: " << dn + getArg( "basedn" ) << ", filter: " << filter << ", qtype: " << qtype.getName() << endl ); + m_msgid = m_pldap->search( dn + getArg("basedn"), LDAP_SCOPE_BASE, filter, (const char**) attributes ); +} + + + +inline bool LdapBackend::prepare() +{ + m_adomains.clear(); + m_ttl = m_default_ttl; + + if( m_result.count( "dNSTTL" ) && !m_result["dNSTTL"].empty() ) + { + char* endptr; + + m_ttl = (u_int32_t) strtol( m_result["dNSTTL"][0].c_str(), &endptr, 10 ); + if( *endptr != '\0' ) { - filter = "(associatedDomain=" + qesc + ")"; - if( qtype.getCode() != QType::ANY ) - { - attr = qtype.getName() + "Record"; - filter = "(&" + filter + "(" + attr + "=*))"; - attronly[0] = (char*) attr.c_str(); - attributes = attronly; - } + L << Logger::Warning << m_myname << " Invalid time to life for " << m_qname << ": " << m_result["dNSTTL"][0] << endl; + m_ttl = m_default_ttl; } + m_result.erase( "dNSTTL" ); + } - DLOG( L << Logger::Debug << backendname << " Search = basedn: " << getArg( "basedn" ) << ", filter: " << filter << ", qtype: " << qtype.getName() << endl ); - - m_adomain = m_adomains.end(); // skip loops in get() first time - m_msgid = m_pldap->search( getArg("basedn"), LDAP_SCOPE_SUBTREE, filter, (const char**) attributes ); + if( !(this->*m_prepare_fcnt)() ) + { + return false; } - catch( LDAPTimeout < ) + + m_adomain = m_adomains.begin(); + m_attribute = m_result.begin(); + m_value = m_attribute->second.begin(); + + return true; +} + + + +inline bool LdapBackend::prepare_simple() +{ + if( !m_axfrqlen ) // request was a normal lookup() { - L << Logger::Warning << backendname << " Unable to search LDAP directory: " << lt.what() << endl; - return; + m_adomains.push_back( m_qname ); } - catch( LDAPException &le ) + else // request was a list() for AXFR { - L << Logger::Error << backendname << " Unable to search LDAP directory: " << le.what() << endl; - throw( AhuException( "LDAP server unreachable" ) ); // try to reconnect to another server + if( m_result.count( "associatedDomain" ) ) + { + vector::iterator i; + for( i = m_result["associatedDomain"].begin(); i != m_result["associatedDomain"].end(); i++ ) { + if( i->substr( i->length() - m_axfrqlen, m_axfrqlen ) == m_qname ) { + m_adomains.push_back( *i ); + } + } + m_result.erase( "associatedDomain" ); + } } - catch( exception &e ) + + return true; +} + + + +inline bool LdapBackend::prepare_strict() +{ + if( !m_axfrqlen ) // request was a normal lookup() { - L << Logger::Error << backendname << " Caught STL exception for qname " << qname << ": " << e.what() << endl; - return; + m_adomains.push_back( m_qname ); + if( m_result.count( "associatedDomain" ) ) + { + m_result["PTRRecord"] = m_result["associatedDomain"]; + m_result.erase( "associatedDomain" ); + } } - catch( ... ) + else // request was a list() for AXFR { - L << Logger::Critical << backendname << " Caught unknown exception for qname " << qname << endl; - return; + if( m_result.count( "associatedDomain" ) ) + { + vector::iterator i; + for( i = m_result["associatedDomain"].begin(); i != m_result["associatedDomain"].end(); i++ ) { + if( i->substr( i->length() - m_axfrqlen, m_axfrqlen ) == m_qname ) { + m_adomains.push_back( *i ); + } + } + m_result.erase( "associatedDomain" ); + } } + + return true; } + bool LdapBackend::get( DNSResourceRecord &rr ) { QType qt; @@ -224,7 +398,7 @@ bool LdapBackend::get( DNSResourceRecord &rr ) if( first == string::npos ) { - L << Logger::Warning << backendname << " Invalid " << attrname << " without priority for " << m_qname << ": " << content << endl; + L << Logger::Warning << m_myname << " Invalid " << attrname << " without priority for " << m_qname << ": " << content << endl; m_value++; continue; } @@ -232,7 +406,7 @@ bool LdapBackend::get( DNSResourceRecord &rr ) rr.priority = (u_int16_t) strtoul( (content.substr( 0, first )).c_str(), &endptr, 10 ); if( *endptr != '\0' ) { - L << Logger::Warning << backendname << " Invalid " << attrname << " without priority for " << m_qname << ": " << content << endl; + L << Logger::Warning << m_myname << " Invalid " << attrname << " without priority for " << m_qname << ": " << content << endl; m_value++; continue; } @@ -243,7 +417,7 @@ bool LdapBackend::get( DNSResourceRecord &rr ) rr.content = content; m_value++; - DLOG( L << Logger::Debug << backendname << " Record = qname: " << rr.qname << ", qtype: " << (rr.qtype).getName() << ", priority: " << rr.priority << ", ttl: " << rr.ttl << ", content: " << rr.content << endl ); + DLOG( L << Logger::Debug << m_myname << " Record = qname: " << rr.qname << ", qtype: " << (rr.qtype).getName() << ", priority: " << rr.priority << ", ttl: " << rr.ttl << ", content: " << rr.content << endl ); return true; } @@ -255,71 +429,30 @@ bool LdapBackend::get( DNSResourceRecord &rr ) m_value = m_attribute->second.begin(); } } - while( m_pldap->getSearchEntry( m_msgid, m_result, false ) && prepareEntry() ); + while( m_pldap->getSearchEntry( m_msgid, m_result, m_getdn ) && prepare() ); } catch( LDAPTimeout < ) { - L << Logger::Warning << backendname << " Search failed: " << lt.what() << endl; + L << Logger::Warning << m_myname << " Search failed: " << lt.what() << endl; + throw( DBException( "LDAP server timeout" ) ); } catch( LDAPException &le ) { - L << Logger::Error << backendname << " Search failed: " << le.what() << endl; + L << Logger::Error << m_myname << " Search failed: " << le.what() << endl; throw( AhuException( "LDAP server unreachable" ) ); // try to reconnect to another server } catch( exception &e ) { - L << Logger::Error << backendname << " Caught STL exception for attribute " << attrname << ": " << e.what() << endl; - } - catch( ... ) - { - L << Logger::Critical << backendname << " Caught unknown exception for attribute " << attrname << endl; + L << Logger::Error << m_myname << " Caught STL exception for attribute " << attrname << ": " << e.what() << endl; + throw( DBException( "STL exception" ) ); } return false; } -inline bool LdapBackend::prepareEntry() -{ - m_adomains.clear(); - m_ttl = m_default_ttl; - - if( m_result.count( "dNSTTL" ) && !m_result["dNSTTL"].empty() ) - { - m_ttl = (u_int32_t) strtol( m_result["dNSTTL"][0].c_str(), NULL, 10 ); - m_result.erase( "dNSTTL" ); - } - - if( !m_axfrqlen ) // request was a normal lookup() - { - m_adomains.push_back( m_qname ); - if( m_result.count( "associatedDomain" ) ) - { - m_result["PTRRecord"] = m_result["associatedDomain"]; - m_result.erase( "associatedDomain" ); - } - } - else // request was a list() for AXFR - { - if( m_result.count( "associatedDomain" ) ) - { - vector::iterator i; - for( i = m_result["associatedDomain"].begin(); i != m_result["associatedDomain"].end(); i++ ) { - if( i->substr( i->length() - m_axfrqlen, m_axfrqlen ) == m_qname ) { - m_adomains.push_back( *i ); - } - } - m_result.erase( "associatedDomain" ); - } - } - - m_adomain = m_adomains.begin(); - m_attribute = m_result.begin(); - m_value = m_attribute->second.begin(); - return true; -} class LdapFactory : public BackendFactory @@ -329,16 +462,16 @@ public: LdapFactory() : BackendFactory( "ldap" ) {} + void declareArguments( const string &suffix="" ) { - declare( suffix, "host", "one or more ldap server","localhost:389" ); - declare( suffix, "port", "ldap server port (depricated, use ldap-host)","389" ); - declare( suffix, "starttls", "use TLS to encrypt connection", "no" ); - declare( suffix, "basedn", "search root in ldap tree (must be set)","" ); - declare( suffix, "binddn", "user dn for non anonymous binds","" ); - declare( suffix, "secret", "user password for non anonymous binds", "" ); - declare( suffix, "disable-ptrrecord", "disable necessity for seperate PTR records", "no" ); - declare( suffix, "default-ttl", "default ttl if DNSTTL is not set (depricated, use default-ttl)", "3600" ); + declare( suffix, "host", "One or more ldap server","127.0.0.1:389" ); + declare( suffix, "starttls", "Use TLS to encrypt connection", "no" ); + declare( suffix, "basedn", "Search root in ldap tree (must be set)","" ); + declare( suffix, "binddn", "User dn for non anonymous binds","" ); + declare( suffix, "secret", "User password for non anonymous binds", "" ); + declare( suffix, "method", "How to search entries (simple, strict or tree)", "list" ); + declare( suffix, "disable-ptrrecord", "Depricated, use ldap-method=strict instead", "no" ); } @@ -351,17 +484,19 @@ public: -class Loader + +class LdapLoader { + LdapFactory factory; public: - Loader() + LdapLoader() { - BackendMakers().report( new LdapFactory ); - L << Logger::Info << backendname << " This is the ldap module version "VERSION" ("__DATE__", "__TIME__") reporting" << endl; - } + BackendMakers().report( &factory ); + L << Logger::Info << " [LdapBackend] This is the ldap module version "VERSION" ("__DATE__", "__TIME__") reporting" << endl; + } }; -static Loader loader; +static LdapLoader ldaploader; diff --git a/modules/ldapbackend/powerldap.hh b/modules/ldapbackend/powerldap.hh index 8ed6e783a..f4b856aec 100644 --- a/modules/ldapbackend/powerldap.hh +++ b/modules/ldapbackend/powerldap.hh @@ -1,23 +1,46 @@ +/* + * PowerDNS LDAP Connector + * By PowerDNS.COM BV + * By Norbert Sendetzky + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + + + #include #include #include #include #include +#include #include #include + #ifndef POWERLDAP_HH #define POWERLDAP_HH + + using std::map; using std::string; using std::vector; -extern int errno; - - class LDAPException : public std::runtime_error { @@ -26,6 +49,7 @@ public: }; + class LDAPTimeout : public LDAPException { public: @@ -33,6 +57,7 @@ public: }; + class PowerLDAP { LDAP* d_ld; @@ -59,4 +84,6 @@ public: static const string escape( const string& tobe ); }; + + #endif diff --git a/pdns.spec b/pdns.spec index d10c06463..5e688526b 100644 --- a/pdns.spec +++ b/pdns.spec @@ -1,6 +1,6 @@ Buildroot: /tmp/pdns Name: pdns-static -Version: 2.9.13 +Version: 2.9.15 Release: 1 Summary: extremely powerful and versatile nameserver Copyright: see /usr/doc/pdns/copyright diff --git a/pdns/Makefile.am b/pdns/Makefile.am index f43155034..cd27947dd 100644 --- a/pdns/Makefile.am +++ b/pdns/Makefile.am @@ -45,14 +45,14 @@ pdns_server_INCLUDES= #resolver_SOURCES=resolver.cc resolver.hh misc.cc unix_utility.cc qtype.cc \ #logger.cc statbag.cc dnspacket.cc arguments.cc tres.cc -INCLUDES=-I/usr/include/mysql +# INCLUDES=-I/usr/include/mysql pdns_recursor_SOURCES=syncres.cc resolver.hh misc.cc unix_utility.cc qtype.cc \ logger.cc statbag.cc dnspacket.cc arguments.cc lwres.cc pdns_recursor.cc lwres.hh \ mtasker.hh sillyrecords.cc syncres.hh recursor_cache.cc recursor_cache.hh \ ../modules/gmysqlbackend/smysql.cc -pdns_recursor_LDFLAGS=-lmysqlclient +pdns_recursor_LDFLAGS= pdns_recursor_LDADD= pdns_control_SOURCES=dynloader.cc dynmessenger.cc arguments.cc logger.cc statbag.cc misc.cc unix_utility.cc diff --git a/pdns/backends/bind/zone2sql.cc b/pdns/backends/bind/zone2sql.cc index 4ba92f356..0318ae7c1 100644 --- a/pdns/backends/bind/zone2sql.cc +++ b/pdns/backends/bind/zone2sql.cc @@ -18,7 +18,7 @@ */ /* accepts a named.conf as parameter and outputs heaps of sql */ -// $Id: zone2sql.cc,v 1.7 2003/11/29 13:14:40 ahu Exp $ +// $Id: zone2sql.cc,v 1.8 2004/01/17 13:18:22 ahu Exp $ #ifdef WIN32 # pragma warning ( disable: 4786 ) # include @@ -74,8 +74,8 @@ static void callback(unsigned int domain_id,const string &domain, const string & num_records++; if(qtype=="SOA") { - // cout<<"Juh: "< - v2.1 $Date: 2004/01/16 22:18:12 $ + v2.1 $Date: 2004/01/17 13:18:22 $ @@ -97,6 +97,12 @@ The Generic SQL backend could cause crashes on PostgreSQL when using pdns_control notify (Georg Bauer) + + + + Debian compatible init.d script (Wichert Akkerman) + + If using the master or slave features, pdns had the notion of eternity ending in 2038, except that due @@ -106,7 +112,7 @@ - Parts of the SOA field were not connonicalized + Parts of the SOA field were not cannonicalized diff --git a/pdns/logger.cc b/pdns/logger.cc index 8963531e1..966639c7d 100644 --- a/pdns/logger.cc +++ b/pdns/logger.cc @@ -41,25 +41,23 @@ void Logger::log(const string &msg, Urgency u) strftime(buffer,sizeof(buffer),"%b %d %H:%M:%S ", &tm); clog<qclass == 3 && p->qtype.getName() == "HINFO") { - rr.content = "PowerDNS $Id: packethandler.cc,v 1.21 2004/01/16 22:18:12 ahu Exp $"; + rr.content = "PowerDNS $Id: packethandler.cc,v 1.22 2004/01/17 13:18:22 ahu Exp $"; rr.ttl = 5; rr.qname=target; rr.qtype=13; // hinfo @@ -170,7 +170,7 @@ int PacketHandler::doVersionRequest(DNSPacket *p, DNSPacket *r, string &target) { DNSResourceRecord rr; if(p->qtype.getCode()==QType::TXT && target=="version.bind") {// TXT - rr.content="Served by POWERDNS "VERSION" $Id: packethandler.cc,v 1.21 2004/01/16 22:18:12 ahu Exp $"; + rr.content="Served by POWERDNS "VERSION" $Id: packethandler.cc,v 1.22 2004/01/17 13:18:22 ahu Exp $"; rr.ttl=5; rr.qname=target; rr.qtype=QType::TXT; // TXT @@ -647,6 +647,7 @@ DNSPacket *PacketHandler::question(DNSPacket *p) bool weAuth; int zoneId; zoneId=-1; + if(p->d.rd && d_doRecursion && arg().mustDo("allow-recursion-override")) weAuth=getAuth(p, &sd, target, &zoneId); else -- 2.50.0