From e1d03bb07f5cc0b1b62cd08994294cf164bebe0b Mon Sep 17 00:00:00 2001 From: Bert Hubert Date: Sat, 29 Nov 2003 16:49:42 +0000 Subject: [PATCH] lots git-svn-id: svn://svn.powerdns.com/pdns/trunk/pdns@200 d19b8d6e-7fed-0310-83ef-9ca221ded41b --- ChangeLog | 5 +- configure.in | 2 +- debian/changelog | 6 + modules/ldapbackend/ldapbackend.cc | 48 ++++--- modules/ldapbackend/powerldap.cc | 218 ++++++++++++++++------------- modules/ldapbackend/powerldap.hh | 9 +- pdns.spec | 2 +- pdns/backends/bind/zone2ldap.cc | 152 +++++++++++++++----- pdns/backends/bind/zoneparser2.cc | 4 +- pdns/docs/pdns.sgml | 82 ++++++++++- 10 files changed, 364 insertions(+), 164 deletions(-) diff --git a/ChangeLog b/ChangeLog index 8e5b596a8..f7a8f2a2f 100644 --- a/ChangeLog +++ b/ChangeLog @@ -6,7 +6,10 @@ changes since 2.9.12: - big LDAP cleanup - LDAP now has TLS support - Opteron support (opteron login by jeffdavey@submersion.com) - + - fixed errors with disable-axfr (Norbert) + - improved error reporting in zone2sql (Thom May) + - Zone2LDAP updates: + Now it's possible to generate ldif files containing a tree or a list of entries. changes since 2.9.11: - ldap updates diff --git a/configure.in b/configure.in index 892d5394f..118c44dc8 100644 --- a/configure.in +++ b/configure.in @@ -1,6 +1,6 @@ dnl intro AC_INIT(pdns/receiver.cc) -AM_INIT_AUTOMAKE(pdns, 2.9.12) +AM_INIT_AUTOMAKE(pdns, 2.9.13) AC_CANONICAL_HOST AM_CONFIG_HEADER(config.h) AC_C_BIGENDIAN diff --git a/debian/changelog b/debian/changelog index d85b4ccfc..596b3c530 100644 --- a/debian/changelog +++ b/debian/changelog @@ -1,3 +1,9 @@ +pdns (2.9.13-1) unstable; urgency=low + + * New upstream release + + -- Wichert Akkerman Sun, 21 Sep 2003 14:59:46 +0200 + pdns (2.9.12-1) unstable; urgency=low * New upstream release diff --git a/modules/ldapbackend/ldapbackend.cc b/modules/ldapbackend/ldapbackend.cc index 34f2387ab..aa15959a5 100644 --- a/modules/ldapbackend/ldapbackend.cc +++ b/modules/ldapbackend/ldapbackend.cc @@ -54,7 +54,7 @@ LdapBackend::LdapBackend( const string &suffix ) throw( AhuException( "Unable to connect to ldap server" ) ); } - L << Logger::Info << backendname << " Ldap connection succeeded" << endl; + L << Logger::Notice << backendname << " Ldap connection succeeded" << endl; } @@ -76,13 +76,12 @@ bool LdapBackend::list( const string &target, int domain_id ) m_axfrqlen = target.length(); m_adomain = m_adomains.end(); // skip loops in get() first time - DLOG( L << Logger::Debug << backendname << " List = target: " << target << endl ); filter = "(|(associatedDomain=" + target + ")(associatedDomain=*." + target + "))"; m_msgid = m_pldap->search( getArg("basedn"), LDAP_SCOPE_SUBTREE, filter, (const char**) attrany ); } catch( LDAPTimeout < ) { - L << Logger::Error << backendname << " Unable to get zone " + target + " from LDAP directory: " << lt.what() << endl; + L << Logger::Warning << backendname << " Unable to get zone " + target + " from LDAP directory: " << lt.what() << endl; return false; } catch( LDAPException &le ) @@ -92,12 +91,12 @@ bool LdapBackend::list( const string &target, int domain_id ) } catch( exception &e ) { - L << Logger::Error << backendname << " Caught STL exception: " << e.what() << endl; + L << Logger::Error << backendname << " Caught STL exception for target " << target << ": " << e.what() << endl; return false; } catch( ... ) { - L << Logger::Critical << backendname << " Caught unknown exception" << endl; + L << Logger::Critical << backendname << " Caught unknown exception for target " << target << endl; return false; } @@ -169,7 +168,7 @@ void LdapBackend::lookup( const QType &qtype, const string &qname, DNSPacket *dn } catch( LDAPTimeout < ) { - L << Logger::Error << backendname << " Unable to search LDAP directory: " << lt.what() << endl; + L << Logger::Warning << backendname << " Unable to search LDAP directory: " << lt.what() << endl; return; } catch( LDAPException &le ) @@ -179,12 +178,12 @@ void LdapBackend::lookup( const QType &qtype, const string &qname, DNSPacket *dn } catch( exception &e ) { - L << Logger::Error << backendname << " Caught STL exception: " << e.what() << endl; + L << Logger::Error << backendname << " Caught STL exception for qname " << qname << ": " << e.what() << endl; return; } catch( ... ) { - L << Logger::Error << backendname << " Caught unknown exception" << endl; + L << Logger::Critical << backendname << " Caught unknown exception for qname " << qname << endl; return; } } @@ -218,25 +217,33 @@ bool LdapBackend::get( DNSResourceRecord &rr ) rr.priority = 0; rr.ttl = m_ttl; - if( qt.getCode() == QType::MX ) // MX Record, e.g. 10 smtp.example.com + if( qt.getCode() == QType::MX || qt.getCode() == QType::SRV ) // Priority, e.g. 10 smtp.example.com { - parts.clear(); - stringtok( parts, content, " " ); + char* endptr; + string::size_type first = content.find_first_of( " " ); - if( parts.size() != 2) + if( first == string::npos ) { - L << Logger::Warning << backendname << " Invalid MX record without priority: " << content << endl; + L << Logger::Warning << backendname << " Invalid " << attrname << " without priority for " << m_qname << ": " << content << endl; + m_value++; continue; } - rr.priority = (u_int16_t) strtol( parts[0].c_str(), NULL, 10 ); - content = parts[1]; + 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; + m_value++; + continue; + } + + content = content.substr( first + 1, content.length() - first - 1 ); } rr.content = content; m_value++; - DLOG( L << Logger::Debug << backendname << " Record = qname: " << rr.qname << ", qtype: " << (rr.qtype).getName() << ", priority: " << rr.priority << ", content: " << rr.content << endl ); + DLOG( L << Logger::Debug << backendname << " Record = qname: " << rr.qname << ", qtype: " << (rr.qtype).getName() << ", priority: " << rr.priority << ", ttl: " << rr.ttl << ", content: " << rr.content << endl ); return true; } @@ -247,14 +254,13 @@ bool LdapBackend::get( DNSResourceRecord &rr ) m_attribute = m_result.begin(); m_value = m_attribute->second.begin(); } - m_result.clear(); } while( m_pldap->getSearchEntry( m_msgid, m_result, false ) && prepareEntry() ); } catch( LDAPTimeout < ) { - L << Logger::Error << backendname << " Search failed: " << lt.what() << endl; + L << Logger::Warning << backendname << " Search failed: " << lt.what() << endl; } catch( LDAPException &le ) { @@ -263,11 +269,11 @@ bool LdapBackend::get( DNSResourceRecord &rr ) } catch( exception &e ) { - L << Logger::Error << backendname << " Caught STL exception: " << e.what() << endl; + L << Logger::Error << backendname << " Caught STL exception for attribute " << attrname << ": " << e.what() << endl; } catch( ... ) { - L << Logger::Error << backendname << " Caught unknown exception" << endl; + L << Logger::Critical << backendname << " Caught unknown exception for attribute " << attrname << endl; } return false; @@ -327,7 +333,7 @@ public: { 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 STARTTLS to encrypt connection", "no" ); + 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", "" ); diff --git a/modules/ldapbackend/powerldap.cc b/modules/ldapbackend/powerldap.cc index 584b53f77..b90984de3 100644 --- a/modules/ldapbackend/powerldap.cc +++ b/modules/ldapbackend/powerldap.cc @@ -2,7 +2,7 @@ -PowerLDAP::PowerLDAP( const string& host, u_int16_t port, bool tls ) : d_timeout( 5 ) +PowerLDAP::PowerLDAP( const string& host, u_int16_t port, bool tls ) { int protocol = LDAP_VERSION3; @@ -63,103 +63,129 @@ void PowerLDAP::simpleBind( const string& ldapbinddn, const string& ldapsecret ) } -/** Function waits for a result, returns its type and optionally stores the result - in retresult. If returned via retresult, the caller is responsible for freeing - it with ldap_msgfree! */ -int PowerLDAP::waitResult(int msgid,LDAPMessage **retresult) +int PowerLDAP::search( const string& base, int scope, const string& filter, const char** attr ) { - struct timeval tv; - tv.tv_sec=d_timeout; - tv.tv_usec=0; - LDAPMessage *result; - - int rc=ldap_result(d_ld,msgid,0,&tv,&result); - if(rc==-1) - throw LDAPException("Error waiting for LDAP result: "+getError()); - if(!rc) - throw LDAPTimeout(); - - if(retresult) - *retresult=result; - - if(rc==LDAP_RES_SEARCH_ENTRY || LDAP_RES_SEARCH_RESULT) // no error in that case - return rc; - - int err; - if((err=ldap_result2error(d_ld, result,0))!=LDAP_SUCCESS) { - ldap_msgfree(result); - throw LDAPException("LDAP Server reported error: "+getError(err)); - } - - if(!retresult) - ldap_msgfree(result); - - return rc; + int msgid; + if( ( msgid = ldap_search( d_ld, base.c_str(), scope, filter.c_str(), const_cast (attr), 0 ) ) == -1 ) + { + throw LDAPException( "Starting LDAP search: " + getError() ); + } + + return msgid; } -int PowerLDAP::search(const string& base, int scope, const string& filter, const char **attr) +/** + * Function waits for a result, returns its type and optionally stores the result. + * If the result is returned, the caller is responsible for freeing it with + * ldap_msgfree! + */ + +int PowerLDAP::waitResult( int msgid, int timeout, LDAPMessage** result ) { - int msgid; + int rc; + struct timeval tv; + LDAPMessage* res; + + + tv.tv_sec = timeout; + tv.tv_usec = 0; + + if( ( rc = ldap_result( d_ld, msgid, LDAP_MSG_ONE, &tv, &res ) ) == -1 ) + { + throw LDAPException( "Error waiting for LDAP result: " + getError() ); + } + else if( rc == 0 ) + { + throw LDAPTimeout(); + } - if( ( msgid = ldap_search( d_ld, base.c_str(), scope, filter.c_str(),const_cast(attr),0 ) ) == -1 ) - throw LDAPException("Starting LDAP search: "+getError()); + if( result == NULL ) + { + ldap_msgfree( res ); + return rc; + } - return msgid; + *result = res; + return rc; } -bool PowerLDAP::getSearchEntry(int msgid, sentry_t &entry, bool withdn) + +bool PowerLDAP::getSearchEntry( int msgid, sentry_t& entry, bool dn, int timeout ) { - entry.clear(); - int rc=waitResult(msgid,&d_searchresult); - - if(rc==LDAP_RES_SEARCH_RESULT) { - ldap_msgfree(d_searchresult); - return false; - } - - if(rc!=LDAP_RES_SEARCH_ENTRY) - throw LDAPException("Search returned non-answer result"); - - d_searchentry=ldap_first_entry(d_ld, d_searchresult); - - // we now have an entry in d_searchentry - - if( withdn == true ) - { - vector dnresult; - char* dn = ldap_get_dn( d_ld, d_searchentry ); - dnresult.push_back( dn ); - ldap_memfree( dn ); - entry["dn"] = dnresult; - } - - BerElement *ber; - - for(char *attr = ldap_first_attribute( d_ld, d_searchresult, &ber ); attr ; attr=ldap_next_attribute(d_ld, d_searchresult, ber)) { - struct berval **bvals=ldap_get_values_len(d_ld,d_searchentry,attr); - vector rvalues; - if(bvals) { - for(struct berval** bval=bvals;*bval;++bval) - rvalues.push_back((*bval)->bv_val); - } - entry[attr]=rvalues; - ldap_value_free_len(bvals); - ldap_memfree(attr); - } - - ber_free(ber,0); - ldap_msgfree(d_searchresult); - - return true; + int i; + char* attr; + BerElement* ber; + struct berval** berval; + vector values; + LDAPMessage* result; + LDAPMessage* object; + + + if( ( i = waitResult( msgid, timeout, &result ) ) == LDAP_RES_SEARCH_RESULT ) + { + ldap_msgfree( result ); + return false; + } + + if( i != LDAP_RES_SEARCH_ENTRY ) + { + ldap_msgfree( result ); + throw LDAPException( "Search returned an unexpected result" ); + } + + if( ( object = ldap_first_entry( d_ld, result ) ) == NULL ) + { + ldap_msgfree( result ); + throw LDAPException( "Couldn't get first result entry: " + getError() ); + } + + entry.clear(); + + if( dn ) + { + attr = ldap_get_dn( d_ld, object ); + values.push_back( attr ); + ldap_memfree( attr ); + entry["dn"] = values; + } + + if( ( attr = ldap_first_attribute( d_ld, object, &ber ) ) != NULL ) + { + do + { + if( ( berval = ldap_get_values_len( d_ld, object, attr ) ) != NULL ) + { + values.clear(); + for( i = 0; i < ldap_count_values_len( berval ); i++ ) + { + values.push_back( berval[i]->bv_val ); // use berval[i]->bv_len for non string values? + } + + entry[attr] = values; + ldap_value_free_len( berval ); + } + ldap_memfree( attr ); + } + while( ( attr = ldap_next_attribute( d_ld, object, ber ) ) != NULL ); + + ber_free( ber, 0 ); + } + + ldap_msgfree( result ); + return true; } -void PowerLDAP::getSearchResults(int msgid, sresult_t &result, bool withdn) + +void PowerLDAP::getSearchResults( int msgid, sresult_t& result, bool dn, int timeout ) { - result.clear(); - sentry_t entry; - while(getSearchEntry(msgid, entry, withdn)) - result.push_back(entry); + sentry_t entry; + + result.clear(); + while( getSearchEntry( msgid, entry, dn, timeout ) ) + { + result.push_back( entry ); + } } @@ -176,14 +202,18 @@ const string PowerLDAP::getError( int rc ) } -const string PowerLDAP::escape(const string &name) +const string PowerLDAP::escape( const string& str ) { - string a; - - for(string::const_iterator i=name.begin();i!=name.end();++i) { - if(*i=='*' || *i=='\\') - a+='\\'; - a+=*i; - } - return a; + string a; + string::const_iterator i; + + for( i = str.begin(); i != str.end(); i++ ) + { + if( *i == '*' || *i == '\\' ) { + a += '\\'; + } + a += *i; + } + + return a; } diff --git a/modules/ldapbackend/powerldap.hh b/modules/ldapbackend/powerldap.hh index 58da8ff9b..8ed6e783a 100644 --- a/modules/ldapbackend/powerldap.hh +++ b/modules/ldapbackend/powerldap.hh @@ -36,12 +36,9 @@ public: class PowerLDAP { LDAP* d_ld; - int d_timeout; - LDAPMessage* d_searchresult; - LDAPMessage* d_searchentry; const string getError( int rc = -1 ); - int waitResult( int msgid = LDAP_RES_ANY, LDAPMessage** retresult = 0 ); + int waitResult( int msgid = LDAP_RES_ANY, int timeout = 0, LDAPMessage** result = NULL ); public: typedef map > sentry_t; @@ -56,8 +53,8 @@ public: void simpleBind( const string& ldapbinddn = "", const string& ldapsecret = "" ); int search( const string& base, int scope, const string& filter, const char** attr = 0 ); - bool getSearchEntry( int msgid, sentry_t& entry, bool withdn = false ); - void getSearchResults( int msgid, sresult_t& result, bool withdn = false ); + bool getSearchEntry( int msgid, sentry_t& entry, bool dn = false, int timeout = 5 ); + void getSearchResults( int msgid, sresult_t& result, bool dn = false, int timeout = 5 ); static const string escape( const string& tobe ); }; diff --git a/pdns.spec b/pdns.spec index bdb0490ca..d10c06463 100644 --- a/pdns.spec +++ b/pdns.spec @@ -1,6 +1,6 @@ Buildroot: /tmp/pdns Name: pdns-static -Version: 2.9.12 +Version: 2.9.13 Release: 1 Summary: extremely powerful and versatile nameserver Copyright: see /usr/doc/pdns/copyright diff --git a/pdns/backends/bind/zone2ldap.cc b/pdns/backends/bind/zone2ldap.cc index 494f6fc50..1c7fcabc8 100644 --- a/pdns/backends/bind/zone2ldap.cc +++ b/pdns/backends/bind/zone2ldap.cc @@ -39,32 +39,111 @@ ArgvMap args; string g_basedn; string g_zonename; map g_objects; +map g_nodes; -static void callback( unsigned int domain_id, const string &domain, const string &qtype, const string &content, int ttl, int prio ) +static void callback_list( unsigned int domain_id, const string &domain, const string &qtype, const string &content, int ttl, int prio ) { + string host; vector parts; string domain2 = ZoneParser::canonic( domain ); string content2 = ZoneParser::canonic( content ); + host = domain2.substr( 0, domain2.rfind( g_zonename ) ); + host = ZoneParser::canonic( host ); + + cout << "dn: dc="; + if( !host.empty() ) { cout << host << ",dc="; } + cout << g_zonename << "," << g_basedn << endl; + + if( host.empty() ) { host = g_zonename; } + + if( !g_objects[domain2] ) + { + g_objects[domain2] = true; + cout << "changetype: add" << endl; + cout << "objectclass: top" << endl; + if( domain2 == g_zonename ) { cout << "objectclass: dcobject" << endl; } // only necessary for phpgeneral + cout << "objectclass: dnsdomain2" << endl; + cout << "objectclass: domainrelatedobject" << endl; + cout << "dc: " << host << endl; + cout << "dnsttl: " << ttl << endl; + cout << "associateddomain: " << domain2 << endl; + } + else + { + cout << "changetype: modify" << endl; + } + + cout << qtype << "Record: "; + if( prio != 0 ) { cout << prio << " "; } + cout << content2 << endl << endl; +} + + +static void callback_tree( unsigned int domain_id, const string &domain, const string &qtype, const string &content, int ttl, int prio ) +{ + string subnet, net; + vector parts, subparts; + vector::const_iterator i, j; + string domain2 = ZoneParser::canonic( domain ); + string content2 = ZoneParser::canonic( content ); + + + subnet = domain2.substr( 0, domain2.rfind( g_zonename ) ); + subnet = ZoneParser::canonic( subnet ); + stringtok( parts, g_zonename, "." ); + stringtok( subparts, subnet, "." ); + net = g_zonename; + + j = subparts.end(); + while( --j != subparts.begin() ) + { + net = *j + "." + net; + if( !g_nodes[net] ) + { + g_nodes[net] = true; + cout << "dn: "; + for( i = j; i != subparts.end(); i++ ) + { + cout << "dc=" << *i << ","; + } + for( i = parts.begin(); i != parts.end(); i++ ) + { + cout << "dc=" << *i << ","; + } + cout << g_basedn << endl; + + cout << "changetype: add" << endl; + cout << "objectclass: top" << endl; + cout << "objectclass: dcobject" << endl; + cout << "objectclass: domainrelatedobject" << endl; + cout << "dc: " << *j << endl; + cout << "associateddomain: " << net << endl << endl; + } + } + + parts.clear(); stringtok( parts, domain2, "." ); - if( parts[0] == g_zonename ) { - cout << "dn: dc=" << g_zonename << "," << g_basedn << endl; - }else { - cout << "dn: dc=" << parts[0] << ",dc=" << g_zonename << "," << g_basedn << endl; + cout << "dn: "; + for( i = parts.begin(); i != parts.end(); i++ ) + { + cout << "dc=" << *i << ","; } + cout << g_basedn << endl; - if( g_objects[domain2] != true ) + if( !g_objects[domain2] ) { g_objects[domain2] = true; cout << "changetype: add" << endl; cout << "objectclass: top" << endl; - if( parts[0] == g_zonename ) cout << "objectclass: dcobject" << endl; // only necessary for phpgeneral, my web based admin interface - cout << "objectclass: dnsdomain" << endl; + if( domain2 == g_zonename ) { cout << "objectclass: dcobject" << endl; } // only necessary for phpgeneral + cout << "objectclass: dnsdomain2" << endl; cout << "objectclass: domainrelatedobject" << endl; cout << "dc: " << parts[0] << endl; + cout << "dnsttl: " << ttl << endl; cout << "associateddomain: " << domain2 << endl; } else @@ -72,26 +151,19 @@ static void callback( unsigned int domain_id, const string &domain, const string cout << "changetype: modify" << endl; } - if( prio != 0 ) { - cout << qtype << "Record: " << prio << " " << content2 << endl << endl; - } else { - cout << qtype << "Record: " << content2 << endl << endl; - } + cout << qtype << "Record: "; + if( prio != 0 ) { cout << prio << " "; } + cout << content2 << endl << endl; } int main( int argc, char* argv[] ) { - string namedfile = ""; - string zonefile = ""; - vector parts; BindParser BP; ZoneParser ZP; + vector parts; - g_basedn = ""; - g_zonename = ""; - try { #if __GNUC__ >= 3 @@ -101,10 +173,11 @@ int main( int argc, char* argv[] ) args.setCmd( "help", "Provide a helpful message" ); args.setSwitch( "verbose", "Verbose comments on operation" ) = "no"; args.setSwitch( "resume", "Continue after errors" ) = "no"; - args.set( "zone", "Zonefile with $ORIGIN to parse" ) = ""; - args.set( "zone-name", "Specify an $ORIGIN in case it is not present" ) = ""; args.set( "named-conf", "Bind 8 named.conf to parse" ) = ""; + args.set( "zone-file", "Zone file to parse" ) = ""; + args.set( "zone-name", "Specify a zone name if zone is set" ) = ""; args.set( "basedn", "Base DN to store objects below" ) = "dc=example,dc=org"; + args.set( "layout", "Arrange entries as list or tree" ) = "tree"; args.parse( argc, argv ); @@ -116,28 +189,29 @@ int main( int argc, char* argv[] ) } g_basedn = args["basedn"]; - namedfile = args["named-conf"]; - zonefile = args["zone"]; - - ZP.setCallback( &callback ); - BP.setVerbose( args.mustDo( "verbose" ) ); - BP.parse( namedfile.empty() ? "./named.conf" : namedfile ); + ZP.setCallback( &callback_tree ); + if( args["layout"] == "list" ) + { + ZP.setCallback( &callback_list ); + } - if( zonefile.empty() ) + if( !args["named-conf"].empty() ) { + BP.setVerbose( args.mustDo( "verbose" ) ); + BP.parse( args["named-conf"] ); ZP.setDirectory( BP.getDirectory() ); const vector &domains = BP.getDomains(); - for( vector::const_iterator i = domains.begin(); i != domains.end(); ++i ) + for( vector::const_iterator i = domains.begin(); i != domains.end(); i++ ) { try { - g_objects.clear(); - if( i->name != "." && i->name != "localhost" && i->name.substr( i->name.length() - 5, 5 ) != ".arpa" && i->name.substr( i->name.length() - 8, 8 ) != ".ip6.int" ) + if( i->name != "." && i->name != "localhost" && i->name != "0.0.127.in-addr.arpa" ) { cerr << "Parsing file: " << i->filename << ", domain: " << i->name << endl; - stringtok( parts, i->name, "." ); - g_zonename = parts[0]; + g_zonename = i->name; + g_nodes.clear(); + g_objects.clear(); ZP.parse( i->filename, i->name, 0 ); } } @@ -153,11 +227,17 @@ int main( int argc, char* argv[] ) } else { - stringtok( parts, args["zone-name"], "." ); - g_zonename = parts[0]; + if( args["zone-file"].empty() || args["zone-name"].empty() ) + { + cerr << "Error: At least zone-file and zone-name are required" << endl; + return 1; + } + + g_nodes.clear(); g_objects.clear(); + g_zonename = args["zone-name"]; ZP.setDirectory( "." ); - ZP.parse( zonefile, args["zone-name"], 0 ); + ZP.parse( args["zone-file"], args["zone-name"], 0 ); } } catch( AhuException &ae ) diff --git a/pdns/backends/bind/zoneparser2.cc b/pdns/backends/bind/zoneparser2.cc index 7042ad9ad..8b69ef9c0 100644 --- a/pdns/backends/bind/zoneparser2.cc +++ b/pdns/backends/bind/zoneparser2.cc @@ -172,7 +172,7 @@ void ZoneParser::fillRec(const string &qname, const string &qtype, const string rec.qtype=qtype; if(!QType::chartocode(qtype.c_str())) - throw AhuException("Unknown qtype '"+qtype+"' on line "+itoa(d_lineno)); + throw AhuException("Unknown qtype '"+qtype+"' on line "+itoa(d_lineno)+" of file '"+d_filename+"'"); rec.content=content; rec.ttl=ttl; rec.prio=prio; @@ -446,7 +446,7 @@ bool ZoneParser::parseLine(const vector&words, vector&rec) return true; } else { - throw AhuException("Unhandled command '"+words[0]+"' on line "+itoa(d_lineno)+" of "+d_filename); + throw AhuException("Unhandled command '"+words[0]+"' on line "+itoa(d_lineno)+" of '"+d_filename+"'"); } return false; diff --git a/pdns/docs/pdns.sgml b/pdns/docs/pdns.sgml index a4f344082..afa7dc5b6 100644 --- a/pdns/docs/pdns.sgml +++ b/pdns/docs/pdns.sgml @@ -11,7 +11,7 @@ - v2.1 $Date: 2003/11/23 15:14:57 $ + v2.1 $Date: 2003/11/29 16:49:42 $ @@ -82,8 +82,66 @@ file. + Version 2.9.13 + + Some bugfixes, some small features. Only one big bugfix, it appears we are heading for stability! + + + Bug fixes: + + + + allow-axfr-ips did not work for individual IP addresses (bug & fix by Norbert Sendetzky) + + + + + + + Improvements: + + + + Opteron support! Thanks to Jeff Davey for providing a shell on an Opteron. The fixes should + also help PowerDNS on other platforms with a 64 bit userspace. + + + Btw, the PowerDNS team has a strong desire for an Opteron :-) + + + + + pdns_recursor jumbles answers now. This means that you can do poor man's roundrobin + by supplying multiple A, MX or AAAA records for a service, and get a random one on top + each time. Interestingly, this feature appeared out of nowhere, this change was made to the + authoritative code but due to the wonders of code-reuse had an effect on pdns_recursor too. + + + + + Big LDAP cleanup. Support for TLS was added. Zone2LDAP also gained the ability to + generate ldif files containing a tree or a list of entries. (Norbert Sendetzky) + + + + + Zone2sql is now somewhat clearer when reporting malformed line errors - it did not always + include the name of the file causing a problem, especially for big installations. Problem noted + by Thom May. + + + + + pdns_recursor now survives the expiration of all its root records, most often caused by prolonged + disconnection from the net. + + + + + + Version 2.9.12 - + Release rich in features. Work on Verisign oddities, addition of SQLite backend, pdns_recursor maturity. @@ -5581,6 +5639,26 @@ Feb 10 14:16:03 stats: 125784 questions, 13971 cache entries, 309 negative entri + + Q: PowerDNS does not give authoritative answers, how come? + + + A: This is almost always not the case. An authoritative answer is recognized by the 'AA' bit being set. Many tools + prominently print the number of Authority records included in an answer, leading users to conclude that the + absence or presence of these records indicates the authority of an answer. This is not the case. + + + Verily, many misguided country code domain operators have fallen into this trap and demand authority records, even though + these are fluff and quite often misleading. Invite such operators to look at section 6.2.1 of RFC 1034, which shows a correct + authoritative answer without authority records. In fact, none of the non-deprecated authoritative answers shown have authority + records! + + + Sorry for sounding like DJB on this, but we get so many misguided questions about authority.. + + + + Q: Which backend should I use? There are so many! -- 2.49.0