Browse Source

Merge branch 'master' into trac1774

Mukund Sivaraman 13 years ago
parent
commit
83d31781cf

+ 8 - 0
ChangeLog

@@ -1,3 +1,11 @@
+451.	[bug]		muks, jinmei
+	libdatasrc: the database-based data source now correctly returns
+	glue records on (not under) a zone cut, such as in the case where
+	the NS name of an NS record is identical to its owner name. (Note:
+	libdatasrc itself doesn't judge what kind of record type can be a
+	"glue"; it's the caller's responsibility.)
+	(Trac #1771, git 483f1075942965f0340291e7ff7dae7806df22af)
+
 450.	[func]*		tomek
 450.	[func]*		tomek
 	b10-dhcp4: DHCPv4 server component is now integrated into
 	b10-dhcp4: DHCPv4 server component is now integrated into
 	BIND10 framework. It can be started from BIND10 (using bindctl)
 	BIND10 framework. It can be started from BIND10 (using bindctl)

+ 188 - 165
doc/guide/bind10-guide.xml

@@ -36,8 +36,8 @@
     <abstract>
     <abstract>
       <para>BIND 10 is a framework that features Domain Name System
       <para>BIND 10 is a framework that features Domain Name System
       (DNS) suite and Dynamic Host Configuration Protocol (DHCP)
       (DNS) suite and Dynamic Host Configuration Protocol (DHCP)
-      servers managed by Internet Systems Consortium (ISC). It
-      includes DNS libraries, modular components for controlling
+      servers with development managed by Internet Systems Consortium (ISC).
+      It includes DNS libraries, modular components for controlling
       authoritative and recursive DNS servers, and experimental DHCPv4
       authoritative and recursive DNS servers, and experimental DHCPv4
       and DHCPv6 servers.
       and DHCPv6 servers.
       </para>
       </para>
@@ -59,6 +59,8 @@
     <section id="acknowledgements">
     <section id="acknowledgements">
       <title>Acknowledgements</title>
       <title>Acknowledgements</title>
 
 
+<!-- TODO: acknowledge all sponsors and CNNIC and CZNIC too -->
+
       <para>ISC would like to acknowledge generous support for
       <para>ISC would like to acknowledge generous support for
       BIND 10 development of DHCPv4 and DHCPv6 components provided
       BIND 10 development of DHCPv4 and DHCPv6 components provided
       by <ulink url="http://www.comcast.com/">Comcast</ulink>.</para>
       by <ulink url="http://www.comcast.com/">Comcast</ulink>.</para>
@@ -72,11 +74,13 @@
     <para>
     <para>
       BIND is the popular implementation of a DNS server, developer
       BIND is the popular implementation of a DNS server, developer
       interfaces, and DNS tools.
       interfaces, and DNS tools.
-      BIND 10 is a rewrite of BIND 9.  BIND 10 is written in C++ and Python
-      and provides a modular environment for serving and maintaining DNS.
+      BIND 10 is a rewrite of BIND 9 and ISC DHCP.
+      BIND 10 is written in C++ and Python and provides a modular
+      environment for serving, maintaining, and developing DNS and DHCP.
       BIND 10 provides a EDNS0- and DNSSEC-capable authoritative
       BIND 10 provides a EDNS0- and DNSSEC-capable authoritative
       DNS server and a caching recursive name server which also
       DNS server and a caching recursive name server which also
       provides forwarding.
       provides forwarding.
+      It also provides experimental DHCPv4 and DHCPv6 servers.
     </para>
     </para>
 
 
     <para>
     <para>
@@ -105,7 +109,7 @@
       <para>
       <para>
         BIND 10 requires at least Python 3.1
         BIND 10 requires at least Python 3.1
         (<ulink url="http://www.python.org/"/>).
         (<ulink url="http://www.python.org/"/>).
-        It has also been tested with Python 3.2.
+        It also works with Python 3.2.
       </para>
       </para>
 
 
       <para>
       <para>
@@ -118,6 +122,7 @@
         BIND 10 uses the log4cplus C++ logging library
         BIND 10 uses the log4cplus C++ logging library
         (<ulink url="http://log4cplus.sourceforge.net/"/>).
         (<ulink url="http://log4cplus.sourceforge.net/"/>).
         It requires at least log4cplus version 1.0.3.
         It requires at least log4cplus version 1.0.3.
+<!-- TODO: It is recommended to use at least version .... -->
       </para>
       </para>
 
 
       <para>
       <para>
@@ -132,9 +137,7 @@
         <command>b10-xfrout</command>, and <command>b10-zonemgr</command>
         <command>b10-xfrout</command>, and <command>b10-zonemgr</command>
         components require the libpython3 library and the Python
         components require the libpython3 library and the Python
         _sqlite3.so module (which is included with Python).
         _sqlite3.so module (which is included with Python).
-        The <command>b10-stats-httpd</command> component uses the
-        Python pyexpat.so module.
-        The Python modules need to be built for the corresponding Python 3.
+        Python modules need to be built for the corresponding Python 3.
       </para>
       </para>
 <!-- TODO: this will change ... -->
 <!-- TODO: this will change ... -->
 
 
@@ -220,8 +223,8 @@
             <simpara>
             <simpara>
               <command>b10-resolver</command> &mdash;
               <command>b10-resolver</command> &mdash;
               Recursive name server.
               Recursive name server.
-              This process handles incoming queries.
-<!-- TODO: -->
+              This process handles incoming DNS queries and provides
+              answers from its cache or by recursively doing remote lookups.
             </simpara>
             </simpara>
           </listitem>
           </listitem>
 
 
@@ -264,15 +267,14 @@
               <command>b10-xfrout</command> &mdash;
               <command>b10-xfrout</command> &mdash;
               Outgoing zone transfer service.
               Outgoing zone transfer service.
               This process is used to handle transfer requests to
               This process is used to handle transfer requests to
-              send a local zone to a remote secondary server,
-              when acting as a master server.
+              send a local zone to a remote secondary server.
             </simpara>
             </simpara>
           </listitem>
           </listitem>
 
 
           <listitem>
           <listitem>
             <simpara>
             <simpara>
               <command>b10-zonemgr</command> &mdash;
               <command>b10-zonemgr</command> &mdash;
-              Secondary manager.
+              Secondary zone manager.
               This process keeps track of timers and other
               This process keeps track of timers and other
               necessary information for BIND 10 to act as a slave server.
               necessary information for BIND 10 to act as a slave server.
             </simpara>
             </simpara>
@@ -282,8 +284,8 @@
       </para>
       </para>
 
 
       <para>
       <para>
-        These are ran automatically by <command>bind10</command>
-        and do not need to be run manually.
+        These are ran by <command>bind10</command>
+        and do not need to be manually started independently.
       </para>
       </para>
 
 
     </section>
     </section>
@@ -298,7 +300,7 @@
           <listitem>
           <listitem>
             <simpara>
             <simpara>
               <command>bindctl</command> &mdash;
               <command>bindctl</command> &mdash;
-              interactive administration interface.
+              Interactive administration interface.
               This is a low-level command-line tool which allows
               This is a low-level command-line tool which allows
               a developer or an experienced administrator to control
               a developer or an experienced administrator to control
               BIND 10.
               BIND 10.
@@ -307,7 +309,7 @@
           <listitem>
           <listitem>
             <simpara>
             <simpara>
               <command>b10-loadzone</command> &mdash;
               <command>b10-loadzone</command> &mdash;
-              zone file loader.
+              Zone file loader.
               This tool will load standard masterfile-format zone files into
               This tool will load standard masterfile-format zone files into
               BIND 10.
               BIND 10.
             </simpara>
             </simpara>
@@ -315,7 +317,7 @@
           <listitem>
           <listitem>
             <simpara>
             <simpara>
               <command>b10-cmdctl-usermgr</command> &mdash;
               <command>b10-cmdctl-usermgr</command> &mdash;
-              user access control.
+              User access control.
               This tool allows an administrator to authorize additional users
               This tool allows an administrator to authorize additional users
               to manage BIND 10.
               to manage BIND 10.
             </simpara>
             </simpara>
@@ -358,6 +360,7 @@ var/
       for C++ and Python for the message bus, configuration backend,
       for C++ and Python for the message bus, configuration backend,
       and, of course, DNS. These include detailed developer
       and, of course, DNS. These include detailed developer
       documentation and code examples.
       documentation and code examples.
+<!-- TODO: DHCP also but no Python yet. -->
 <!-- TODO point to this -->
 <!-- TODO point to this -->
     </para>
     </para>
 
 
@@ -366,12 +369,100 @@ var/
   <chapter id="installation">
   <chapter id="installation">
     <title>Installation</title>
     <title>Installation</title>
 
 
+    <section id="packages">
+      <title>Packages</title>
+
+      <para>
+        Some operating systems or softare package vendors may
+        provide ready-to-use, pre-built software packages for
+        the BIND 10 suite.
+        Installing a pre-built package means you do not need to
+        install build-only prerequisites and do not need to
+        <emphasis>make</emphasis> the software.
+      </para>
+
+      <para>
+        FreeBSD ports, NetBSD pkgsrc, and Debian
+        <emphasis>testing</emphasis> package collections provide
+        all the prerequisite packages.
+      </para>
+    </section>
+
+    <section id="install-hierarchy">
+      <title>Install Hierarchy</title>
+      <para>
+        The following is the standard, common layout of the
+        complete BIND 10 installation:
+        <itemizedlist>
+          <listitem>
+           <simpara>
+              <filename>bin/</filename> &mdash;
+              general tools and diagnostic clients.
+            </simpara>
+          </listitem>
+          <listitem>
+          <simpara>
+            <filename>etc/bind10-devel/</filename> &mdash;
+            configuration files.
+          </simpara>
+          </listitem>
+          <listitem>
+            <simpara>
+              <filename>lib/</filename> &mdash;
+              libraries and python modules.
+            </simpara>
+          </listitem>
+          <listitem>
+            <simpara>
+              <filename>libexec/bind10-devel/</filename> &mdash;
+              executables that a user wouldn't normally run directly and
+              are not run independently.
+              These are the BIND 10 modules which are daemons started by
+              the <command>bind10</command> tool.
+            </simpara>
+          </listitem>
+          <listitem>
+            <simpara>
+              <filename>sbin/</filename> &mdash;
+              commands used by the system administrator.
+            </simpara>
+          </listitem>
+          <listitem>
+            <simpara>
+              <filename>share/bind10-devel/</filename> &mdash;
+              configuration specifications.
+            </simpara>
+          </listitem>
+          <listitem>
+            <simpara>
+              <filename>share/doc/bind10-devel/</filename> &mdash;
+              this guide and other supplementary documentation.
+            </simpara>
+          </listitem>
+          <listitem>
+            <simpara>
+              <filename>share/man/</filename> &mdash;
+              manual pages (online documentation).
+            </simpara>
+          </listitem>
+          <listitem>
+            <simpara>
+              <filename>var/bind10-devel/</filename> &mdash;
+              data source and configuration databases.
+            </simpara>
+          </listitem>
+        </itemizedlist>
+      </para>
+    </section>
+
     <section id="build-requirements">
     <section id="build-requirements">
       <title>Building Requirements</title>
       <title>Building Requirements</title>
 
 
         <para>
         <para>
-          In addition to the run-time requirements, building BIND 10
-          from source code requires various development include headers.
+          In addition to the run-time requirements (listed in
+          <xref linkend="required-software"/>), building BIND 10
+          from source code requires various development include headers and
+          program development tools.
         </para>
         </para>
 
 
         <note>
         <note>
@@ -415,7 +506,7 @@ as a dependency earlier -->
         </para>
         </para>
 
 
         <para>
         <para>
-          Visit the wiki at <ulink
+          Visit the user-contributed wiki at <ulink
           url="http://bind10.isc.org/wiki/SystemSpecificNotes" />
           url="http://bind10.isc.org/wiki/SystemSpecificNotes" />
           for system-specific installation tips.
           for system-specific installation tips.
         </para>
         </para>
@@ -484,7 +575,7 @@ as a dependency earlier -->
         </listitem>
         </listitem>
 
 
         <listitem>
         <listitem>
-
+<!-- TODO: this is wrong; b10-auth is not started by default any more -->
          <para>Test it; for example:
          <para>Test it; for example:
             <screen>$ <userinput>dig @127.0.0.1 -c CH -t TXT authors.bind</userinput></screen>
             <screen>$ <userinput>dig @127.0.0.1 -c CH -t TXT authors.bind</userinput></screen>
          </para>
          </para>
@@ -510,10 +601,10 @@ as a dependency earlier -->
       <title>Installation from source</title>
       <title>Installation from source</title>
       <para>
       <para>
         BIND 10 is open source software written in C++ and Python.
         BIND 10 is open source software written in C++ and Python.
-        It is freely available in source code form from ISC via
-        the Git code revision control system or as a downloadable
-        tar file. It may also be available in pre-compiled ready-to-use
-        packages from operating system vendors.
+        It is freely available in source code form from ISC as a
+        downloadable tar file or via BIND 10's Git code revision control
+        service. (It may also be available in pre-compiled ready-to-use
+        packages from operating system vendors.)
       </para>
       </para>
 
 
       <section>
       <section>
@@ -541,7 +632,7 @@ as a dependency earlier -->
 
 
         <note>
         <note>
           <para>
           <para>
-            When using source code retrieved via Git additional
+            When using source code retrieved via Git, additional
             software will be required:  automake (v1.11 or newer),
             software will be required:  automake (v1.11 or newer),
             libtoolize, and autoconf (2.59 or newer).
             libtoolize, and autoconf (2.59 or newer).
             These may need to be installed.
             These may need to be installed.
@@ -549,11 +640,12 @@ as a dependency earlier -->
         </note>
         </note>
 
 
         <para>
         <para>
-          The latest development code, including temporary experiments
-          and un-reviewed code, is available via the BIND 10 code revision
+          The latest development code (and temporary experiments
+          and un-reviewed code) is available via the BIND 10 code revision
           control system. This is powered by Git and all the BIND 10
           control system. This is powered by Git and all the BIND 10
           development is public.
           development is public.
-          The leading development is done in the <quote>master</quote>.
+          The leading development is done in the <quote>master</quote>
+          branch.
         </para>
         </para>
         <para>
         <para>
           The code can be checked out from
           The code can be checked out from
@@ -566,8 +658,8 @@ as a dependency earlier -->
         <para>
         <para>
           When checking out the code from
           When checking out the code from
           the code version control system, it doesn't include the
           the code version control system, it doesn't include the
-          generated configure script, Makefile.in files, nor the
-          related configure files.
+          generated configure script, Makefile.in files, nor their
+          related build files.
           They can be created by running <command>autoreconf</command>
           They can be created by running <command>autoreconf</command>
           with the <option>--install</option> switch.
           with the <option>--install</option> switch.
           This will run <command>autoconf</command>,
           This will run <command>autoconf</command>,
@@ -591,7 +683,7 @@ as a dependency earlier -->
         </para>
         </para>
         <para>
         <para>
           Run <command>./configure</command> with the <option>--help</option>
           Run <command>./configure</command> with the <option>--help</option>
-          switch to view the different options. The commonly-used options are:
+          switch to view the different options. Some commonly-used options are:
 
 
           <variablelist>
           <variablelist>
 
 
@@ -679,65 +771,6 @@ as a dependency earlier -->
 
 
   <!-- TODO: tests -->
   <!-- TODO: tests -->
 
 
-      <section>
-        <title>Install Hierarchy</title>
-        <para>
-          The following is the layout of the complete BIND 10 installation:
-          <itemizedlist>
-            <listitem>
-              <simpara>
-                <filename>bin/</filename> &mdash;
-                general tools and diagnostic clients.
-              </simpara>
-            </listitem>
-            <listitem>
-            <simpara>
-              <filename>etc/bind10-devel/</filename> &mdash;
-              configuration files.
-            </simpara>
-            </listitem>
-            <listitem>
-              <simpara>
-                <filename>lib/</filename> &mdash;
-                libraries and python modules.
-              </simpara>
-            </listitem>
-            <listitem>
-              <simpara>
-                <filename>libexec/bind10-devel/</filename> &mdash;
-                executables that a user wouldn't normally run directly and
-                are not run independently.
-                These are the BIND 10 modules which are daemons started by
-                the <command>bind10</command> tool.
-              </simpara>
-            </listitem>
-            <listitem>
-              <simpara>
-                <filename>sbin/</filename> &mdash;
-                commands used by the system administrator.
-              </simpara>
-            </listitem>
-            <listitem>
-              <simpara>
-                <filename>share/bind10-devel/</filename> &mdash;
-                configuration specifications.
-              </simpara>
-            </listitem>
-            <listitem>
-              <simpara>
-                <filename>share/man/</filename> &mdash;
-                manual pages (online documentation).
-              </simpara>
-            </listitem>
-            <listitem>
-              <simpara>
-                <filename>var/bind10-devel/</filename> &mdash;
-                data source and configuration databases.
-              </simpara>
-            </listitem>
-          </itemizedlist>
-        </para>
-      </section>
     </section>
     </section>
 
 
   <!--
   <!--
@@ -775,8 +808,9 @@ as a dependency earlier -->
       The <command>b10-cfgmgr</command> daemon is always needed by every
       The <command>b10-cfgmgr</command> daemon is always needed by every
       module, if only to send information about themselves somewhere,
       module, if only to send information about themselves somewhere,
       but more importantly to ask about their own settings, and
       but more importantly to ask about their own settings, and
-      about other modules. The <command>b10-sockcreator</command> will
-      allocate sockets for the rest of the system.
+      about other modules. The <command>b10-sockcreator</command> daemon
+      helps allocate Internet addresses and ports as needed for BIND 10
+      network services.
     </para>
     </para>
 
 
     <para>
     <para>
@@ -807,23 +841,22 @@ as a dependency earlier -->
 
 
     </section>
     </section>
     <section id="bind10.config">
     <section id="bind10.config">
-      <title>Configuration of started processes</title>
-      <para>
-        The processes to be started can be configured, with the exception
-        of the <command>b10-sockcreator</command>, <command>b10-msgq</command>
-        and <command>b10-cfgmgr</command>.
-      </para>
+      <title>Configuration to start processes</title>
 
 
       <para>
       <para>
-        The configuration is in the Boss/components section. Each element
-        represents one component, which is an abstraction of a process
-        (currently there's also one component which doesn't represent
-        a process).
+	The processes to be used can be configured for
+	<command>bind10</command> to start, with the exception
+	of the required <command>b10-sockcreator</command>,
+	<command>b10-msgq</command> and <command>b10-cfgmgr</command>
+	components.
+	The configuration is in the <varname>Boss/components</varname>
+	section. Each element represents one component, which is
+	an abstraction of a process.
       </para>
       </para>
 
 
       <para>
       <para>
-        To add a process to the set, let's say the resolver (which not started
-        by default), you would do this:
+	To add a process to the set, let's say the resolver (which
+	is not started by default), you would do this:
         <screen>&gt; <userinput>config add Boss/components b10-resolver</userinput>
         <screen>&gt; <userinput>config add Boss/components b10-resolver</userinput>
 &gt; <userinput>config set Boss/components/b10-resolver/special resolver</userinput>
 &gt; <userinput>config set Boss/components/b10-resolver/special resolver</userinput>
 &gt; <userinput>config set Boss/components/b10-resolver/kind needed</userinput>
 &gt; <userinput>config set Boss/components/b10-resolver/kind needed</userinput>
