]> granicus.if.org Git - pdns/commitdiff
lots
authorBert Hubert <bert.hubert@netherlabs.nl>
Sat, 29 Nov 2003 16:49:42 +0000 (16:49 +0000)
committerBert Hubert <bert.hubert@netherlabs.nl>
Sat, 29 Nov 2003 16:49:42 +0000 (16:49 +0000)
git-svn-id: svn://svn.powerdns.com/pdns/trunk/pdns@200 d19b8d6e-7fed-0310-83ef-9ca221ded41b

ChangeLog
configure.in
debian/changelog
modules/ldapbackend/ldapbackend.cc
modules/ldapbackend/powerldap.cc
modules/ldapbackend/powerldap.hh
pdns.spec
pdns/backends/bind/zone2ldap.cc
pdns/backends/bind/zoneparser2.cc
pdns/docs/pdns.sgml

index 8e5b596a845430abfbc68ba1f3728417892bbc2d..f7a8f2a2fc3a7bb3f4b777e337bde724bd7c01bf 100644 (file)
--- 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
index 892d5394f83d536006ba2cc35732878937b4f191..118c44dc81731d27e3f2b69ba00e844c2d667d40 100644 (file)
@@ -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 
index d85b4ccfc9d4c62a749584ddea2c4b299f9f746d..596b3c530d84e0792c6d358272716b7a37144d3b 100644 (file)
@@ -1,3 +1,9 @@
+pdns (2.9.13-1) unstable; urgency=low
+
+  * New upstream release
+
+ -- Wichert Akkerman <wakkerma@debian.org>  Sun,  21 Sep 2003 14:59:46 +0200
+
 pdns (2.9.12-1) unstable; urgency=low
 
   * New upstream release
index 34f2387ab82ba8659a9784383dc1e3d8eddc2fdc..aa15959a5a46b7e9272eceb7a4a579527e46b7c4 100644 (file)
@@ -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 &lt )
        {
-               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 &lt )
        {
-               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 &lt )
        {
-               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", "" );
index 584b53f77097ca46a9129243580225f1e1e8ad6f..b90984de319284e2d8e7dda76d574b0c23a77397 100644 (file)
@@ -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<char**> (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<char **>(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<string> 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<string> 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<string> 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;
 }
index 58da8ff9b6fbcfdb04bcb8910c8aca32e6fd7ff6..8ed6e783ae2614004f32ca3eba90ca8ef0ac829e 100644 (file)
@@ -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<string, vector<string> > 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 );
 };
index bdb0490cac98aa52119a4e7c489241e60e623633..d10c064638cc4c7653c3d174d887601e41993f19 100644 (file)
--- 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
index 494f6fc50a6f68c287c61bcb609b414f24c61189..1c7fcabc8c9018028acad8edb05f58c62ade6b64 100644 (file)
@@ -39,32 +39,111 @@ ArgvMap args;
 string g_basedn;
 string g_zonename;
 map<string,bool> g_objects;
+map<string,bool> 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<string> 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<string> parts, subparts;
+       vector<string>::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<string> parts;
        BindParser BP;
        ZoneParser ZP;
+       vector<string> 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<BindDomainInfo> &domains = BP.getDomains();
 
-                       for( vector<BindDomainInfo>::const_iterator i = domains.begin(); i != domains.end(); ++i )
+                       for( vector<BindDomainInfo>::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 )
index 7042ad9ad8370fd03756172d92d6f4f7de6dc71c..8b69ef9c0c1e953cf1fa3287accd2d644dfe3adb 100644 (file)
@@ -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<string>&words, vector<Record>&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;
index a4f344082418e2a3dd5e2c28b9bd1d9100e85a0b..afa7dc5b6c10b0be26ec5fbe2a240a103b1af2d2 100644 (file)
@@ -11,7 +11,7 @@
       </affiliation>
     </author>
     
-    <PubDate>v2.1 $Date: 2003/11/23 15:14:57 $</PubDate>
+    <PubDate>v2.1 $Date: 2003/11/29 16:49:42 $</PubDate>
     
     <Abstract>
        <para>  
        file.
       </para>
 
+    <sect2 id="changelog-2-9-13"><title>Version 2.9.13</title>
+       <para>
+         Some bugfixes, some small features. Only one big bugfix, it appears we are heading for stability!
+       </para>
+       <para>
+         Bug fixes:
+         <itemizedlist>
+           <listitem>
+             <para>
+               <command>allow-axfr-ips</command> did not work for individual IP addresses (bug &amp; fix by Norbert Sendetzky)
+             </para>
+           </listitem>
+         </itemizedlist>
+       </para>
+
+       <para>
+         Improvements:
+         <itemizedlist>
+           <listitem>
+             <para>
+               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.
+             </para>
+             <para>
+               Btw, the PowerDNS team has a strong desire for an Opteron :-)
+             </para>
+           </listitem>
+           <listitem>
+             <para>
+               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.
+             </para>
+           </listitem>
+           <listitem>
+             <para>
+               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)
+             </para>
+           </listitem>
+           <listitem>
+             <para>
+               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.
+             </para>
+           </listitem>
+           <listitem>
+             <para>
+               pdns_recursor now survives the expiration of all its root records, most often caused by prolonged
+               disconnection from the net.
+             </para>
+           </listitem>
+         </itemizedlist>
+       </para>
+      </sect2>
+
     <sect2 id="changelog-2-9-12"><title>Version 2.9.12</title>
-      <para> 
+       <para> 
         Release rich in features. Work on Verisign oddities, addition of SQLite backend, pdns_recursor maturity.
       </para>
       <para>
@@ -5581,6 +5639,26 @@ Feb 10 14:16:03 stats: 125784 questions, 13971 cache entries, 309 negative entri
              </para>
            </listitem>
          </varlistentry>
+         <varlistentry>
+           <term>Q: PowerDNS does not give authoritative answers, how come?</term>
+           <listitem>
+             <para>
+               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.
+             </para>
+             <para>
+               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!
+             </para>
+             <para>
+               Sorry for sounding like DJB on this, but we get so many misguided questions about authority..
+             </para>
+           </listitem>
+         </varlistentry>
+
          <varlistentry>
            <term>Q: Which backend should I use? There are so many!</term>
            <listitem>