@@ -831,27 +864,32 @@ as a dependency earlier -->
 &gt; <userinput>config commit</userinput></screen></para>
 &gt; <userinput>config commit</userinput></screen></para>
 
 
       <para>
       <para>
-        Now, what it means. We add an entry called b10-resolver. It is both a
-        name used to reference this component in the configuration and the
-        name of the process to start. Then we set some parameters on how to
-        start it.
+	Now, what it means. We add an entry called
+	<quote>b10-resolver</quote>. It is both a name used to
+	reference this component in the configuration and the name
+	of the process to start. Then we set some parameters on
+	how to start it.
       </para>
       </para>
 
 
       <para>
       <para>
-        The special one is for components that need some kind of special care
-        during startup or shutdown. Unless specified, the component is started
-        in usual way. This is the list of components that need to be started
-        in a special way, with the value of special used for them:
+	The <varname>special</varname> setting is for components
+	that need some kind of special care during startup or
+	shutdown. Unless specified, the component is started in a
+	usual way. This is the list of components that need to be
+	started in a special way, with the value of special used
+	for them:
+<!-- TODO: this still doesn't explain why they are special -->
         <table>
         <table>
+          <title>Special startup components</title>
           <tgroup cols='3' align='left'>
           <tgroup cols='3' align='left'>
           <colspec colname='component'/>
           <colspec colname='component'/>
           <colspec colname='special'/>
           <colspec colname='special'/>
           <colspec colname='description'/>
           <colspec colname='description'/>
           <thead><row><entry>Component</entry><entry>Special</entry><entry>Description</entry></row></thead>
           <thead><row><entry>Component</entry><entry>Special</entry><entry>Description</entry></row></thead>
           <tbody>
           <tbody>
-            <row><entry>b10-auth</entry><entry>auth</entry><entry>Authoritative server</entry></row>
-            <row><entry>b10-resolver</entry><entry>resolver</entry><entry>The resolver</entry></row>
-            <row><entry>b10-cmdctl</entry><entry>cmdctl</entry><entry>The command control (remote control interface)</entry></row>
+            <row><entry>b10-auth</entry><entry>auth</entry><entry>Authoritative DNS server</entry></row>
+            <row><entry>b10-resolver</entry><entry>resolver</entry><entry>DNS resolver</entry></row>
+            <row><entry>b10-cmdctl</entry><entry>cmdctl</entry><entry>Command control (remote control interface)</entry></row>
             <!-- TODO Either add xfrin and xfrout as well or clean up the workarounds in boss before the release -->
             <!-- TODO Either add xfrin and xfrout as well or clean up the workarounds in boss before the release -->
           </tbody>
           </tbody>
           </tgroup>
           </tgroup>
@@ -859,32 +897,34 @@ as a dependency earlier -->
       </para>
       </para>
 
 
       <para>
       <para>
-        The kind specifies how a failure of the component should
-        be handled.  If it is set to <quote>dispensable</quote>
-        (the default unless you set something else), it will get
-        started again if it fails. If it is set to <quote>needed</quote>
-        and it fails at startup, the whole <command>bind10</command>
-        shuts down and exits with error exit code. But if it fails
-        some time later, it is just started again. If you set it
-        to <quote>core</quote>, you indicate that the system is
-        not usable without the component and if such component
-        fails, the system shuts down no matter when the failure
-        happened.  This is the behaviour of the core components
-        (the ones you can't turn off), but you can declare any
-        other components as core as well if you wish (but you can
-        turn these off, they just can't fail).
+	The <varname>kind</varname> specifies how a failure of the
+	component should be handled.  If it is set to
+	<quote>dispensable</quote> (the default unless you set
+	something else), it will get started again if it fails. If
+	it is set to <quote>needed</quote> and it fails at startup,
+	the whole <command>bind10</command> shuts down and exits
+	with an error exit code. But if it fails some time later, it
+	is just started again. If you set it to <quote>core</quote>,
+	you indicate that the system is not usable without the
+	component and if such component fails, the system shuts
+	down no matter when the failure happened.  This is the
+	behaviour of the core components (the ones you can't turn
+	off), but you can declare any other components as core as
+	well if you wish (but you can turn these off, they just
+	can't fail).
       </para>
       </para>
 
 
       <para>
       <para>
-        The priority defines order in which the components should start.
-        The ones with higher number are started sooner than the ones with
-        lower ones. If you don't set it, 0 (zero) is used as the priority.
-        Usually, leaving it at the default is enough.
+	The <varname>priority</varname> defines order in which the
+	components should start.  The ones with higher numbers are
+	started sooner than the ones with lower ones. If you don't
+	set it, 0 (zero) is used as the priority.  Usually, leaving
+	it at the default is enough.
       </para>
       </para>
 
 
       <para>
       <para>
         There are other parameters we didn't use in our example.
         There are other parameters we didn't use in our example.
-        One of them is <quote>address</quote>. It is the address
+        One of them is <varname>address</varname>. It is the address
         used by the component on the <command>b10-msgq</command>
         used by the component on the <command>b10-msgq</command>
         message bus. The special components already know their
         message bus. The special components already know their
         address, but the usual ones don't. The address is by
         address, but the usual ones don't. The address is by
@@ -900,25 +940,17 @@ address, but the usual ones don't." mean? -->
 <!-- TODO: document params when is enabled -->
 <!-- TODO: document params when is enabled -->
 
 
       <para>
       <para>
-        The last one is process. It is the name of the process to be started.
-        It defaults to the name of the component if not set, but you can use
-        this to override it.
+	The last one is <varname>process</varname>. It is the name
+	of the process to be started.  It defaults to the name of
+	the component if not set, but you can use this to override
+	it. (The special components also already know their
+        executable name.)
       </para>
       </para>
 
 
       <!-- TODO Add parameters when they work, not implemented yet-->
       <!-- TODO Add parameters when they work, not implemented yet-->
 
 
       <note>
       <note>
         <para>
         <para>
-          This system allows you to start the same component multiple times
-          (by including it in the configuration with different names, but the
-          same process setting). However, the rest of the system doesn't expect
-          such a situation, so it would probably not do what you want. Such
-          support is yet to be implemented.
-        </para>
-      </note>
-
-      <note>
-        <para>
           The configuration is quite powerful, but that includes
           The configuration is quite powerful, but that includes
           a lot of space for mistakes. You could turn off the
           a lot of space for mistakes. You could turn off the
           <command>b10-cmdctl</command>, but then you couldn't
           <command>b10-cmdctl</command>, but then you couldn't
@@ -938,7 +970,7 @@ address, but the usual ones don't." mean? -->
       </note>
       </note>
       <para>
       <para>
         It is possible to start some components multiple times (currently
         It is possible to start some components multiple times (currently
-        <command>b10-auth</command> and <command>b10-resolzer</command>).
+        <command>b10-auth</command> and <command>b10-resolver</command>).
         You might want to do that to gain more performance (each one uses only
         You might want to do that to gain more performance (each one uses only
         single core). Just put multiple entries under different names, like
         single core). Just put multiple entries under different names, like
         this, with the same config:
         this, with the same config:
@@ -953,6 +985,9 @@ address, but the usual ones don't." mean? -->
         server will keep its own copy of in-memory data and there could be
         server will keep its own copy of in-memory data and there could be
         problems with locking the sqlite database, if used. The configuration
         problems with locking the sqlite database, if used. The configuration
         might be changed to something more convenient in future.
         might be changed to something more convenient in future.
+	Other components don't expect such a situation, so it would
+	probably not do what you want. Such support is yet to be
+	implemented.
       </para>
       </para>
     </section>
     </section>
 
 
@@ -977,23 +1012,11 @@ address, but the usual ones don't." mean? -->
       <para>
       <para>
         Administrators do not communicate directly with the
         Administrators do not communicate directly with the
         <command>b10-msgq</command> daemon.
         <command>b10-msgq</command> daemon.
-        By default, BIND 10 uses port 9912 for the
-        <command>b10-msgq</command> service.
-        It listens on 127.0.0.1.
+        By default, BIND 10 uses a UNIX domain socket file named
+        <filename>/usr/local/var/bind10-devel/msg_socket</filename>
+        for this interprocess communication.
       </para>
       </para>
 
 
-<!-- TODO: this is broken, see Trac #111
-      <para>
-        To select an alternate port for the <command>b10-msgq</command> to
-        use, run <command>bind10</command> specifying the option:
-        <screen> $ <userinput>bind10 -TODO-msgq-port 9912</userinput></screen>
-      </para>
--->
-
-<!-- TODO: upcoming plans:
-Unix domain sockets
--->
-
   </chapter>
   </chapter>
 
 
   <chapter id="cfgmgr">
   <chapter id="cfgmgr">

+ 3 - 0
src/bin/auth/auth_messages.mes

@@ -110,6 +110,9 @@ look into the cause and address the issue.  The log message includes
 the client's address (and port), and the error message sent from the
 the client's address (and port), and the error message sent from the
 lower layer that detects the failure.
 lower layer that detects the failure.
 
 
+% AUTH_RECEIVED_NOTIFY received incoming NOTIFY for zone name %1, zone class %2
+This is a debug message reporting that an incoming NOTIFY was received.
+
 % AUTH_NOTIFY_QUESTIONS invalid number of questions (%1) in incoming NOTIFY
 % AUTH_NOTIFY_QUESTIONS invalid number of questions (%1) in incoming NOTIFY
 This debug message is logged by the authoritative server when it receives
 This debug message is logged by the authoritative server when it receives
 a NOTIFY packet that contains zero or more than one question. (A valid
 a NOTIFY packet that contains zero or more than one question. (A valid

+ 3 - 0
src/bin/auth/auth_srv.cc

@@ -828,6 +828,9 @@ AuthSrvImpl::processNotify(const IOMessage& io_message, Message& message,
         return (false);
         return (false);
     }
     }
 
 
+    LOG_DEBUG(auth_logger, DBG_AUTH_DETAIL, AUTH_RECEIVED_NOTIFY)
+      .arg(question->getName()).arg(question->getClass());
+
     const string remote_ip_address =
     const string remote_ip_address =
         io_message.getRemoteEndpoint().getAddress().toText();
         io_message.getRemoteEndpoint().getAddress().toText();
     static const string command_template_start =
     static const string command_template_start =

+ 1 - 7
src/bin/msgq/msgq.xml

@@ -20,7 +20,7 @@
 <refentry>
 <refentry>
 
 
   <refentryinfo>
   <refentryinfo>
-    <date>August 4, 2010</date>
+    <date>June 25, 2012</date>
   </refentryinfo>
   </refentryinfo>
 
 
   <refmeta>
   <refmeta>
@@ -92,10 +92,6 @@
     </para>
     </para>
 
 
     <para>
     <para>
-      It listens on 127.0.0.1.
-    </para>
-
-    <para>
       The <command>b10-msgq</command> daemon may be cleanly stopped by
       The <command>b10-msgq</command> daemon may be cleanly stopped by
       sending the SIGTERM signal to the process.
       sending the SIGTERM signal to the process.
       This shutdown does not notify the subscribers.
       This shutdown does not notify the subscribers.
@@ -168,5 +164,3 @@
  - End:
  - End:
 -->
 -->
 
 
-
-

+ 4 - 0
src/bin/xfrin/xfrin.py.in

@@ -889,6 +889,10 @@ class XfrinConnection(asyncore.dispatcher):
             req_str = 'IXFR' if request_type == RRType.IXFR() else 'AXFR'
             req_str = 'IXFR' if request_type == RRType.IXFR() else 'AXFR'
             if check_soa:
             if check_soa:
                 self._check_soa_serial()
                 self._check_soa_serial()
+                self.close()
+                self.init_socket()
+                if not self.connect_to_master():
+                    raise XfrinException('Unable to reconnect to master')
 
 
             logger.info(XFRIN_XFR_TRANSFER_STARTED, req_str, self.zone_str())
             logger.info(XFRIN_XFR_TRANSFER_STARTED, req_str, self.zone_str())
             self._send_query(self._request_type)
             self._send_query(self._request_type)

+ 3 - 0
src/bin/xfrout/xfrout.py.in

@@ -952,6 +952,9 @@ class XfroutServer:
     def _start_notifier(self):
     def _start_notifier(self):
         datasrc = self._unix_socket_server.get_db_file()
         datasrc = self._unix_socket_server.get_db_file()
         self._notifier = notify_out.NotifyOut(datasrc)
         self._notifier = notify_out.NotifyOut(datasrc)
+        if 'also_notify' in self._config_data:
+            for slave in self._config_data['also_notify']:
+                self._notifier.add_slave(slave['address'], slave['port'])
         self._notifier.dispatcher()
         self._notifier.dispatcher()
 
 
     def send_notify(self, zone_name, zone_class):
     def send_notify(self, zone_name, zone_class):

+ 27 - 0
src/bin/xfrout/xfrout.spec.pre.in

@@ -21,6 +21,33 @@
          }
          }
        },
        },
        {
        {
+         "item_name": "also_notify",
+         "item_type": "list",
+         "item_optional": true,
+         "item_default": [],
+         "list_item_spec":
+         {
+             "item_name": "also_notify_element",
+             "item_type": "map",
+             "item_optional": true,
+             "item_default": {},
+             "map_item_spec": [
+               {
+                   "item_name": "address",
+                   "item_type": "string",
+                   "item_optional": false,
+                   "item_default": ""
+               },
+               {
+                   "item_name": "port",
+                   "item_type": "integer",
+                   "item_optional": false,
+                   "item_default": 0
+               }
+             ]
+         }
+       },
+       {
          "item_name": "zone_config",
          "item_name": "zone_config",
          "item_type": "list",
          "item_type": "list",
          "item_optional": true,
          "item_optional": true,

+ 22 - 35
src/lib/datasrc/database.cc

@@ -179,8 +179,7 @@ private:
 
 
 DatabaseClient::Finder::FoundRRsets
 DatabaseClient::Finder::FoundRRsets
 DatabaseClient::Finder::getRRsets(const string& name, const WantedTypes& types,
 DatabaseClient::Finder::getRRsets(const string& name, const WantedTypes& types,
-                                  bool check_ns, const string* construct_name,
-                                  bool any,
+                                  const string* construct_name, bool any,
                                   DatabaseAccessor::IteratorContextPtr context)
                                   DatabaseAccessor::IteratorContextPtr context)
 {
 {
     RRsigStore sig_store;
     RRsigStore sig_store;
@@ -204,9 +203,7 @@ DatabaseClient::Finder::getRRsets(const string& name, const WantedTypes& types,
     const Name construct_name_object(*construct_name);
     const Name construct_name_object(*construct_name);
 
 
     bool seen_cname(false);
     bool seen_cname(false);
-    bool seen_ds(false);
     bool seen_other(false);
     bool seen_other(false);
-    bool seen_ns(false);
 
 
     while (context->getNext(columns)) {
     while (context->getNext(columns)) {
         // The domain is not empty
         // The domain is not empty
@@ -249,16 +246,12 @@ DatabaseClient::Finder::getRRsets(const string& name, const WantedTypes& types,
 
 
             if (cur_type == RRType::CNAME()) {
             if (cur_type == RRType::CNAME()) {
                 seen_cname = true;
                 seen_cname = true;
-            } else if (cur_type == RRType::NS()) {
-                seen_ns = true;
-            } else if (cur_type == RRType::DS()) {
-                seen_ds = true;
             } else if (cur_type != RRType::RRSIG() &&
             } else if (cur_type != RRType::RRSIG() &&
                        cur_type != RRType::NSEC3() &&
                        cur_type != RRType::NSEC3() &&
                        cur_type != RRType::NSEC()) {
                        cur_type != RRType::NSEC()) {
                 // NSEC and RRSIG can coexist with anything, otherwise
                 // NSEC and RRSIG can coexist with anything, otherwise
                 // we've seen something that can't live together with potential
                 // we've seen something that can't live together with potential
-                // CNAME or NS
+                // CNAME.
                 //
                 //
                 // NSEC3 lives in separate namespace from everything, therefore
                 // NSEC3 lives in separate namespace from everything, therefore
                 // we just ignore it here for these checks as well.
                 // we just ignore it here for these checks as well.
@@ -278,14 +271,10 @@ DatabaseClient::Finder::getRRsets(const string& name, const WantedTypes& types,
                       RDATA_COLUMN]);
                       RDATA_COLUMN]);
         }
         }
     }
     }
-    if (seen_cname && (seen_other || seen_ns || seen_ds)) {
+    if (seen_cname && seen_other) {
         isc_throw(DataSourceError, "CNAME shares domain " << name <<
         isc_throw(DataSourceError, "CNAME shares domain " << name <<
                   " with something else");
                   " with something else");
     }
     }
-    if (check_ns && seen_ns && seen_other) {
-        isc_throw(DataSourceError, "NS shares domain " << name <<
-                  " with something else");
-    }
     // Add signatures to all found RRsets
     // Add signatures to all found RRsets
     for (std::map<RRType, RRsetPtr>::iterator i(result.begin());
     for (std::map<RRType, RRsetPtr>::iterator i(result.begin());
          i != result.end(); ++ i) {
          i != result.end(); ++ i) {
@@ -455,20 +444,20 @@ DatabaseClient::Finder::findDelegationPoint(const isc::dns::Name& name,
     for (int i = remove_labels; i > 0; --i) {
     for (int i = remove_labels; i > 0; --i) {
         const Name superdomain(name.split(i));
         const Name superdomain(name.split(i));
 
 
-        // Note if this is the origin. (We don't count NS records at the origin
-        // as a delegation so this controls whether NS RRs are included in
-        // the results of some searches.)
-        const bool not_origin = (i != remove_labels);
-
         // Look if there's NS or DNAME at this point of the tree, but ignore
         // Look if there's NS or DNAME at this point of the tree, but ignore
         // the NS RRs at the apex of the zone.
         // the NS RRs at the apex of the zone.
         const FoundRRsets found = getRRsets(superdomain.toText(),
         const FoundRRsets found = getRRsets(superdomain.toText(),
-                                            DELEGATION_TYPES(), not_origin);
+                                            DELEGATION_TYPES());
         if (found.first) {
         if (found.first) {
             // This node contains either NS or DNAME RRs so it does exist.
             // This node contains either NS or DNAME RRs so it does exist.
             const FoundIterator nsi(found.second.find(RRType::NS()));
             const FoundIterator nsi(found.second.find(RRType::NS()));
             const FoundIterator dni(found.second.find(RRType::DNAME()));
             const FoundIterator dni(found.second.find(RRType::DNAME()));
 
 
+            // Note if this is the origin. (We don't count NS records at the
+            // origin as a delegation so this controls whether NS RRs are
+            // included in the results of some searches.)
+            const bool not_origin = (i != remove_labels);
+
             // An optimisation.  We know that there is an exact match for
             // An optimisation.  We know that there is an exact match for
             // something at this point in the tree so remember it.  If we have
             // something at this point in the tree so remember it.  If we have
             // to do a wildcard search, as we search upwards through the tree
             // to do a wildcard search, as we search upwards through the tree
@@ -477,7 +466,7 @@ DatabaseClient::Finder::findDelegationPoint(const isc::dns::Name& name,
             last_known = superdomain.getLabelCount();
             last_known = superdomain.getLabelCount();
 
 
             if (glue_ok && !first_ns && not_origin &&
             if (glue_ok && !first_ns && not_origin &&
-                    nsi != found.second.end()) {
+                nsi != found.second.end()) {
                 // If we are searching for glue ("glue OK" mode), store the
                 // If we are searching for glue ("glue OK" mode), store the
                 // highest NS record that we find that is not the apex.  This
                 // highest NS record that we find that is not the apex.  This
                 // is another optimisation for later, where we need the
                 // is another optimisation for later, where we need the
@@ -590,8 +579,9 @@ DatabaseClient::Finder::findWildcardMatch(
         // TODO Add a check for DNAME, as DNAME wildcards are discouraged (see
         // TODO Add a check for DNAME, as DNAME wildcards are discouraged (see
         // RFC 4592 section 4.4).
         // RFC 4592 section 4.4).
         // Search for a match.  The types are the same as with original query.
         // Search for a match.  The types are the same as with original query.
-        FoundRRsets found = getRRsets(wildcard, final_types, true,
-                                      &construct_name, type == RRType::ANY());
+        const FoundRRsets found = getRRsets(wildcard, final_types,
+                                            &construct_name,
+                                            type == RRType::ANY());
         if (found.first) {
         if (found.first) {
             // Found something - but what?
             // Found something - but what?
 
 
@@ -694,7 +684,7 @@ DatabaseClient::Finder::FindDNSSECContext::probe() {
             // such cases).
             // such cases).
             const string origin = finder_.getOrigin().toText();
             const string origin = finder_.getOrigin().toText();
             const FoundRRsets nsec3_found =
             const FoundRRsets nsec3_found =
-                finder_.getRRsets(origin, NSEC3PARAM_TYPES(), false);
+                finder_.getRRsets(origin, NSEC3PARAM_TYPES());
             const FoundIterator nfi=
             const FoundIterator nfi=
                 nsec3_found.second.find(RRType::NSEC3PARAM());
                 nsec3_found.second.find(RRType::NSEC3PARAM());
             is_nsec3_ = (nfi != nsec3_found.second.end());
             is_nsec3_ = (nfi != nsec3_found.second.end());
@@ -705,7 +695,7 @@ DatabaseClient::Finder::FindDNSSECContext::probe() {
             // described in Section 10.4 of RFC 5155.
             // described in Section 10.4 of RFC 5155.
             if (!is_nsec3_) {
             if (!is_nsec3_) {
                 const FoundRRsets nsec_found =
                 const FoundRRsets nsec_found =
-                    finder_.getRRsets(origin, NSEC_TYPES(), false);
+                    finder_.getRRsets(origin, NSEC_TYPES());
                 const FoundIterator nfi =
                 const FoundIterator nfi =
                     nsec_found.second.find(RRType::NSEC());
                     nsec_found.second.find(RRType::NSEC());
                 is_nsec_ = (nfi != nsec_found.second.end());
                 is_nsec_ = (nfi != nsec_found.second.end());
@@ -757,10 +747,8 @@ DatabaseClient::Finder::FindDNSSECContext::getDNSSECRRset(const Name &name,
     try {
     try {
         const Name& nsec_name =
         const Name& nsec_name =
             covering ? finder_.findPreviousName(name) : name;
             covering ? finder_.findPreviousName(name) : name;
-        const bool need_nscheck = (nsec_name != finder_.getOrigin());
         const FoundRRsets found = finder_.getRRsets(nsec_name.toText(),
         const FoundRRsets found = finder_.getRRsets(nsec_name.toText(),
-                                                    NSEC_TYPES(),
-                                                    need_nscheck);
+                                                    NSEC_TYPES());
         const FoundIterator nci = found.second.find(RRType::NSEC());
         const FoundIterator nci = found.second.find(RRType::NSEC());
         if (nci != found.second.end()) {
         if (nci != found.second.end()) {
             return (nci->second);
             return (nci->second);
@@ -984,16 +972,15 @@ DatabaseClient::Finder::findInternal(const Name& name, const RRType& type,
     // - Requested name is a delegation point (NS only but not at the zone
     // - Requested name is a delegation point (NS only but not at the zone
     //   apex - DNAME is ignored here as it redirects DNS names subordinate to
     //   apex - DNAME is ignored here as it redirects DNS names subordinate to
     //   the owner name - the owner name itself is not redirected.)
     //   the owner name - the owner name itself is not redirected.)
-    const bool is_origin = (name == getOrigin());
     WantedTypes final_types(FINAL_TYPES());
     WantedTypes final_types(FINAL_TYPES());
     final_types.insert(type);
     final_types.insert(type);
     const FoundRRsets found = getRRsets(name.toText(), final_types,
     const FoundRRsets found = getRRsets(name.toText(), final_types,
-                                        !is_origin, NULL,
-                                        type == RRType::ANY());
+                                        NULL, type == RRType::ANY());
     FindDNSSECContext dnssec_ctx(*this, options);
     FindDNSSECContext dnssec_ctx(*this, options);
     if (found.first) {
     if (found.first) {
         // Something found at the domain name.  Look into it further to get
         // Something found at the domain name.  Look into it further to get
         // the final result.
         // the final result.
+        const bool is_origin = (name == getOrigin());
         return (findOnNameResult(name, type, options, is_origin, found, NULL,
         return (findOnNameResult(name, type, options, is_origin, found, NULL,
                                  target, dnssec_ctx));
                                  target, dnssec_ctx));
     } else {
     } else {
@@ -1021,7 +1008,7 @@ DatabaseClient::Finder::findNSEC3(const Name& name, bool recursive) {
     // Now, we need to get the NSEC3 params from the apex and create the hash
     // Now, we need to get the NSEC3 params from the apex and create the hash
     // creator for it.
     // creator for it.
     const FoundRRsets nsec3param(getRRsets(getOrigin().toText(),
     const FoundRRsets nsec3param(getRRsets(getOrigin().toText(),
-                                 NSEC3PARAM_TYPES(), false));
+                                           NSEC3PARAM_TYPES()));
     const FoundIterator param(nsec3param.second.find(RRType::NSEC3PARAM()));
     const FoundIterator param(nsec3param.second.find(RRType::NSEC3PARAM()));
     if (!nsec3param.first || param == nsec3param.second.end()) {
     if (!nsec3param.first || param == nsec3param.second.end()) {
         // No NSEC3 params? :-(
         // No NSEC3 params? :-(
@@ -1061,7 +1048,7 @@ DatabaseClient::Finder::findNSEC3(const Name& name, bool recursive) {
         }
         }
 
 
         const FoundRRsets nsec3(getRRsets(hash + "." + otext, NSEC3_TYPES(),
         const FoundRRsets nsec3(getRRsets(hash + "." + otext, NSEC3_TYPES(),
-                                          false, NULL, false, context));
+                                          NULL, false, context));
 
 
         if (nsec3.first) {
         if (nsec3.first) {
             // We found an exact match against the current label.
             // We found an exact match against the current label.
@@ -1086,8 +1073,8 @@ DatabaseClient::Finder::findNSEC3(const Name& name, bool recursive) {
                 arg(labels).arg(prevHash);
                 arg(labels).arg(prevHash);
             context = accessor_->getNSEC3Records(prevHash, zone_id_);
             context = accessor_->getNSEC3Records(prevHash, zone_id_);
             const FoundRRsets prev_nsec3(getRRsets(prevHash + "." + otext,
             const FoundRRsets prev_nsec3(getRRsets(prevHash + "." + otext,
-                                                   NSEC3_TYPES(), false, NULL,
-                                                   false, context));
+                                                   NSEC3_TYPES(), NULL, false,
+                                                   context));
 
 
             if (!prev_nsec3.first) {
             if (!prev_nsec3.first) {
                 isc_throw(DataSourceError, "Hash " + prevHash + " returned "
                 isc_throw(DataSourceError, "Hash " + prevHash + " returned "

+ 6 - 9
src/lib/datasrc/database.h

@@ -963,17 +963,14 @@ public:
         ///
         ///
         /// \param name Which domain name should be scanned.
         /// \param name Which domain name should be scanned.
         /// \param types List of types the caller is interested in.
         /// \param types List of types the caller is interested in.
-        /// \param check_ns If this is set to true, it checks nothing lives
-        ///     together with NS record (with few little exceptions, like RRSIG
-        ///     or NSEC). This check is meant for non-apex NS records.
         /// \param construct_name If this is NULL, the resulting RRsets have
         /// \param construct_name If this is NULL, the resulting RRsets have
-        ///     their name set to name. If it is not NULL, it overrides the name
-        ///     and uses this one (this can be used for wildcard synthesized
-        ///     records).
+        ///     their name set to name. If it is not NULL, it overrides the
+        ///     name and uses this one (this can be used for wildcard
+        ///     synthesized records).
         /// \param any If this is true, it records all the types, not only the
         /// \param any If this is true, it records all the types, not only the
         ///     ones requested by types. It also puts a NULL pointer under the
         ///     ones requested by types. It also puts a NULL pointer under the
-        ///     ANY type into the result, if it finds any RRs at all, to easy the
-        ///     identification of success.
+        ///     ANY type into the result, if it finds any RRs at all, to easy
+        ///     the identification of success.
         /// \param srcContext This can be set to non-NULL value to override the
         /// \param srcContext This can be set to non-NULL value to override the
         ///     iterator context used for obtaining the data. This can be used,
         ///     iterator context used for obtaining the data. This can be used,
         ///     for example, to get data from the NSEC3 namespace.
         ///     for example, to get data from the NSEC3 namespace.
@@ -986,7 +983,7 @@ public:
         /// \throw DataSourceError If there's a low-level error with the
         /// \throw DataSourceError If there's a low-level error with the
         ///     database or the database contains bad data.
         ///     database or the database contains bad data.
         FoundRRsets getRRsets(const std::string& name,
         FoundRRsets getRRsets(const std::string& name,
-                              const WantedTypes& types, bool check_ns,
+                              const WantedTypes& types,
                               const std::string* construct_name = NULL,
                               const std::string* construct_name = NULL,
                               bool any = false,
                               bool any = false,
                               DatabaseAccessor::IteratorContextPtr srcContext =
                               DatabaseAccessor::IteratorContextPtr srcContext =

+ 24 - 13
src/lib/datasrc/tests/database_unittest.cc

@@ -168,13 +168,16 @@ const char* const TEST_RECORDS[][5] = {
     {"child.insecdelegation.example.org.", "DS", "3600", "", "DS 5 3 3600 "
     {"child.insecdelegation.example.org.", "DS", "3600", "", "DS 5 3 3600 "
      "20000101000000 20000201000000 12345 example.org. FAKEFAKEFAKE"},
      "20000101000000 20000201000000 12345 example.org. FAKEFAKEFAKE"},
 
 
-    // Broken NS
+    // Delegation NS and other ordinary type of RR coexist at the same
+    // name.  This is deviant (except for some special cases like the other
+    // RR could be used for addressing the NS name), but as long as the
+    // other records are hidden behind the delegation for normal queries
+    // it's not necessarily harmful. (so "broken" may be too strong, but we
+    // keep the name since it could be in a chain of sorted names for DNSSEC
+    // processing and renaming them may have other bad effects for tests).
     {"brokenns1.example.org.", "A", "3600", "", "192.0.2.1"},
     {"brokenns1.example.org.", "A", "3600", "", "192.0.2.1"},
     {"brokenns1.example.org.", "NS", "3600", "", "ns.example.com."},
     {"brokenns1.example.org.", "NS", "3600", "", "ns.example.com."},
 
 
-    {"brokenns2.example.org.", "NS", "3600", "", "ns.example.com."},
-    {"brokenns2.example.org.", "A", "3600", "", "192.0.2.1"},
-
     // Now double DNAME, to test failure mode
     // Now double DNAME, to test failure mode
     {"baddname.example.org.", "DNAME", "3600", "", "dname1.example.com."},
     {"baddname.example.org.", "DNAME", "3600", "", "dname1.example.com."},
     {"baddname.example.org.", "DNAME", "3600", "", "dname2.example.com."},
     {"baddname.example.org.", "DNAME", "3600", "", "dname2.example.com."},
@@ -2202,15 +2205,23 @@ TYPED_TEST(DatabaseClientTest, findDelegation) {
                               ZoneFinder::FIND_DEFAULT),
                               ZoneFinder::FIND_DEFAULT),
                  DataSourceError);
                  DataSourceError);
 
 
-    // Broken NS - it lives together with something else
-    EXPECT_THROW(finder->find(isc::dns::Name("brokenns1.example.org."),
-                              this->qtype_,
-                              ZoneFinder::FIND_DEFAULT),
-                 DataSourceError);
-    EXPECT_THROW(finder->find(isc::dns::Name("brokenns2.example.org."),
-                              this->qtype_,
-                              ZoneFinder::FIND_DEFAULT),
-                 DataSourceError);
+    // NS and other type coexist: deviant and not necessarily harmful.
+    // It should normally just result in DELEGATION; if GLUE_OK is specified,
+    // the other RR should be visible.
+    this->expected_rdatas_.clear();
+    this->expected_rdatas_.push_back("ns.example.com");
+    doFindTest(*finder, Name("brokenns1.example.org"), this->qtype_,
+               RRType::NS(), this->rrttl_, ZoneFinder::DELEGATION,
+               this->expected_rdatas_, this->empty_rdatas_,
+               ZoneFinder::RESULT_DEFAULT);
+
+    this->expected_rdatas_.clear();
+    this->expected_rdatas_.push_back("192.0.2.1");
+    doFindTest(*finder, Name("brokenns1.example.org"), this->qtype_,
+               this->qtype_, this->rrttl_, ZoneFinder::SUCCESS,
+               this->expected_rdatas_, this->empty_rdatas_,
+               ZoneFinder::RESULT_DEFAULT, Name("brokenns1.example.org"),
+               ZoneFinder::FIND_GLUE_OK);
 }
 }
 
 
 TYPED_TEST(DatabaseClientTest, findDS) {
 TYPED_TEST(DatabaseClientTest, findDS) {

+ 0 - 13
src/lib/datasrc/tests/zone_finder_context_unittest.cc

@@ -208,13 +208,6 @@ TEST_P(ZoneFinderContextTest, getAdditionalDelegation) {
 TEST_P(ZoneFinderContextTest, getAdditionalDelegationAtZoneCut) {
 TEST_P(ZoneFinderContextTest, getAdditionalDelegationAtZoneCut) {
     // Similar to the previous case, but one of the NS addresses is at the
     // Similar to the previous case, but one of the NS addresses is at the
     // zone cut.
     // zone cut.
-
-    // XXX: the current database-based data source incorrectly rejects this
-    // setup (see #1771)
-    if (GetParam() == createSQLite3Client) {
-        return;
-    }
-
     ZoneFinderContextPtr ctx = finder_->find(Name("www.b.example.org"),
     ZoneFinderContextPtr ctx = finder_->find(Name("www.b.example.org"),
                                              RRType::SOA());
                                              RRType::SOA());
     EXPECT_EQ(ZoneFinder::DELEGATION, ctx->code);
     EXPECT_EQ(ZoneFinder::DELEGATION, ctx->code);
@@ -316,12 +309,6 @@ TEST_P(ZoneFinderContextTest, getAdditionalMX) {
 }
 }
 
 
 TEST_P(ZoneFinderContextTest, getAdditionalMXAtZoneCut) {
 TEST_P(ZoneFinderContextTest, getAdditionalMXAtZoneCut) {
-    // XXX: the current database-based data source incorrectly rejects this
-    // setup (see #1771)
-    if (GetParam() == createSQLite3Client) {
-        return;
-    }
-
     ZoneFinderContextPtr ctx = finder_->find(Name("mxatcut.example.org."),
     ZoneFinderContextPtr ctx = finder_->find(Name("mxatcut.example.org."),
                                              RRType::MX());
                                              RRType::MX());
     EXPECT_EQ(ZoneFinder::SUCCESS, ctx->code);
     EXPECT_EQ(ZoneFinder::SUCCESS, ctx->code);

+ 10 - 0
src/lib/datasrc/zone.h

@@ -376,6 +376,16 @@ public:
     ///   RRsets for that name are searched just like the normal case;
     ///   RRsets for that name are searched just like the normal case;
     ///   otherwise, if the search has encountered a zone cut, \c DELEGATION
     ///   otherwise, if the search has encountered a zone cut, \c DELEGATION
     ///   with the information of the highest zone cut will be returned.
     ///   with the information of the highest zone cut will be returned.
+    ///   Note: the term "glue" in the DNS protocol standard may sometimes
+    ///   cause confusion: some people use this term strictly for an address
+    ///   record (type AAAA or A) for the name used in the RDATA of an NS RR;
+    ///   some others seem to give it broader flexibility.  Nevertheless,
+    ///   in this API the "GLUE OK" simply means the search by find() can
+    ///   continue beyond a zone cut; the derived class implementation does
+    ///   not have to, and should not, check whether the type is an address
+    ///   record or whether the query name is pointed by some NS RR.
+    ///   It's up to the caller with which definition of "glue" the search
+    ///   result with this option should be used.
     /// - \c FIND_DNSSEC Request that DNSSEC data (like NSEC, RRSIGs) are
     /// - \c FIND_DNSSEC Request that DNSSEC data (like NSEC, RRSIGs) are
     ///   returned with the answer. It is allowed for the data source to
     ///   returned with the answer. It is allowed for the data source to
     ///   include them even when not requested.
     ///   include them even when not requested.

+ 6 - 0
src/lib/python/isc/notify/notify_out.py

@@ -161,6 +161,12 @@ class NotifyOut:
             for item in slaves:
             for item in slaves:
                 self._notify_infos[zone_id].notify_slaves.append((item, 53))
                 self._notify_infos[zone_id].notify_slaves.append((item, 53))
 
 
+    def add_slave(self, address, port):
+        for zone_name, zone_class in sqlite3_ds.get_zones_info(self._db_file):
+            zone_id = (zone_name, zone_class)
+            if zone_id in self._notify_infos:
+                self._notify_infos[zone_id].notify_slaves.append((address, port))
+
     def send_notify(self, zone_name, zone_class='IN'):
     def send_notify(self, zone_name, zone_class='IN'):
         '''Send notify to one zone's slaves, this function is
         '''Send notify to one zone's slaves, this function is
         the only interface for class NotifyOut which can be called
         the only interface for class NotifyOut which can be called

+ 6 - 0
tests/lettuce/configurations/DO_NOT_USE_127.0.0.1:47807

@@ -0,0 +1,6 @@
+Note well:
+
+In some configuration we intentionally use an IPv6 address (::1) with
+port 47807.  DO NOT CHANGE THAT; at least do not change it to
+127.0.0.1:47807.  See git e3f4b290d17a68db728166cdffcbe93517966e8b
+for why.

+ 0 - 4
tests/lettuce/configurations/NOTES

@@ -1,4 +0,0 @@
-- In some configuration we intentionally use an IPv6 address (::1) with
-  port 47807.  DO NOT CHANGE THAT; at least do not change it to
-  127.0.0.1:47807.  See git e3f4b290d17a68db728166cdffcbe93517966e8b
-  for why.

+ 2 - 2
tests/lettuce/configurations/xfrin/inmem_slave.conf

@@ -19,8 +19,8 @@
             } ]
             } ]
         } ],
         } ],
         "listen_on": [ {
         "listen_on": [ {
-            "port": 47806,
-            "address": "127.0.0.1"
+            "address": "::1",
+            "port": 47806
         } ]
         } ]
     },
     },
     "Boss": {
     "Boss": {

+ 6 - 2
tests/lettuce/configurations/xfrin/retransfer_master.conf

@@ -10,13 +10,17 @@
     "Auth": {
     "Auth": {
         "database_file": "data/example.org.sqlite3",
         "database_file": "data/example.org.sqlite3",
         "listen_on": [ {
         "listen_on": [ {
-            "port": 47807,
-            "address": "::1"
+            "address": "::1",
+            "port": 47807
         } ]
         } ]
     },
     },
     "Xfrout": {
     "Xfrout": {
         "zone_config": [ {
         "zone_config": [ {
             "origin": "example.org"
             "origin": "example.org"
+        } ],
+        "also_notify": [ {
+            "address": "::1",
+            "port": 47806
         } ]
         } ]
     },
     },
     "Boss": {
     "Boss": {

+ 2 - 2
tests/lettuce/configurations/xfrin/retransfer_slave.conf

@@ -10,8 +10,8 @@
     "Auth": {
     "Auth": {
         "database_file": "data/test_nonexistent_db.sqlite3",
         "database_file": "data/test_nonexistent_db.sqlite3",
         "listen_on": [ {
         "listen_on": [ {
-            "port": 47806,
-            "address": "127.0.0.1"
+            "address": "::1",
+            "port": 47806
         } ]
         } ]
     },
     },
     "Boss": {
     "Boss": {

+ 38 - 0
tests/lettuce/configurations/xfrin/retransfer_slave_notify.conf

@@ -0,0 +1,38 @@
+{
+    "version": 2,
+    "Logging": {
+        "loggers": [ {
+            "debuglevel": 99,
+            "severity": "DEBUG",
+            "name": "*"
+        } ]
+    },
+    "Auth": {
+        "database_file": "data/xfrin-notify.sqlite3",
+        "listen_on": [ {
+            "address": "::1",
+            "port": 47806
+        } ]
+    },
+    "Xfrin": {
+        "zones": [ {
+            "name": "example.org",
+            "master_addr": "::1",
+            "master_port": 47807
+        } ]
+    },
+    "Zonemgr": {
+        "secondary_zones": [ {
+            "name": "example.org",
+            "class": "IN"
+        } ]
+    },
+    "Boss": {
+        "components": {
+            "b10-auth": { "kind": "needed", "special": "auth" },
+            "b10-xfrin": { "address": "Xfrin", "kind": "dispensable" },
+            "b10-zonemgr": { "address": "Zonemgr", "kind": "dispensable" },
+            "b10-cmdctl": { "special": "cmdctl", "kind": "needed" }
+        }
+    }
+}

+ 1 - 0
tests/lettuce/data/.gitignore

@@ -1,2 +1,3 @@
 /inmem-xfrin.sqlite3
 /inmem-xfrin.sqlite3
 /test_nonexistent_db.sqlite3
 /test_nonexistent_db.sqlite3
+/xfrin-notify.sqlite3

+ 1 - 0
tests/lettuce/data/example.org

@@ -10,3 +10,4 @@ dname.example.org.	3600	IN	DNAME	dname.example.info.
 dname2.foo.example.org.	3600	IN	DNAME	dname2.example.info.
 dname2.foo.example.org.	3600	IN	DNAME	dname2.example.info.
 ns1.example.org.	3600	IN	A	192.0.2.3
 ns1.example.org.	3600	IN	A	192.0.2.3
 ns2.example.org.	3600	IN	A	192.0.2.4
 ns2.example.org.	3600	IN	A	192.0.2.4
+shell.example.org.	3600	IN	SSHFP	2 1 123456789abcdef67890123456789abcdef67890

BIN
tests/lettuce/data/xfrin-notify.sqlite3.orig


+ 4 - 4
tests/lettuce/features/inmemory_over_sqlite3.feature

@@ -26,18 +26,18 @@ Feature: In-memory zone using SQLite3 backend
         And wait for bind10 stderr message XFRIN_STARTED
         And wait for bind10 stderr message XFRIN_STARTED
         And wait for bind10 stderr message ZONEMGR_STARTED
         And wait for bind10 stderr message ZONEMGR_STARTED
 
 
-        A query for www.example.org should have rcode NOERROR
+        A query for www.example.org to [::1]:47806 should have rcode NOERROR
         """
         """
         www.example.org.        3600    IN      A       192.0.2.63
         www.example.org.        3600    IN      A       192.0.2.63
         """
         """
-        A query for mail.example.org should have rcode NXDOMAIN
+        A query for mail.example.org to [::1]:47806 should have rcode NXDOMAIN
         When I send bind10 the command Xfrin retransfer example.org IN ::1 47807
         When I send bind10 the command Xfrin retransfer example.org IN ::1 47807
         Then wait for new bind10 stderr message XFRIN_TRANSFER_SUCCESS not XFRIN_XFR_PROCESS_FAILURE
         Then wait for new bind10 stderr message XFRIN_TRANSFER_SUCCESS not XFRIN_XFR_PROCESS_FAILURE
         Then wait for new bind10 stderr message AUTH_LOAD_ZONE
         Then wait for new bind10 stderr message AUTH_LOAD_ZONE
 
 
-        A query for www.example.org should have rcode NOERROR
+        A query for www.example.org to [::1]:47807 should have rcode NOERROR
         The answer section of the last query response should be
         The answer section of the last query response should be
         """
         """
         www.example.org.        3600    IN      A       192.0.2.1
         www.example.org.        3600    IN      A       192.0.2.1
         """
         """
-        A query for mail.example.org should have rcode NOERROR
+        A query for mail.example.org to [::1]:47806 should have rcode NOERROR

+ 25 - 0
tests/lettuce/features/queries.feature

@@ -103,6 +103,7 @@ Feature: Querying feature
         ns2.example.org.        3600    IN      A       192.0.2.4
         ns2.example.org.        3600    IN      A       192.0.2.4
         mail.example.org.       3600    IN      A       192.0.2.10
         mail.example.org.       3600    IN      A       192.0.2.10
         """
         """
+
     Scenario: Delegation query for unsigned child zone
     Scenario: Delegation query for unsigned child zone
         Given I have bind10 running with configuration example.org.inmem.config
         Given I have bind10 running with configuration example.org.inmem.config
         And wait for bind10 stderr message BIND10_STARTED_CC
         And wait for bind10 stderr message BIND10_STARTED_CC
@@ -122,3 +123,27 @@ Feature: Querying feature
         """
         """
         ns.sub.example.org.	3600	IN	A	192.0.2.101
         ns.sub.example.org.	3600	IN	A	192.0.2.101
         """
         """
+
+    Scenario: SSHFP query
+        # We are testing one more RR type for a normal successful case
+        Given I have bind10 running with configuration example.org.inmem.config
+        And wait for bind10 stderr message BIND10_STARTED_CC
+        And wait for bind10 stderr message CMDCTL_STARTED
+        And wait for bind10 stderr message AUTH_SERVER_STARTED
+
+        bind10 module Auth should be running
+        And bind10 module Resolver should not be running
+        And bind10 module Xfrout should not be running
+        And bind10 module Zonemgr should not be running
+        And bind10 module Xfrin should not be running
+        And bind10 module Stats should not be running
+        And bind10 module StatsHttpd should not be running
+
+        A query for example.org type SSHFP should have rcode NOERROR
+        The last query response should have ancount 0
+        A query for shell.example.org type SSHFP should have rcode NOERROR
+        The last query response should have ancount 1
+        The answer section of the last query response should be
+        """
+        shell.example.org.      3600    IN      SSHFP   2 1 123456789abcdef67890123456789abcdef67890
+        """

+ 2 - 2
tests/lettuce/features/terrain/bind10_control.py

@@ -306,8 +306,8 @@ def config_remove_command(step, name, value, cmdctl_port):
                 "quit"]
                 "quit"]
     run_bindctl(commands, cmdctl_port)
     run_bindctl(commands, cmdctl_port)
 
 
-@step('send bind10 the command (.+)(?: with cmdctl port (\d+))?')
-def send_command(step, command, cmdctl_port):
+@step('send bind10(?: with cmdctl port (\d+))? the command (.+)')
+def send_command(step, cmdctl_port, command):
     """
     """
     Run bindctl, send the given command, and exit bindctl.
     Run bindctl, send the given command, and exit bindctl.
     Parameters:
     Parameters:

+ 2 - 0
tests/lettuce/features/terrain/terrain.py

@@ -59,6 +59,8 @@ copylist = [
      "configurations/ddns/noddns.config"],
      "configurations/ddns/noddns.config"],
     ["data/inmem-xfrin.sqlite3.orig",
     ["data/inmem-xfrin.sqlite3.orig",
      "data/inmem-xfrin.sqlite3"],
      "data/inmem-xfrin.sqlite3"],
+    ["data/xfrin-notify.sqlite3.orig",
+     "data/xfrin-notify.sqlite3"],
     ["data/ddns/example.org.sqlite3.orig",
     ["data/ddns/example.org.sqlite3.orig",
      "data/ddns/example.org.sqlite3"]
      "data/ddns/example.org.sqlite3"]
 ]
 ]

+ 2 - 2
tests/lettuce/features/terrain/transfer.py

@@ -67,11 +67,11 @@ def perform_axfr(step, zone_name, address, port):
     Step definition:
     Step definition:
     An AXFR transfer of <zone_name> [from <address>:<port>]
     An AXFR transfer of <zone_name> [from <address>:<port>]
 
 
-    Address defaults to 127.0.0.1
+    Address defaults to ::1
     Port defaults to 47806
     Port defaults to 47806
     """
     """
     if address is None:
     if address is None:
-        address = "127.0.0.1"
+        address = "::1"
     # convert [IPv6_addr] to IPv6_addr:
     # convert [IPv6_addr] to IPv6_addr:
     address = re.sub(r"\[(.+)\]", r"\1", address)
     address = re.sub(r"\[(.+)\]", r"\1", address)
     if port is None:
     if port is None:

+ 2 - 2
tests/lettuce/features/xfrin_bind10.feature

@@ -23,11 +23,11 @@ Feature: Xfrin
     # Now we use the first step again to see if the file has been created
     # Now we use the first step again to see if the file has been created
     The file data/test_nonexistent_db.sqlite3 should exist
     The file data/test_nonexistent_db.sqlite3 should exist
 
 
-    A query for www.example.org should have rcode REFUSED
+    A query for www.example.org to [::1]:47806 should have rcode REFUSED
     When I send bind10 the command Xfrin retransfer example.org IN ::1 47807
     When I send bind10 the command Xfrin retransfer example.org IN ::1 47807
     Then wait for new bind10 stderr message XFRIN_TRANSFER_SUCCESS not XFRIN_XFR_PROCESS_FAILURE
     Then wait for new bind10 stderr message XFRIN_TRANSFER_SUCCESS not XFRIN_XFR_PROCESS_FAILURE
     Then wait for new bind10 stderr message ZONEMGR_RECEIVE_XFRIN_SUCCESS
     Then wait for new bind10 stderr message ZONEMGR_RECEIVE_XFRIN_SUCCESS
-    A query for www.example.org should have rcode NOERROR
+    A query for www.example.org to [::1]:47806 should have rcode NOERROR
 
 
     # The transferred zone should have 11 non-NSEC3 RRs and 1 NSEC3 RR.
     # The transferred zone should have 11 non-NSEC3 RRs and 1 NSEC3 RR.
     # The following check will get these by AXFR, so the total # of RRs
     # The following check will get these by AXFR, so the total # of RRs

+ 29 - 0
tests/lettuce/features/xfrin_notify_handling.feature

@@ -0,0 +1,29 @@
+Feature: Xfrin incoming notify handling
+    Tests for Xfrin incoming notify handling.
+
+    Scenario: Handle incoming notify
+    Given I have bind10 running with configuration xfrin/retransfer_master.conf with cmdctl port 47804 as master
+    And wait for master stderr message BIND10_STARTED_CC
+    And wait for master stderr message CMDCTL_STARTED
+    And wait for master stderr message AUTH_SERVER_STARTED
+    And wait for master stderr message XFROUT_STARTED
+    And wait for master stderr message ZONEMGR_STARTED
+
+    And I have bind10 running with configuration xfrin/retransfer_slave_notify.conf
+    And wait for bind10 stderr message BIND10_STARTED_CC
+    And wait for bind10 stderr message CMDCTL_STARTED
+    And wait for bind10 stderr message AUTH_SERVER_STARTED
+    And wait for bind10 stderr message XFRIN_STARTED
+    And wait for bind10 stderr message ZONEMGR_STARTED
+
+    A query for www.example.org to [::1]:47806 should have rcode NXDOMAIN
+
+    When I send bind10 with cmdctl port 47804 the command Xfrout notify example.org IN
+    Then wait for new master stderr message XFROUT_NOTIFY_COMMAND
+    Then wait for new bind10 stderr message AUTH_RECEIVED_NOTIFY
+    Then wait for new bind10 stderr message ZONEMGR_RECEIVE_NOTIFY
+    Then wait for new bind10 stderr message XFRIN_XFR_TRANSFER_STARTED
+    Then wait for new bind10 stderr message XFRIN_TRANSFER_SUCCESS not XFRIN_XFR_PROCESS_FAILURE
+    Then wait for new bind10 stderr message ZONEMGR_RECEIVE_XFRIN_SUCCESS
+
+    A query for www.example.org to [::1]:47806 should have rcode NOERROR