diff options
Diffstat (limited to 'contrib/bind9/bin/named')
33 files changed, 3874 insertions, 1947 deletions
diff --git a/contrib/bind9/bin/named/Makefile.in b/contrib/bind9/bin/named/Makefile.in index e3ce3bd1547b..689413570378 100644 --- a/contrib/bind9/bin/named/Makefile.in +++ b/contrib/bind9/bin/named/Makefile.in @@ -13,7 +13,7 @@ # OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR # PERFORMANCE OF THIS SOFTWARE. -# $Id: Makefile.in,v 1.114.14.2 2011/03/10 23:47:25 tbox Exp $ +# $Id: Makefile.in,v 1.116 2011/03/10 23:47:49 tbox Exp $ srcdir = @srcdir@ VPATH = @srcdir@ @@ -161,8 +161,11 @@ maintainer-clean:: bind9.xsl.h: bind9.xsl ${srcdir}/convertxsl.pl ${PERL} ${srcdir}/convertxsl.pl < ${srcdir}/bind9.xsl > bind9.xsl.h -depend: bind9.xsl.h -statschannel.@O@: bind9.xsl.h +bind9.ver3.xsl.h: bind9.ver3.xsl ${srcdir}/convertxsl.pl + ${PERL} ${srcdir}/convertxsl.pl < ${srcdir}/bind9.ver3.xsl > bind9.ver3.xsl.h + +depend: bind9.xsl.h bind9.ver3.xsl.h +statschannel.@O@: bind9.xsl.h bind9.ver3.xsl.h installdirs: $(SHELL) ${top_srcdir}/mkinstalldirs ${DESTDIR}${sbindir} diff --git a/contrib/bind9/bin/named/bind9.ver3.xsl b/contrib/bind9/bin/named/bind9.ver3.xsl new file mode 100644 index 000000000000..22e5c45fbef4 --- /dev/null +++ b/contrib/bind9/bin/named/bind9.ver3.xsl @@ -0,0 +1,738 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- + - Copyright (C) 2012, 2013 Internet Systems Consortium, Inc. ("ISC") + - + - Permission to use, copy, modify, and/or distribute this software for any + - purpose with or without fee is hereby granted, provided that the above + - copyright notice and this permission notice appear in all copies. + - + - THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES WITH + - REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY + - AND FITNESS. IN NO EVENT SHALL ISC BE LIABLE FOR ANY SPECIAL, DIRECT, + - INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM + - LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE + - OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR + - PERFORMANCE OF THIS SOFTWARE. +--> + +<!-- $Id$ --> + +<!-- %Id: bind9.xsl,v 1.21 2009/01/27 23:47:54 tbox Exp % --> +<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" xmlns="http://www.w3.org/1999/xhtml" version="1.0"> + <xsl:output method="html" indent="yes" version="4.0"/> + <xsl:template match="statistics[@version="3.0"]"> + <html> + <head> + <xsl:if test="system-property('xsl:vendor')!='Transformiix'"> + <!-- Non Mozilla specific markup --> + <script type="text/javascript" src="https://www.google.com/jsapi"/> + <script type="text/javascript"> + + google.load("visualization", "1", {packages:["corechart"]}); + google.setOnLoadCallback(loadGraphs); + + var graphs=[]; + + function drawChart(chart_title,target,data) { + var data = google.visualization.arrayToDataTable(data); + + var options = { + title: chart_title + }; + + var chart = new google.visualization.BarChart(document.getElementById(target)); + chart.draw(data, options); + } + + function loadGraphs(){ + //alert("here we are!"); + var g; + + // Server Incoming query Types + while(g = graphs.shift()){ + // alert("going for: " + g.target); + if(g.data.length > 1){ + drawChart(g.title,g.target,g.data); + } + } + } + + // Server Incoming Queries Types + graphs.push({ + 'title' : "Server Incoming Query Types", + 'target': 'chart_incoming_qtypes', + 'data': [['Type','Counter'],<xsl:for-each select="server/counters[@type="qtype"]/counter">['<xsl:value-of select="@name"/>',<xsl:value-of select="."/>],</xsl:for-each>] + }); + + + // Server Incoming Requests + graphs.push({ + 'title' : "Server Incoming Requests", + 'target': 'chart_incoming_requests', + 'data': [['Requests','Counter'],<xsl:for-each select="server/counters[@type="opcode"]/counter">['<xsl:value-of select="@name"/>',<xsl:value-of select="."/>],</xsl:for-each>]}); + + + + + </script> + </xsl:if> + <style type="text/css"> + body { + font-family: sans-serif; + background-color: #ffffff; + color: #000000; + font-size: 10pt; + } + + .odd{ + background-color: #f0f0f0; + } + + .even{ + background-color: #ffffff; + } + + p.footer{ + font-style:italic; + color: grey; + } + + table { + border-collapse: collapse; + border: 1px solid grey; + } + + table.counters{ + border: 1px solid grey; + width: 500px; + } + + table.counters th { + text-align: center; + border: 1px solid grey; + width: 120px; + } + table.counters td{ + text-align:center; + + } + + table.counters tr:hover{ + background-color: #99ddff; + } + + .totals { + background-color: rgb(1,169,206); + color: #ffffff; + } + + td, th { + padding-right: 5px; + padding-left: 5px; + border: 1px solid grey; + } + + .header h1 { + color: rgb(1,169,206); + padding: 0px; + } + + .content { + background-color: #ffffff; + color: #000000; + padding: 4px; + } + + .item { + padding: 4px; + text-align: right; + } + + .value { + padding: 4px; + font-weight: bold; + } + + + h2 { + color: grey; + font-size: 14pt; + width:500px; + text-align:center; + } + + h3 { + color: #444444; + font-size: 12pt; + width:500px; + text-align:center; + + } + h4 { + color: rgb(1,169,206); + font-size: 10pt; + width:500px; + text-align:center; + + } + + .pie { + width:500px; + height: 500px; + } + + </style> + <title>ISC BIND 9 Statistics</title> + </head> + <body> + <div class="header"> + <h1>ISC Bind 9 Configuration and Statistics</h1> + </div> + <hr/> + <h2>Server Times</h2> + <table class="counters"> + <tr> + <th>Boot time:</th> + <td> + <xsl:value-of select="server/boot-time"/> + </td> + </tr> + <tr> + <th>Sample time:</th> + <td> + <xsl:value-of select="server/current-time"/> + </td> + </tr> + </table> + <br/> + <h2>Incoming Requests</h2> + <xsl:if test="system-property('xsl:vendor')!='Transformiix'"> + <!-- Non Mozilla specific markup --> + <div class="pie" id="chart_incoming_requests">[no incoming requests]</div> + </xsl:if> + <table class="counters"> + <xsl:for-each select="server/counters[@type="opcode"]/counter"> + <xsl:sort select="." data-type="number" order="descending"/> + <tr> + <th> + <xsl:value-of select="@name"/> + </th> + <td> + <xsl:value-of select="."/> + </td> + </tr> + </xsl:for-each> + <tr> + <th class="totals">Total:</th> + <td class="totals"> + <xsl:value-of select="sum(server/counters[@type="opcode"]/counter)"/> + </td> + </tr> + </table> + <br/> + <h3>Incoming Queries by Type</h3> + <xsl:if test="system-property('xsl:vendor')!='Transformiix'"> + <!-- Non Mozilla specific markup --> + <div class="pie" id="chart_incoming_qtypes">[no incoming queries]</div> + </xsl:if> + <table class="counters"> + <xsl:for-each select="server/counters[@type="qtype"]/counter"> + <xsl:sort select="." data-type="number" order="descending"/> + <xsl:variable name="css-class"> + <xsl:choose> + <xsl:when test="position() mod 2 = 0">even</xsl:when> + <xsl:otherwise>odd</xsl:otherwise> + </xsl:choose> + </xsl:variable> + <tr class="{$css-class}"> + <th> + <xsl:value-of select="@name"/> + </th> + <td> + <xsl:value-of select="."/> + </td> + </tr> + </xsl:for-each> + <tr> + <th class="totals">Total:</th> + <td class="totals"> + <xsl:value-of select="sum(server/counters[@type="qtype"]/counter)"/> + </td> + </tr> + </table> + <br/> + <h2>Outgoing Queries per view</h2> + <xsl:for-each select="views/view[count(counters[@type="resqtype"]/counter) > 0]"> + <h3>View <xsl:value-of select="@name"/></h3> + <xsl:if test="system-property('xsl:vendor')!='Transformiix'"> + <!-- Non Mozilla specific markup --> + <script type="text/javascript"> + graphs.push({ + 'title': "Outgoing queries for view: <xsl:value-of select="@name"/>", + 'target': 'chart_outgoing_queries_view_<xsl:value-of select="@name"/>', + 'data': [['Type','Counter'],<xsl:for-each select="counters[@type="resqtype"]/counter">['<xsl:value-of select="@name"/>',<xsl:value-of select="."/>],</xsl:for-each>] + }); + + </script> + <xsl:variable name="target"> + <xsl:value-of select="@name"/> + </xsl:variable> + <div class="pie" id="chart_outgoing_queries_view_{$target}"/> + </xsl:if> + <table class="counters"> + <xsl:for-each select="counters[@type="resqtype"]/counter"> + <xsl:sort select="." data-type="number" order="descending"/> + <xsl:variable name="css-class1"> + <xsl:choose> + <xsl:when test="position() mod 2 = 0">even</xsl:when> + <xsl:otherwise>odd</xsl:otherwise> + </xsl:choose> + </xsl:variable> + <tr class="{$css-class1}"> + <th> + <xsl:value-of select="@name"/> + </th> + <td> + <xsl:value-of select="."/> + </td> + </tr> + </xsl:for-each> + </table> + <br/> + </xsl:for-each> + <h2>Server Statistics</h2> + <xsl:if test="system-property('xsl:vendor')!='Transformiix'"> + <!-- Non Mozilla specific markup --> + <script type="text/javascript"> + graphs.push({ + 'title' : "Server Counters", + 'target': 'chart_server_nsstat_restype', + 'data': [['Type','Counter'],<xsl:for-each select="server/counters[@type="nsstat"]/counter[.>0]">['<xsl:value-of select="@name"/>',<xsl:value-of select="."/>],</xsl:for-each>] + }); + + </script> + <div class="pie" id="chart_server_nsstat_restype"/> + </xsl:if> + <table class="counters"> + <xsl:for-each select="server/counters[@type="nsstat"]/counter[.>0]"> + <xsl:sort select="." data-type="number" order="descending"/> + <xsl:variable name="css-class2"> + <xsl:choose> + <xsl:when test="position() mod 2 = 0">even</xsl:when> + <xsl:otherwise>odd</xsl:otherwise> + </xsl:choose> + </xsl:variable> + <tr class="{$css-class2}"> + <th> + <xsl:value-of select="@name"/> + </th> + <td> + <xsl:value-of select="."/> + </td> + </tr> + </xsl:for-each> + </table> + <br/> + <h2>Zone Maintenance Statistics</h2> + <xsl:if test="system-property('xsl:vendor')!='Transformiix'"> + <script type="text/javascript"> + graphs.push({ + 'title' : "Zone Maintenance Stats", + 'target': 'chart_server_zone_maint', + 'data': [['Type','Counter'],<xsl:for-each select="server/counters[@type="zonestat"]/counter">['<xsl:value-of select="@name"/>',<xsl:value-of select="."/>],</xsl:for-each>] + }); + + </script> + <!-- Non Mozilla specific markup --> + <div class="pie" id="chart_server_zone_maint"/> + </xsl:if> + <table class="counters"> + <xsl:for-each select="server/counters[@type="zonestat"]/counter"> + <xsl:sort select="." data-type="number" order="descending"/> + <xsl:variable name="css-class3"> + <xsl:choose> + <xsl:when test="position() mod 2 = 0">even</xsl:when> + <xsl:otherwise>odd</xsl:otherwise> + </xsl:choose> + </xsl:variable> + <tr class="{$css-class3}"> + <th> + <xsl:value-of select="@name"/> + </th> + <td> + <xsl:value-of select="."/> + </td> + </tr> + </xsl:for-each> + </table> + <h2>Resolver Statistics (Common)</h2> + <table class="counters"> + <xsl:for-each select="server/counters[@type="restat"]/counter"> + <xsl:sort select="." data-type="number" order="descending"/> + <xsl:variable name="css-class4"> + <xsl:choose> + <xsl:when test="position() mod 2 = 0">even</xsl:when> + <xsl:otherwise>odd</xsl:otherwise> + </xsl:choose> + </xsl:variable> + <tr class="{$css-class4}"> + <th> + <xsl:value-of select="@name"/> + </th> + <td> + <xsl:value-of select="."/> + </td> + </tr> + </xsl:for-each> + </table> + <xsl:for-each select="views/view"> + <h3>Resolver Statistics for View <xsl:value-of select="@name"/></h3> + <table class="counters"> + <xsl:for-each select="counters[@type="resstats"]/counter[.>0]"> + <xsl:sort select="." data-type="number" order="descending"/> + <xsl:variable name="css-class5"> + <xsl:choose> + <xsl:when test="position() mod 2 = 0">even</xsl:when> + <xsl:otherwise>odd</xsl:otherwise> + </xsl:choose> + </xsl:variable> + <tr class="{$css-class5}"> + <th> + <xsl:value-of select="@name"/> + </th> + <td> + <xsl:value-of select="."/> + </td> + </tr> + </xsl:for-each> + </table> + </xsl:for-each> + <h3>Cache DB RRsets for View <xsl:value-of select="@name"/></h3> + <xsl:for-each select="views/view"> + <table class="counters"> + <xsl:for-each select="cache/rrset"> + <xsl:variable name="css-class6"> + <xsl:choose> + <xsl:when test="position() mod 2 = 0">even</xsl:when> + <xsl:otherwise>odd</xsl:otherwise> + </xsl:choose> + </xsl:variable> + <tr class="{$css-class6}"> + <th> + <xsl:value-of select="name"/> + </th> + <td> + <xsl:value-of select="counter"/> + </td> + </tr> + </xsl:for-each> + </table> + <br/> + </xsl:for-each> + <h2>Socket I/O Statistics</h2> + <table class="counters"> + <xsl:for-each select="server/counters[@type="sockstat"]/counter[.>0]"> + <xsl:variable name="css-class7"> + <xsl:choose> + <xsl:when test="position() mod 2 = 0">even</xsl:when> + <xsl:otherwise>odd</xsl:otherwise> + </xsl:choose> + </xsl:variable> + <tr class="{$css-class7}"> + <th> + <xsl:value-of select="@name"/> + </th> + <td> + <xsl:value-of select="."/> + </td> + </tr> + </xsl:for-each> + </table> + <br/> + <br/> + <h2>Response Codes per view/zone</h2> + <xsl:for-each select="views/view[zones/zone/counters[@type="rcode"]/counter >0]"> + <h3>View <xsl:value-of select="@name"/></h3> + <xsl:variable name="thisview"> + <xsl:value-of select="@name"/> + </xsl:variable> + <xsl:for-each select="zones/zone"> + <xsl:if test="counters[@type="rcode"]/counter[. > 0]"> + <h4>Zone <xsl:value-of select="@name"/></h4> + <xsl:if test="system-property('xsl:vendor')!='Transformiix'"> + <!-- Non Mozilla specific markup --> + <script type="text/javascript"> + graphs.push({ + 'title': "Response Codes for zone <xsl:value-of select="@name"/>", + 'target': 'chart_rescode_<xsl:value-of select="../../@name"/>_<xsl:value-of select="@name"/>', + 'data': [['Type','Counter'],<xsl:for-each select="counters[@type="rcode"]/counter[.>0 and @name != "QryAuthAns"]">['<xsl:value-of select="@name"/>',<xsl:value-of select="."/>],</xsl:for-each>] + }); + + </script> + <xsl:variable name="target"> + <xsl:value-of select="@name"/> + </xsl:variable> + <div class="pie" id="chart_rescode_{$thisview}_{$target}"/> + </xsl:if> + <table class="counters"> + <xsl:for-each select="counters[@type="rcode"]/counter[.>0 and @name != "QryAuthAns"]"> + <xsl:sort select="."/> + <xsl:variable name="css-class10"> + <xsl:choose> + <xsl:when test="position() mod 2 = 0">even</xsl:when> + <xsl:otherwise>odd</xsl:otherwise> + </xsl:choose> + </xsl:variable> + <tr class="{$css-class10}"> + <th> + <xsl:value-of select="@name"/> + </th> + <td> + <xsl:value-of select="."/> + </td> + </tr> + </xsl:for-each> + </table> + </xsl:if> + </xsl:for-each> + </xsl:for-each> + <h2>Received QTYPES per view/zone</h2> + <xsl:for-each select="views/view[zones/zone/counters[@type="qtype"]/counter >0]"> + <h3>View <xsl:value-of select="@name"/></h3> + <xsl:variable name="thisview2"> + <xsl:value-of select="@name"/> + </xsl:variable> + <xsl:for-each select="zones/zone"> + <xsl:if test="counters[@type="qtype"]/counter[count(.) > 0]"> + <h4>Zone <xsl:value-of select="@name"/></h4> + <xsl:if test="system-property('xsl:vendor')!='Transformiix'"> + <!-- Non Mozilla specific markup --> + <script type="text/javascript"> + graphs.push({ + 'title': "Query Types for zone <xsl:value-of select="@name"/>", + 'target': 'chart_qtype_<xsl:value-of select="../../@name"/>_<xsl:value-of select="@name"/>', + 'data': [['Type','Counter'],<xsl:for-each select="counters[@type="qtype"]/counter[.>0 and @name != "QryAuthAns"]">['<xsl:value-of select="@name"/>',<xsl:value-of select="."/>],</xsl:for-each>] + }); + + </script> + <xsl:variable name="target"> + <xsl:value-of select="@name"/> + </xsl:variable> + <div class="pie" id="chart_qtype_{$thisview2}_{$target}"/> + </xsl:if> + <table class="counters"> + <xsl:for-each select="counters[@type="qtype"]/counter"> + <xsl:sort select="."/> + <xsl:variable name="css-class11"> + <xsl:choose> + <xsl:when test="position() mod 2 = 0">even</xsl:when> + <xsl:otherwise>odd</xsl:otherwise> + </xsl:choose> + </xsl:variable> + <tr class="{$css-class11}"> + <th> + <xsl:value-of select="@name"/> + </th> + <td> + <xsl:value-of select="."/> + </td> + </tr> + </xsl:for-each> + </table> + </xsl:if> + </xsl:for-each> + </xsl:for-each> + <h2>Network Status</h2> + <table class="counters"> + <tr> + <th>ID</th> + <th>Name</th> + <th>Type</th> + <th>References</th> + <th>LocalAddress</th> + <th>PeerAddress</th> + <th>State</th> + </tr> + <xsl:for-each select="socketmgr/sockets/socket"> + <xsl:sort select="id"/> + <xsl:variable name="css-class12"> + <xsl:choose> + <xsl:when test="position() mod 2 = 0">even</xsl:when> + <xsl:otherwise>odd</xsl:otherwise> + </xsl:choose> + </xsl:variable> + <tr class="{$css-class12}"> + <td> + <xsl:value-of select="id"/> + </td> + <td> + <xsl:value-of select="name"/> + </td> + <td> + <xsl:value-of select="type"/> + </td> + <td> + <xsl:value-of select="references"/> + </td> + <td> + <xsl:value-of select="local-address"/> + </td> + <td> + <xsl:value-of select="peer-address"/> + </td> + <td> + <xsl:for-each select="states"> + <xsl:value-of select="."/> + </xsl:for-each> + </td> + </tr> + </xsl:for-each> + </table> + <br/> + <h2>Task Manager Configuration</h2> + <table class="counters"> + <tr> + <th class="even">Thread-Model</th> + <td> + <xsl:value-of select="taskmgr/thread-model/type"/> + </td> + </tr> + <tr class="odd"> + <th>Worker Threads</th> + <td> + <xsl:value-of select="taskmgr/thread-model/worker-threads"/> + </td> + </tr> + <tr class="even"> + <th>Default Quantum</th> + <td> + <xsl:value-of select="taskmgr/thread-model/default-quantum"/> + </td> + </tr> + <tr class="odd"> + <th>Tasks Running</th> + <td> + <xsl:value-of select="taskmgr/thread-model/tasks-running"/> + </td> + </tr> + </table> + <br/> + <h2>Tasks</h2> + <table class="counters"> + <tr> + <th>ID</th> + <th>Name</th> + <th>References</th> + <th>State</th> + <th>Quantum</th> + </tr> + <xsl:for-each select="taskmgr/tasks/task"> + <xsl:sort select="name"/> + <xsl:variable name="css-class14"> + <xsl:choose> + <xsl:when test="position() mod 2 = 0">even</xsl:when> + <xsl:otherwise>odd</xsl:otherwise> + </xsl:choose> + </xsl:variable> + <tr class="{$css-class14}"> + <td> + <xsl:value-of select="id"/> + </td> + <td> + <xsl:value-of select="name"/> + </td> + <td> + <xsl:value-of select="references"/> + </td> + <td> + <xsl:value-of select="state"/> + </td> + <td> + <xsl:value-of select="quantum"/> + </td> + </tr> + </xsl:for-each> + </table> + <br/> + <h2>Memory Usage Summary</h2> + <table class="counters"> + <xsl:for-each select="memory/summary/*"> + <xsl:variable name="css-class13"> + <xsl:choose> + <xsl:when test="position() mod 2 = 0">even</xsl:when> + <xsl:otherwise>odd</xsl:otherwise> + </xsl:choose> + </xsl:variable> + <tr class="{$css-class13}"> + <th> + <xsl:value-of select="name()"/> + </th> + <td> + <xsl:value-of select="."/> + </td> + </tr> + </xsl:for-each> + </table> + <br/> + <h2>Memory Contexts</h2> + <table class="counters"> + <tr> + <th>ID</th> + <th>Name</th> + <th>References</th> + <th>TotalUse</th> + <th>InUse</th> + <th>MaxUse</th> + <th>BlockSize</th> + <th>Pools</th> + <th>HiWater</th> + <th>LoWater</th> + </tr> + <xsl:for-each select="memory/contexts/context"> + <xsl:sort select="total" data-type="number" order="descending"/> + <xsl:variable name="css-class14"> + <xsl:choose> + <xsl:when test="position() mod 2 = 0">even</xsl:when> + <xsl:otherwise>odd</xsl:otherwise> + </xsl:choose> + </xsl:variable> + <tr class="{$css-class14}"> + <td> + <xsl:value-of select="id"/> + </td> + <td> + <xsl:value-of select="name"/> + </td> + <td> + <xsl:value-of select="references"/> + </td> + <td> + <xsl:value-of select="total"/> + </td> + <td> + <xsl:value-of select="inuse"/> + </td> + <td> + <xsl:value-of select="maxinuse"/> + </td> + <td> + <xsl:value-of select="blocksize"/> + </td> + <td> + <xsl:value-of select="pools"/> + </td> + <td> + <xsl:value-of select="hiwater"/> + </td> + <td> + <xsl:value-of select="lowater"/> + </td> + </tr> + </xsl:for-each> + </table> + <hr/> + <p class="footer">Internet Systems Consortium Inc.<br/><a href="http://www.isc.org">http://www.isc.org</a></p> + </body> + </html> + </xsl:template> +</xsl:stylesheet> diff --git a/contrib/bind9/bin/named/bind9.ver3.xsl.h b/contrib/bind9/bin/named/bind9.ver3.xsl.h new file mode 100644 index 000000000000..c55714a6fb7b --- /dev/null +++ b/contrib/bind9/bin/named/bind9.ver3.xsl.h @@ -0,0 +1,740 @@ +/* + * Generated by convertxsl.pl 1.14 2008/07/17 23:43:26 jinmei Exp + * From <!-- %Id: bind9.xsl 1.21 2009/01/27 23:47:54 tbox Exp % + */ +static char xslmsg[] = + "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n" + "<!--\n" + " - Copyright (C) 2006-2009 Internet Systems Consortium, Inc. (\"ISC\")\n" + " -\n" + " - Permission to use, copy, modify, and/or distribute this software for any\n" + " - purpose with or without fee is hereby granted, provided that the above\n" + " - copyright notice and this permission notice appear in all copies.\n" + " -\n" + " - THE SOFTWARE IS PROVIDED \"AS IS\" AND ISC DISCLAIMS ALL WARRANTIES WITH\n" + " - REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY\n" + " - AND FITNESS. IN NO EVENT SHALL ISC BE LIABLE FOR ANY SPECIAL, DIRECT,\n" + " - INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM\n" + " - LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE\n" + " - OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR\n" + " - PERFORMANCE OF THIS SOFTWARE.\n" + "-->\n" + "<!-- \045Id: bind9.xsl,v 1.21 2009/01/27 23:47:54 tbox Exp \045 -->\n" + "<xsl:stylesheet xmlns:xsl=\"http://www.w3.org/1999/XSL/Transform\" xmlns=\"http://www.w3.org/1999/xhtml\" version=\"1.0\">\n" + " <xsl:output method=\"html\" indent=\"yes\" version=\"4.0\"/>\n" + " <xsl:template match=\"statistics[@version="3.0"]\">\n" + " <html>\n" + " <head>\n" + " <xsl:if test=\"system-property('xsl:vendor')!='Transformiix'\">\n" + " <!-- Non Mozilla specific markup -->\n" + " <script type=\"text/javascript\" src=\"https://www.google.com/jsapi\"/>\n" + " <script type=\"text/javascript\">\n" + " \n" + " google.load(\"visualization\", \"1\", {packages:[\"corechart\"]});\n" + " google.setOnLoadCallback(loadGraphs);\n" + "\n" + " var graphs=[];\n" + " \n" + " function drawChart(chart_title,target,data) {\n" + " var data = google.visualization.arrayToDataTable(data);\n" + "\n" + " var options = {\n" + " title: chart_title\n" + " };\n" + " \n" + " var chart = new google.visualization.BarChart(document.getElementById(target));\n" + " chart.draw(data, options);\n" + " }\n" + " \n" + " function loadGraphs(){\n" + " //alert(\"here we are!\");\n" + " var g;\n" + " \n" + " // Server Incoming query Types\n" + " while(g = graphs.shift()){\n" + " // alert(\"going for: \" + g.target);\n" + " if(g.data.length > 1){\n" + " drawChart(g.title,g.target,g.data);\n" + " }\n" + " }\n" + " }\n" + " \n" + " // Server Incoming Queries Types \n" + " graphs.push({\n" + " 'title' : \"Server Incoming Query Types\",\n" + " 'target': 'chart_incoming_qtypes',\n" + " 'data': [['Type','Counter'],<xsl:for-each select=\"server/counters[@type="qtype"]/counter\">['<xsl:value-of select=\"@name\"/>',<xsl:value-of select=\".\"/>],</xsl:for-each>]\n" + " });\n" + "\n" + "\n" + " // Server Incoming Requests \n" + " graphs.push({\n" + " 'title' : \"Server Incoming Requests\",\n" + " 'target': 'chart_incoming_requests',\n" + " 'data': [['Requests','Counter'],<xsl:for-each select=\"server/counters[@type="opcode"]/counter\">['<xsl:value-of select=\"@name\"/>',<xsl:value-of select=\".\"/>],</xsl:for-each>]});\n" + " \n" + " \n" + " \n" + " \n" + " </script>\n" + " </xsl:if>\n" + " <style type=\"text/css\">\n" + " body {\n" + " font-family: sans-serif;\n" + " background-color: #ffffff;\n" + " color: #000000;\n" + " font-size: 10pt;\n" + " }\n" + " \n" + " .odd{\n" + " background-color: #f0f0f0;\n" + " }\n" + " \n" + " .even{\n" + " background-color: #ffffff;\n" + " }\n" + " \n" + " p.footer{\n" + " font-style:italic;\n" + " color: grey;\n" + " }\n" + "\n" + " table {\n" + " border-collapse: collapse;\n" + " border: 1px solid grey;\n" + " }\n" + "\n" + " table.counters{\n" + " border: 1px solid grey;\n" + " width: 500px;\n" + " }\n" + " \n" + " table.counters th {\n" + " text-align: center;\n" + " border: 1px solid grey;\n" + " width: 120px;\n" + " }\n" + " table.counters td{\n" + " text-align:center;\n" + " \n" + " }\n" + " \n" + " table.counters tr:hover{\n" + " background-color: #99ddff;\n" + " }\n" + " \n" + " .totals {\n" + " background-color: rgb(1,169,206);\n" + " color: #ffffff;\n" + " }\n" + "\n" + " td, th {\n" + " padding-right: 5px;\n" + " padding-left: 5px;\n" + " border: 1px solid grey;\n" + " }\n" + "\n" + " .header h1 {\n" + " color: rgb(1,169,206);\n" + " padding: 0px;\n" + " }\n" + "\n" + " .content {\n" + " background-color: #ffffff;\n" + " color: #000000;\n" + " padding: 4px;\n" + " }\n" + "\n" + " .item {\n" + " padding: 4px;\n" + " text-align: right;\n" + " }\n" + "\n" + " .value {\n" + " padding: 4px;\n" + " font-weight: bold;\n" + " }\n" + "\n" + "\n" + " h2 {\n" + " color: grey;\n" + " font-size: 14pt;\n" + " width:500px;\n" + " text-align:center;\n" + " }\n" + " \n" + " h3 {\n" + " color: #444444;\n" + " font-size: 12pt;\n" + " width:500px;\n" + " text-align:center;\n" + " \n" + " }\n" + " h4 {\n" + " color: rgb(1,169,206);\n" + " font-size: 10pt;\n" + " width:500px;\n" + " text-align:center;\n" + " \n" + " }\n" + "\n" + " .pie {\n" + " width:500px;\n" + " height: 500px;\n" + " }\n" + "\n" + " </style>\n" + " <title>ISC BIND 9 Statistics</title>\n" + " </head>\n" + " <body>\n" + " <div class=\"header\">\n" + " <h1>ISC Bind 9 Configuration and Statistics</h1>\n" + " </div>\n" + " <hr/>\n" + " <h2>Server Times</h2>\n" + " <table class=\"counters\">\n" + " <tr>\n" + " <th>Boot time:</th>\n" + " <td>\n" + " <xsl:value-of select=\"server/boot-time\"/>\n" + " </td>\n" + " </tr>\n" + " <tr>\n" + " <th>Sample time:</th>\n" + " <td>\n" + " <xsl:value-of select=\"server/current-time\"/>\n" + " </td>\n" + " </tr>\n" + " </table>\n" + " <br/>\n" + " <h2>Incoming Requests</h2>\n" + " <xsl:if test=\"system-property('xsl:vendor')!='Transformiix'\">\n" + " <!-- Non Mozilla specific markup -->\n" + " <div class=\"pie\" id=\"chart_incoming_requests\">[graph incoming requests]</div>\n" + " </xsl:if>\n" + " <table class=\"counters\">\n" + " <xsl:for-each select=\"server/counters[@type="opcode"]/counter\">\n" + " <xsl:sort select=\".\" data-type=\"number\" order=\"descending\"/>\n" + " <tr>\n" + " <th>\n" + " <xsl:value-of select=\"@name\"/>\n" + " </th>\n" + " <td>\n" + " <xsl:value-of select=\".\"/>\n" + " </td>\n" + " </tr>\n" + " </xsl:for-each>\n" + " <tr>\n" + " <th class=\"totals\">Total:</th>\n" + " <td class=\"totals\">\n" + " <xsl:value-of select=\"sum(server/counters[@type="opcode"]/counter)\"/>\n" + " </td>\n" + " </tr>\n" + " </table>\n" + " <br/>\n" + " <h3>Incoming Queries by Type</h3>\n" + " <xsl:if test=\"system-property('xsl:vendor')!='Transformiix'\">\n" + " <!-- Non Mozilla specific markup -->\n" + " <div class=\"pie\" id=\"chart_incoming_qtypes\">[graph incoming qtypes]</div>\n" + " </xsl:if>\n" + " <table class=\"counters\">\n" + " <xsl:for-each select=\"server/counters[@type="qtype"]/counter\">\n" + " <xsl:sort select=\".\" data-type=\"number\" order=\"descending\"/>\n" + " <xsl:variable name=\"css-class\">\n" + " <xsl:choose>\n" + " <xsl:when test=\"position() mod 2 = 0\">even</xsl:when>\n" + " <xsl:otherwise>odd</xsl:otherwise>\n" + " </xsl:choose>\n" + " </xsl:variable>\n" + " <tr class=\"{$css-class}\">\n" + " <th>\n" + " <xsl:value-of select=\"@name\"/>\n" + " </th>\n" + " <td>\n" + " <xsl:value-of select=\".\"/>\n" + " </td>\n" + " </tr>\n" + " </xsl:for-each>\n" + " <tr>\n" + " <th class=\"totals\">Total:</th>\n" + " <td class=\"totals\">\n" + " <xsl:value-of select=\"sum(server/counters[@type="qtype"]/counter)\"/>\n" + " </td>\n" + " </tr>\n" + " </table>\n" + " <br/>\n" + " <h2>Outgoing Queries per view</h2>\n" + " <xsl:for-each select=\"views/view[count(counters[@type="resqtype"]/counter) > 0]\">\n" + " <h3>View <xsl:value-of select=\"@name\"/></h3>\n" + " <xsl:if test=\"system-property('xsl:vendor')!='Transformiix'\">\n" + " <!-- Non Mozilla specific markup -->\n" + " <script type=\"text/javascript\">\n" + " graphs.push({\n" + " 'title': \"Outgoing queries for view: <xsl:value-of select=\"@name\"/>\",\n" + " 'target': 'chart_outgoing_queries_view_<xsl:value-of select=\"@name\"/>',\n" + " 'data': [['Type','Counter'],<xsl:for-each select=\"counters[@type="resqtype"]/counter\">['<xsl:value-of select=\"@name\"/>',<xsl:value-of select=\".\"/>],</xsl:for-each>]\n" + " });\n" + " \n" + " </script>\n" + " <xsl:variable name=\"target\">\n" + " <xsl:value-of select=\"@name\"/>\n" + " </xsl:variable>\n" + " <div class=\"pie\" id=\"chart_outgoing_queries_view_{$target}\"/>\n" + " </xsl:if>\n" + " <table class=\"counters\">\n" + " <xsl:for-each select=\"counters[@type="resqtype"]/counter\">\n" + " <xsl:sort select=\".\" data-type=\"number\" order=\"descending\"/>\n" + " <xsl:variable name=\"css-class1\">\n" + " <xsl:choose>\n" + " <xsl:when test=\"position() mod 2 = 0\">even</xsl:when>\n" + " <xsl:otherwise>odd</xsl:otherwise>\n" + " </xsl:choose>\n" + " </xsl:variable>\n" + " <tr class=\"{$css-class1}\">\n" + " <th>\n" + " <xsl:value-of select=\"@name\"/>\n" + " </th>\n" + " <td>\n" + " <xsl:value-of select=\".\"/>\n" + " </td>\n" + " </tr>\n" + " </xsl:for-each>\n" + " </table>\n" + " <br/>\n" + " </xsl:for-each>\n" + " <h2>Server Statistics</h2>\n" + " <xsl:if test=\"system-property('xsl:vendor')!='Transformiix'\">\n" + " <!-- Non Mozilla specific markup -->\n" + " <script type=\"text/javascript\">\n" + " graphs.push({\n" + " 'title' : \"Server Response Types\",\n" + " 'target': 'chart_server_nsstat_restype',\n" + " 'data': [['Type','Counter'],<xsl:for-each select=\"server/counters[@type="nsstat"]/counter[.>0]\">['<xsl:value-of select=\"@name\"/>',<xsl:value-of select=\".\"/>],</xsl:for-each>]\n" + " });\n" + " \n" + " </script>\n" + " <div class=\"pie\" id=\"chart_server_nsstat_restype\"/>\n" + " </xsl:if>\n" + " <table class=\"counters\">\n" + " <xsl:for-each select=\"server/counters[@type="nsstat"]/counter[.>0]\">\n" + " <xsl:sort select=\".\" data-type=\"number\" order=\"descending\"/>\n" + " <xsl:variable name=\"css-class2\">\n" + " <xsl:choose>\n" + " <xsl:when test=\"position() mod 2 = 0\">even</xsl:when>\n" + " <xsl:otherwise>odd</xsl:otherwise>\n" + " </xsl:choose>\n" + " </xsl:variable>\n" + " <tr class=\"{$css-class2}\">\n" + " <th>\n" + " <xsl:value-of select=\"@name\"/>\n" + " </th>\n" + " <td>\n" + " <xsl:value-of select=\".\"/>\n" + " </td>\n" + " </tr>\n" + " </xsl:for-each>\n" + " </table>\n" + " <br/>\n" + " <h2>Zone Maintenance Statistics</h2>\n" + " <xsl:if test=\"system-property('xsl:vendor')!='Transformiix'\">\n" + " <script type=\"text/javascript\">\n" + " graphs.push({\n" + " 'title' : \"Zone Maintenance Stats\",\n" + " 'target': 'chart_server_zone_maint',\n" + " 'data': [['Type','Counter'],<xsl:for-each select=\"server/counters[@type="zonestat"]/counter\">['<xsl:value-of select=\"@name\"/>',<xsl:value-of select=\".\"/>],</xsl:for-each>]\n" + " });\n" + "\n" + " </script>\n" + " <!-- Non Mozilla specific markup -->\n" + " <div class=\"pie\" id=\"chart_server_zone_maint\"/>\n" + " </xsl:if>\n" + " <table class=\"counters\">\n" + " <xsl:for-each select=\"server/counters[@type="zonestat"]/counter\">\n" + " <xsl:sort select=\".\" data-type=\"number\" order=\"descending\"/>\n" + " <xsl:variable name=\"css-class3\">\n" + " <xsl:choose>\n" + " <xsl:when test=\"position() mod 2 = 0\">even</xsl:when>\n" + " <xsl:otherwise>odd</xsl:otherwise>\n" + " </xsl:choose>\n" + " </xsl:variable>\n" + " <tr class=\"{$css-class3}\">\n" + " <th>\n" + " <xsl:value-of select=\"@name\"/>\n" + " </th>\n" + " <td>\n" + " <xsl:value-of select=\".\"/>\n" + " </td>\n" + " </tr>\n" + " </xsl:for-each>\n" + " </table>\n" + " <h2>Resolver Statistics (Common)</h2>\n" + " <table class=\"counters\">\n" + " <xsl:for-each select=\"server/counters[@type="restat"]/counter\">\n" + " <xsl:sort select=\".\" data-type=\"number\" order=\"descending\"/>\n" + " <xsl:variable name=\"css-class4\">\n" + " <xsl:choose>\n" + " <xsl:when test=\"position() mod 2 = 0\">even</xsl:when>\n" + " <xsl:otherwise>odd</xsl:otherwise>\n" + " </xsl:choose>\n" + " </xsl:variable>\n" + " <tr class=\"{$css-class4}\">\n" + " <th>\n" + " <xsl:value-of select=\"@name\"/>\n" + " </th>\n" + " <td>\n" + " <xsl:value-of select=\".\"/>\n" + " </td>\n" + " </tr>\n" + " </xsl:for-each>\n" + " </table>\n" + " <xsl:for-each select=\"views/view\">\n" + " <h3>Resolver Statistics for View <xsl:value-of select=\"@name\"/></h3>\n" + " <table class=\"counters\">\n" + " <xsl:for-each select=\"counters[@type="resstats"]/counter[.>0]\">\n" + " <xsl:sort select=\".\" data-type=\"number\" order=\"descending\"/>\n" + " <xsl:variable name=\"css-class5\">\n" + " <xsl:choose>\n" + " <xsl:when test=\"position() mod 2 = 0\">even</xsl:when>\n" + " <xsl:otherwise>odd</xsl:otherwise>\n" + " </xsl:choose>\n" + " </xsl:variable>\n" + " <tr class=\"{$css-class5}\">\n" + " <th>\n" + " <xsl:value-of select=\"@name\"/>\n" + " </th>\n" + " <td>\n" + " <xsl:value-of select=\".\"/>\n" + " </td>\n" + " </tr>\n" + " </xsl:for-each>\n" + " </table>\n" + " </xsl:for-each>\n" + " <h3>Cache DB RRsets for View <xsl:value-of select=\"@name\"/></h3>\n" + " <xsl:for-each select=\"views/view\">\n" + " <table class=\"counters\">\n" + " <xsl:for-each select=\"cache/rrset\">\n" + " <xsl:variable name=\"css-class6\">\n" + " <xsl:choose>\n" + " <xsl:when test=\"position() mod 2 = 0\">even</xsl:when>\n" + " <xsl:otherwise>odd</xsl:otherwise>\n" + " </xsl:choose>\n" + " </xsl:variable>\n" + " <tr class=\"{$css-class6}\">\n" + " <th>\n" + " <xsl:value-of select=\"name\"/>\n" + " </th>\n" + " <td>\n" + " <xsl:value-of select=\"counter\"/>\n" + " </td>\n" + " </tr>\n" + " </xsl:for-each>\n" + " </table>\n" + " <br/>\n" + " </xsl:for-each>\n" + " <h2>Socket I/O Statistics</h2>\n" + " <table class=\"counters\">\n" + " <xsl:for-each select=\"server/counters[@type="sockstat"]/counter[.>0]\">\n" + " <xsl:variable name=\"css-class7\">\n" + " <xsl:choose>\n" + " <xsl:when test=\"position() mod 2 = 0\">even</xsl:when>\n" + " <xsl:otherwise>odd</xsl:otherwise>\n" + " </xsl:choose>\n" + " </xsl:variable>\n" + " <tr class=\"{$css-class7}\">\n" + " <th>\n" + " <xsl:value-of select=\"@name\"/>\n" + " </th>\n" + " <td>\n" + " <xsl:value-of select=\".\"/>\n" + " </td>\n" + " </tr>\n" + " </xsl:for-each>\n" + " </table>\n" + " <br/>\n" + " <br/>\n" + " <h2>Response Codes per view/zone</h2>\n" + " <xsl:for-each select=\"views/view[zones/zone/counters[@type="rcode"]/counter >0]\">\n" + " <h3>View <xsl:value-of select=\"@name\"/></h3>\n" + " <xsl:variable name=\"thisview\">\n" + " <xsl:value-of select=\"@name\"/>\n" + " </xsl:variable>\n" + " <xsl:for-each select=\"zones/zone\">\n" + " <xsl:if test=\"counters[@type="rcode"]/counter[. > 0]\">\n" + " <h4>Zone <xsl:value-of select=\"@name\"/></h4>\n" + " <xsl:if test=\"system-property('xsl:vendor')!='Transformiix'\">\n" + " <!-- Non Mozilla specific markup -->\n" + " <script type=\"text/javascript\">\n" + " graphs.push({\n" + " 'title': \"Response Codes for zone <xsl:value-of select=\"@name\"/>\",\n" + " 'target': 'chart_rescode_<xsl:value-of select=\"../../@name\"/>_<xsl:value-of select=\"@name\"/>',\n" + " 'data': [['Type','Counter'],<xsl:for-each select=\"counters[@type="rcode"]/counter[.>0 and @name != "QryAuthAns"]\">['<xsl:value-of select=\"@name\"/>',<xsl:value-of select=\".\"/>],</xsl:for-each>]\n" + " });\n" + "\n" + " </script>\n" + " <xsl:variable name=\"target\">\n" + " <xsl:value-of select=\"@name\"/>\n" + " </xsl:variable>\n" + " <div class=\"pie\" id=\"chart_rescode_{$thisview}_{$target}\"/>\n" + " </xsl:if>\n" + " <table class=\"counters\">\n" + " <xsl:for-each select=\"counters[@type="rcode"]/counter[.>0 and @name != "QryAuthAns"]\">\n" + " <xsl:sort select=\".\"/>\n" + " <xsl:variable name=\"css-class10\">\n" + " <xsl:choose>\n" + " <xsl:when test=\"position() mod 2 = 0\">even</xsl:when>\n" + " <xsl:otherwise>odd</xsl:otherwise>\n" + " </xsl:choose>\n" + " </xsl:variable>\n" + " <tr class=\"{$css-class10}\">\n" + " <th>\n" + " <xsl:value-of select=\"@name\"/>\n" + " </th>\n" + " <td>\n" + " <xsl:value-of select=\".\"/>\n" + " </td>\n" + " </tr>\n" + " </xsl:for-each>\n" + " </table>\n" + " </xsl:if>\n" + " </xsl:for-each>\n" + " </xsl:for-each>\n" + " <h2>Received QTYPES per view/zone</h2>\n" + " <xsl:for-each select=\"views/view[zones/zone/counters[@type="qtype"]/counter >0]\">\n" + " <h3>View <xsl:value-of select=\"@name\"/></h3>\n" + " <xsl:variable name=\"thisview2\">\n" + " <xsl:value-of select=\"@name\"/>\n" + " </xsl:variable>\n" + " <xsl:for-each select=\"zones/zone\">\n" + " <xsl:if test=\"counters[@type="qtype"]/counter[count(.) > 0]\">\n" + " <h4>Zone <xsl:value-of select=\"@name\"/></h4>\n" + " <xsl:if test=\"system-property('xsl:vendor')!='Transformiix'\">\n" + " <!-- Non Mozilla specific markup -->\n" + " <script type=\"text/javascript\">\n" + " graphs.push({\n" + " 'title': \"Query Types for zone <xsl:value-of select=\"@name\"/>\",\n" + " 'target': 'chart_qtype_<xsl:value-of select=\"../../@name\"/>_<xsl:value-of select=\"@name\"/>',\n" + " 'data': [['Type','Counter'],<xsl:for-each select=\"counters[@type="qtype"]/counter[.>0 and @name != "QryAuthAns"]\">['<xsl:value-of select=\"@name\"/>',<xsl:value-of select=\".\"/>],</xsl:for-each>]\n" + " });\n" + "\n" + " </script>\n" + " <xsl:variable name=\"target\">\n" + " <xsl:value-of select=\"@name\"/>\n" + " </xsl:variable>\n" + " <div class=\"pie\" id=\"chart_qtype_{$thisview2}_{$target}\"/>\n" + " </xsl:if>\n" + " <table class=\"counters\">\n" + " <xsl:for-each select=\"counters[@type="qtype"]/counter\">\n" + " <xsl:sort select=\".\"/>\n" + " <xsl:variable name=\"css-class11\">\n" + " <xsl:choose>\n" + " <xsl:when test=\"position() mod 2 = 0\">even</xsl:when>\n" + " <xsl:otherwise>odd</xsl:otherwise>\n" + " </xsl:choose>\n" + " </xsl:variable>\n" + " <tr class=\"{$css-class11}\">\n" + " <th>\n" + " <xsl:value-of select=\"@name\"/>\n" + " </th>\n" + " <td>\n" + " <xsl:value-of select=\".\"/>\n" + " </td>\n" + " </tr>\n" + " </xsl:for-each>\n" + " </table>\n" + " </xsl:if>\n" + " </xsl:for-each>\n" + " </xsl:for-each>\n" + " <h2>Network Status</h2>\n" + " <table class=\"counters\">\n" + " <tr>\n" + " <th>ID</th>\n" + " <th>Name</th>\n" + " <th>Type</th>\n" + " <th>References</th>\n" + " <th>LocalAddress</th>\n" + " <th>PeerAddress</th>\n" + " <th>State</th>\n" + " </tr>\n" + " <xsl:for-each select=\"socketmgr/sockets/socket\">\n" + " <xsl:sort select=\"id\"/>\n" + " <xsl:variable name=\"css-class12\">\n" + " <xsl:choose>\n" + " <xsl:when test=\"position() mod 2 = 0\">even</xsl:when>\n" + " <xsl:otherwise>odd</xsl:otherwise>\n" + " </xsl:choose>\n" + " </xsl:variable>\n" + " <tr class=\"{$css-class12}\">\n" + " <td>\n" + " <xsl:value-of select=\"id\"/>\n" + " </td>\n" + " <td>\n" + " <xsl:value-of select=\"name\"/>\n" + " </td>\n" + " <td>\n" + " <xsl:value-of select=\"type\"/>\n" + " </td>\n" + " <td>\n" + " <xsl:value-of select=\"references\"/>\n" + " </td>\n" + " <td>\n" + " <xsl:value-of select=\"local-address\"/>\n" + " </td>\n" + " <td>\n" + " <xsl:value-of select=\"peer-address\"/>\n" + " </td>\n" + " <td>\n" + " <xsl:for-each select=\"states\">\n" + " <xsl:value-of select=\".\"/>\n" + " </xsl:for-each>\n" + " </td>\n" + " </tr>\n" + " </xsl:for-each>\n" + " </table>\n" + " <br/>\n" + " <h2>Task Manager Configuration</h2>\n" + " <table class=\"counters\">\n" + " <tr>\n" + " <th class=\"even\">Thread-Model</th>\n" + " <td>\n" + " <xsl:value-of select=\"taskmgr/thread-model/type\"/>\n" + " </td>\n" + " </tr>\n" + " <tr class=\"odd\">\n" + " <th>Worker Threads</th>\n" + " <td>\n" + " <xsl:value-of select=\"taskmgr/thread-model/worker-threads\"/>\n" + " </td>\n" + " </tr>\n" + " <tr class=\"even\">\n" + " <th>Default Quantum</th>\n" + " <td>\n" + " <xsl:value-of select=\"taskmgr/thread-model/default-quantum\"/>\n" + " </td>\n" + " </tr>\n" + " <tr class=\"odd\">\n" + " <th>Tasks Running</th>\n" + " <td>\n" + " <xsl:value-of select=\"taskmgr/thread-model/tasks-running\"/>\n" + " </td>\n" + " </tr>\n" + " </table>\n" + " <br/>\n" + " <h2>Tasks</h2>\n" + " <table class=\"counters\">\n" + " <tr>\n" + " <th>ID</th>\n" + " <th>Name</th>\n" + " <th>References</th>\n" + " <th>State</th>\n" + " <th>Quantum</th>\n" + " </tr>\n" + " <xsl:for-each select=\"taskmgr/tasks/task\">\n" + " <xsl:sort select=\"name\"/>\n" + " <xsl:variable name=\"css-class14\">\n" + " <xsl:choose>\n" + " <xsl:when test=\"position() mod 2 = 0\">even</xsl:when>\n" + " <xsl:otherwise>odd</xsl:otherwise>\n" + " </xsl:choose>\n" + " </xsl:variable>\n" + " <tr class=\"{$css-class14}\">\n" + " <td>\n" + " <xsl:value-of select=\"id\"/>\n" + " </td>\n" + " <td>\n" + " <xsl:value-of select=\"name\"/>\n" + " </td>\n" + " <td>\n" + " <xsl:value-of select=\"references\"/>\n" + " </td>\n" + " <td>\n" + " <xsl:value-of select=\"state\"/>\n" + " </td>\n" + " <td>\n" + " <xsl:value-of select=\"quantum\"/>\n" + " </td>\n" + " </tr>\n" + " </xsl:for-each>\n" + " </table>\n" + " <br/>\n" + " <h2>Memory Usage Summary</h2>\n" + " <table class=\"counters\">\n" + " <xsl:for-each select=\"memory/summary/*\">\n" + " <xsl:variable name=\"css-class13\">\n" + " <xsl:choose>\n" + " <xsl:when test=\"position() mod 2 = 0\">even</xsl:when>\n" + " <xsl:otherwise>odd</xsl:otherwise>\n" + " </xsl:choose>\n" + " </xsl:variable>\n" + " <tr class=\"{$css-class13}\">\n" + " <th>\n" + " <xsl:value-of select=\"name()\"/>\n" + " </th>\n" + " <td>\n" + " <xsl:value-of select=\".\"/>\n" + " </td>\n" + " </tr>\n" + " </xsl:for-each>\n" + " </table>\n" + " <br/>\n" + " <h2>Memory Contexts</h2>\n" + " <table class=\"counters\">\n" + " <tr>\n" + " <th>ID</th>\n" + " <th>Name</th>\n" + " <th>References</th>\n" + " <th>TotalUse</th>\n" + " <th>InUse</th>\n" + " <th>MaxUse</th>\n" + " <th>BlockSize</th>\n" + " <th>Pools</th>\n" + " <th>HiWater</th>\n" + " <th>LoWater</th>\n" + " </tr>\n" + " <xsl:for-each select=\"memory/contexts/context\">\n" + " <xsl:sort select=\"total\" data-type=\"number\" order=\"descending\"/>\n" + " <xsl:variable name=\"css-class14\">\n" + " <xsl:choose>\n" + " <xsl:when test=\"position() mod 2 = 0\">even</xsl:when>\n" + " <xsl:otherwise>odd</xsl:otherwise>\n" + " </xsl:choose>\n" + " </xsl:variable>\n" + " <tr class=\"{$css-class14}\">\n" + " <td>\n" + " <xsl:value-of select=\"id\"/>\n" + " </td>\n" + " <td>\n" + " <xsl:value-of select=\"name\"/>\n" + " </td>\n" + " <td>\n" + " <xsl:value-of select=\"references\"/>\n" + " </td>\n" + " <td>\n" + " <xsl:value-of select=\"total\"/>\n" + " </td>\n" + " <td>\n" + " <xsl:value-of select=\"inuse\"/>\n" + " </td>\n" + " <td>\n" + " <xsl:value-of select=\"maxinuse\"/>\n" + " </td>\n" + " <td>\n" + " <xsl:value-of select=\"blocksize\"/>\n" + " </td>\n" + " <td>\n" + " <xsl:value-of select=\"pools\"/>\n" + " </td>\n" + " <td>\n" + " <xsl:value-of select=\"hiwater\"/>\n" + " </td>\n" + " <td>\n" + " <xsl:value-of select=\"lowater\"/>\n" + " </td>\n" + " </tr>\n" + " </xsl:for-each>\n" + " </table>\n" + " <hr/>\n" + " <p class=\"footer\">Internet Systems Consortium Inc.<br/><a href=\"http://www.isc.org\">http://www.isc.org</a></p>\n" + " </body>\n" + " </html>\n" + " </xsl:template>\n" + "</xsl:stylesheet>\n"; diff --git a/contrib/bind9/bin/named/builtin.c b/contrib/bind9/bin/named/builtin.c index 14204cd295c6..4604cb3ce07e 100644 --- a/contrib/bind9/bin/named/builtin.c +++ b/contrib/bind9/bin/named/builtin.c @@ -15,7 +15,7 @@ * PERFORMANCE OF THIS SOFTWARE. */ -/* $Id: builtin.c,v 1.20.14.3 2012/01/11 20:19:40 ckb Exp $ */ +/* $Id: builtin.c,v 1.26 2012/01/21 19:44:18 each Exp $ */ /*! \file * \brief @@ -281,11 +281,14 @@ dns64_cname(const dns_name_t *zone, const dns_name_t *name, static isc_result_t builtin_lookup(const char *zone, const char *name, void *dbdata, - dns_sdblookup_t *lookup) + dns_sdblookup_t *lookup, dns_clientinfomethods_t *methods, + dns_clientinfo_t *clientinfo) { builtin_t *b = (builtin_t *) dbdata; UNUSED(zone); + UNUSED(methods); + UNUSED(clientinfo); if (strcmp(name, "@") == 0) return (b->do_lookup(lookup)); @@ -295,10 +298,14 @@ builtin_lookup(const char *zone, const char *name, void *dbdata, static isc_result_t dns64_lookup(const dns_name_t *zone, const dns_name_t *name, void *dbdata, - dns_sdblookup_t *lookup) + dns_sdblookup_t *lookup, dns_clientinfomethods_t *methods, + dns_clientinfo_t *clientinfo) { builtin_t *b = (builtin_t *) dbdata; + UNUSED(methods); + UNUSED(clientinfo); + if (name->labels == 0 && name->length == 0) return (b->do_lookup(lookup)); else @@ -353,6 +360,8 @@ do_authors_lookup(dns_sdblookup_t *lookup) { "Curtis Blackburn", "James Brister", "Ben Cottrell", + "John H. DuBois III", + "Francis Dupont", "Michael Graff", "Andreas Gustafsson", "Bob Halley", diff --git a/contrib/bind9/bin/named/client.c b/contrib/bind9/bin/named/client.c index ff4ab691c184..933abc7631e2 100644 --- a/contrib/bind9/bin/named/client.c +++ b/contrib/bind9/bin/named/client.c @@ -15,7 +15,7 @@ * PERFORMANCE OF THIS SOFTWARE. */ -/* $Id: client.c,v 1.271.10.4 2012/01/31 23:46:39 tbox Exp $ */ +/* $Id$ */ #include <config.h> @@ -24,6 +24,7 @@ #include <isc/once.h> #include <isc/platform.h> #include <isc/print.h> +#include <isc/queue.h> #include <isc/stats.h> #include <isc/stdio.h> #include <isc/string.h> @@ -116,15 +117,26 @@ struct ns_clientmgr { /* Unlocked. */ unsigned int magic; + + /* The queue object has its own locks */ + client_queue_t inactive; /*%< To be recycled */ + isc_mem_t * mctx; isc_taskmgr_t * taskmgr; isc_timermgr_t * timermgr; + + /* Lock covers manager state. */ isc_mutex_t lock; - /* Locked by lock. */ isc_boolean_t exiting; - client_list_t active; /*%< Active clients */ - client_list_t recursing; /*%< Recursing clients */ - client_list_t inactive; /*%< To be recycled */ + + /* Lock covers the clients list */ + isc_mutex_t listlock; + client_list_t clients; /*%< All active clients */ + + /* Lock covers the recursing list */ + isc_mutex_t reclock; + client_list_t recursing; /*%< Recursing clients */ + #if NMCTXS > 0 /*%< mctx pool for clients. */ unsigned int nextmctx; @@ -188,6 +200,12 @@ struct ns_clientmgr { * recursion quota, and an outstanding write request. */ +#define NS_CLIENTSTATE_RECURSING 5 +/*%< + * The client object is recursing. It will be on the 'recursing' + * list. + */ + #define NS_CLIENTSTATE_MAX 9 /*%< * Sentinel value used to indicate "no state". When client->newstate @@ -210,20 +228,21 @@ static void client_udprecv(ns_client_t *client); static void clientmgr_destroy(ns_clientmgr_t *manager); static isc_boolean_t exit_check(ns_client_t *client); static void ns_client_endrequest(ns_client_t *client); -static void ns_client_checkactive(ns_client_t *client); static void client_start(isc_task_t *task, isc_event_t *event); static void client_request(isc_task_t *task, isc_event_t *event); static void ns_client_dumpmessage(ns_client_t *client, const char *reason); +static isc_result_t get_client(ns_clientmgr_t *manager, ns_interface_t *ifp, + dns_dispatch_t *disp, isc_boolean_t tcp); void ns_client_recursing(ns_client_t *client) { REQUIRE(NS_CLIENT_VALID(client)); + REQUIRE(client->state == NS_CLIENTSTATE_WORKING); - LOCK(&client->manager->lock); - ISC_LIST_UNLINK(*client->list, client, link); - ISC_LIST_APPEND(client->manager->recursing, client, link); - client->list = &client->manager->recursing; - UNLOCK(&client->manager->lock); + LOCK(&client->manager->reclock); + client->newstate = client->state = NS_CLIENTSTATE_RECURSING; + ISC_LIST_APPEND(client->manager->recursing, client, rlink); + UNLOCK(&client->manager->reclock); } void @@ -231,15 +250,14 @@ ns_client_killoldestquery(ns_client_t *client) { ns_client_t *oldest; REQUIRE(NS_CLIENT_VALID(client)); - LOCK(&client->manager->lock); + LOCK(&client->manager->reclock); oldest = ISC_LIST_HEAD(client->manager->recursing); if (oldest != NULL) { + ISC_LIST_UNLINK(client->manager->recursing, oldest, rlink); + UNLOCK(&client->manager->reclock); ns_query_cancel(oldest); - ISC_LIST_UNLINK(*oldest->list, oldest, link); - ISC_LIST_APPEND(client->manager->active, oldest, link); - oldest->list = &client->manager->active; - } - UNLOCK(&client->manager->lock); + } else + UNLOCK(&client->manager->reclock); } void @@ -268,15 +286,16 @@ ns_client_settimeout(ns_client_t *client, unsigned int seconds) { */ static isc_boolean_t exit_check(ns_client_t *client) { - ns_clientmgr_t *locked_manager = NULL; - ns_clientmgr_t *destroy_manager = NULL; + isc_boolean_t destroy_manager = ISC_FALSE; + ns_clientmgr_t *manager = NULL; REQUIRE(NS_CLIENT_VALID(client)); + manager = client->manager; if (client->state <= client->newstate) return (ISC_FALSE); /* Business as usual. */ - INSIST(client->newstate < NS_CLIENTSTATE_WORKING); + INSIST(client->newstate < NS_CLIENTSTATE_RECURSING); /* * We need to detach from the view early when shutting down @@ -293,13 +312,16 @@ exit_check(ns_client_t *client) { client->newstate == NS_CLIENTSTATE_FREED && client->view != NULL) dns_view_detach(&client->view); - if (client->state == NS_CLIENTSTATE_WORKING) { + if (client->state == NS_CLIENTSTATE_WORKING || + client->state == NS_CLIENTSTATE_RECURSING) + { INSIST(client->newstate <= NS_CLIENTSTATE_READING); /* * Let the update processing complete. */ if (client->nupdates > 0) return (ISC_TRUE); + /* * We are trying to abort request processing. */ @@ -322,23 +344,28 @@ exit_check(ns_client_t *client) { */ return (ISC_TRUE); } + /* * I/O cancel is complete. Burn down all state * related to the current request. Ensure that - * the client is on the active list and not the - * recursing list. + * the client is no longer on the recursing list. + * + * We need to check whether the client is still linked, + * because it may already have been removed from the + * recursing list by ns_client_killoldestquery() */ - LOCK(&client->manager->lock); - if (client->list == &client->manager->recursing) { - ISC_LIST_UNLINK(*client->list, client, link); - ISC_LIST_APPEND(client->manager->active, client, link); - client->list = &client->manager->active; + if (client->state == NS_CLIENTSTATE_RECURSING) { + LOCK(&manager->reclock); + if (ISC_LINK_LINKED(client, rlink)) + ISC_LIST_UNLINK(manager->recursing, + client, rlink); + UNLOCK(&manager->reclock); } - UNLOCK(&client->manager->lock); ns_client_endrequest(client); client->state = NS_CLIENTSTATE_READING; INSIST(client->recursionquota == NULL); + if (NS_CLIENTSTATE_READING == client->newstate) { client_read(client); client->newstate = NS_CLIENTSTATE_MAX; @@ -389,8 +416,27 @@ exit_check(ns_client_t *client) { * or UDP request, but we may have enough clients doing * that already. Check whether this client needs to remain * active and force it to go inactive if not. + * + * UDP clients go inactive at this point, but TCP clients + * may remain active if we have fewer active TCP client + * objects than desired due to an earlier quota exhaustion. */ - ns_client_checkactive(client); + if (client->mortal && TCP_CLIENT(client) && !ns_g_clienttest) { + LOCK(&client->interface->lock); + if (client->interface->ntcpcurrent < + client->interface->ntcptarget) + client->mortal = ISC_FALSE; + UNLOCK(&client->interface->lock); + } + + /* + * We don't need the client; send it to the inactive + * queue for recycling. + */ + if (client->mortal) { + if (client->newstate > NS_CLIENTSTATE_INACTIVE) + client->newstate = NS_CLIENTSTATE_INACTIVE; + } if (NS_CLIENTSTATE_READY == client->newstate) { if (TCP_CLIENT(client)) { @@ -404,6 +450,7 @@ exit_check(ns_client_t *client) { if (client->state == NS_CLIENTSTATE_READY) { INSIST(client->newstate <= NS_CLIENTSTATE_INACTIVE); + /* * We are trying to enter the inactive state. */ @@ -411,25 +458,22 @@ exit_check(ns_client_t *client) { isc_socket_cancel(client->tcplistener, client->task, ISC_SOCKCANCEL_ACCEPT); - if (! (client->naccepts == 0)) { - /* Still waiting for accept cancel completion. */ + /* Still waiting for accept cancel completion. */ + if (! (client->naccepts == 0)) return (ISC_TRUE); - } - /* Accept cancel is complete. */ + /* Accept cancel is complete. */ if (client->nrecvs > 0) isc_socket_cancel(client->udpsocket, client->task, ISC_SOCKCANCEL_RECV); - if (! (client->nrecvs == 0)) { - /* Still waiting for recv cancel completion. */ + + /* Still waiting for recv cancel completion. */ + if (! (client->nrecvs == 0)) return (ISC_TRUE); - } - /* Recv cancel is complete. */ - if (client->nctls > 0) { - /* Still waiting for control event to be delivered */ + /* Still waiting for control event to be delivered */ + if (client->nctls > 0) return (ISC_TRUE); - } /* Deactivate the client. */ if (client->interface) @@ -449,7 +493,6 @@ exit_check(ns_client_t *client) { client->attributes = 0; client->mortal = ISC_FALSE; - LOCK(&client->manager->lock); /* * Put the client on the inactive list. If we are aiming for * the "freed" state, it will be removed from the inactive @@ -457,18 +500,18 @@ exit_check(ns_client_t *client) { * that has been done, lest the manager decide to reactivate * the dying client inbetween. */ - locked_manager = client->manager; - ISC_LIST_UNLINK(*client->list, client, link); - ISC_LIST_APPEND(client->manager->inactive, client, link); - client->list = &client->manager->inactive; client->state = NS_CLIENTSTATE_INACTIVE; INSIST(client->recursionquota == NULL); if (client->state == client->newstate) { client->newstate = NS_CLIENTSTATE_MAX; + if (!ns_g_clienttest && manager != NULL && + !manager->exiting) + ISC_QUEUE_PUSH(manager->inactive, client, + ilink); if (client->needshutdown) isc_task_shutdown(client->task); - goto unlock; + return (ISC_TRUE); } } @@ -485,6 +528,7 @@ exit_check(ns_client_t *client) { REQUIRE(client->state == NS_CLIENTSTATE_INACTIVE); INSIST(client->recursionquota == NULL); + INSIST(!ISC_QLINK_LINKED(client, ilink)); ns_query_free(client); isc_mem_put(client->mctx, client->recvbuf, RECV_BUFFER_SIZE); @@ -493,27 +537,27 @@ exit_check(ns_client_t *client) { isc_timer_detach(&client->timer); if (client->tcpbuf != NULL) - isc_mem_put(client->mctx, client->tcpbuf, TCP_BUFFER_SIZE); + isc_mem_put(client->mctx, client->tcpbuf, + TCP_BUFFER_SIZE); if (client->opt != NULL) { INSIST(dns_rdataset_isassociated(client->opt)); dns_rdataset_disassociate(client->opt); - dns_message_puttemprdataset(client->message, &client->opt); + dns_message_puttemprdataset(client->message, + &client->opt); } + dns_message_destroy(&client->message); - if (client->manager != NULL) { - ns_clientmgr_t *manager = client->manager; - if (locked_manager == NULL) { - LOCK(&manager->lock); - locked_manager = manager; - } - ISC_LIST_UNLINK(*client->list, client, link); - client->list = NULL; + if (manager != NULL) { + LOCK(&manager->listlock); + ISC_LIST_UNLINK(manager->clients, client, link); + LOCK(&manager->lock); if (manager->exiting && - ISC_LIST_EMPTY(manager->active) && - ISC_LIST_EMPTY(manager->inactive) && - ISC_LIST_EMPTY(manager->recursing)) - destroy_manager = manager; + ISC_LIST_EMPTY(manager->clients)) + destroy_manager = ISC_TRUE; + UNLOCK(&manager->lock); + UNLOCK(&manager->listlock); } + /* * Detaching the task must be done after unlinking from * the manager's lists because the manager accesses @@ -524,6 +568,7 @@ exit_check(ns_client_t *client) { CTRACE("free"); client->magic = 0; + /* * Check that there are no other external references to * the memory context. @@ -533,22 +578,10 @@ exit_check(ns_client_t *client) { INSIST(0); } isc_mem_putanddetach(&client->mctx, client, sizeof(*client)); - - goto unlock; - } - - unlock: - if (locked_manager != NULL) { - UNLOCK(&locked_manager->lock); - locked_manager = NULL; } - /* - * Only now is it safe to destroy the client manager (if needed), - * because we have accessed its lock for the last time. - */ - if (destroy_manager != NULL) - clientmgr_destroy(destroy_manager); + if (destroy_manager && manager != NULL) + clientmgr_destroy(manager); return (ISC_TRUE); } @@ -604,6 +637,9 @@ client_shutdown(isc_task_t *task, isc_event_t *event) { client->shutdown_arg = NULL; } + if (ISC_QLINK_LINKED(client, ilink)) + ISC_QUEUE_UNLINK(client->manager->inactive, client, ilink); + client->newstate = NS_CLIENTSTATE_FREED; client->needshutdown = ISC_FALSE; (void)exit_check(client); @@ -616,7 +652,8 @@ ns_client_endrequest(ns_client_t *client) { INSIST(client->nsends == 0); INSIST(client->nrecvs == 0); INSIST(client->nupdates == 0); - INSIST(client->state == NS_CLIENTSTATE_WORKING); + INSIST(client->state == NS_CLIENTSTATE_WORKING || + client->state == NS_CLIENTSTATE_RECURSING); CTRACE("endrequest"); @@ -649,46 +686,13 @@ ns_client_endrequest(ns_client_t *client) { client->attributes &= NS_CLIENTATTR_TCP; } -static void -ns_client_checkactive(ns_client_t *client) { - if (client->mortal) { - /* - * This client object should normally go inactive - * at this point, but if we have fewer active client - * objects than desired due to earlier quota exhaustion, - * keep it active to make up for the shortage. - */ - isc_boolean_t need_another_client = ISC_FALSE; - if (TCP_CLIENT(client) && !ns_g_clienttest) { - LOCK(&client->interface->lock); - if (client->interface->ntcpcurrent < - client->interface->ntcptarget) - need_another_client = ISC_TRUE; - UNLOCK(&client->interface->lock); - } else { - /* - * The UDP client quota is enforced by making - * requests fail rather than by not listening - * for new ones. Therefore, there is always a - * full set of UDP clients listening. - */ - } - if (! need_another_client) { - /* - * We don't need this client object. Recycle it. - */ - if (client->newstate >= NS_CLIENTSTATE_INACTIVE) - client->newstate = NS_CLIENTSTATE_INACTIVE; - } - } -} - void ns_client_next(ns_client_t *client, isc_result_t result) { int newstate; REQUIRE(NS_CLIENT_VALID(client)); REQUIRE(client->state == NS_CLIENTSTATE_WORKING || + client->state == NS_CLIENTSTATE_RECURSING || client->state == NS_CLIENTSTATE_READING); CTRACE("next"); @@ -745,9 +749,6 @@ client_senddone(isc_task_t *task, isc_event_t *event) { client->tcpbuf = NULL; } - if (exit_check(client)) - return; - ns_client_next(client, ISC_R_SUCCESS); } @@ -1974,6 +1975,11 @@ static isc_result_t get_clientmctx(ns_clientmgr_t *manager, isc_mem_t **mctxp) { isc_mem_t *clientmctx; isc_result_t result; +#if NMCTXS > 0 + unsigned int nextmctx; +#endif + + MTRACE("clientmctx"); /* * Caller must be holding the manager lock. @@ -1985,19 +1991,21 @@ get_clientmctx(ns_clientmgr_t *manager, isc_mem_t **mctxp) { return (result); } #if NMCTXS > 0 - INSIST(manager->nextmctx < NMCTXS); - clientmctx = manager->mctxpool[manager->nextmctx]; + nextmctx = manager->nextmctx++; + if (manager->nextmctx == NMCTXS) + manager->nextmctx = 0; + + INSIST(nextmctx < NMCTXS); + + clientmctx = manager->mctxpool[nextmctx]; if (clientmctx == NULL) { result = isc_mem_create(0, 0, &clientmctx); if (result != ISC_R_SUCCESS) return (result); isc_mem_setname(clientmctx, "client", NULL); - manager->mctxpool[manager->nextmctx] = clientmctx; + manager->mctxpool[nextmctx] = clientmctx; } - manager->nextmctx++; - if (manager->nextmctx == NMCTXS) - manager->nextmctx = 0; #else clientmctx = manager->mctx; #endif @@ -2118,6 +2126,8 @@ client_create(ns_clientmgr_t *manager, ns_client_t **clientp) { #ifdef ALLOW_FILTER_AAAA_ON_V4 client->filter_aaaa = dns_v4_aaaa_ok; #endif + client->needshutdown = ns_g_clienttest; + ISC_EVENT_INIT(&client->ctlevent, sizeof(client->ctlevent), 0, NULL, NS_EVENT_CLIENTCONTROL, client_start, client, client, NULL, NULL); @@ -2129,7 +2139,8 @@ client_create(ns_clientmgr_t *manager, ns_client_t **clientp) { client->formerrcache.time = 0; client->formerrcache.id = 0; ISC_LINK_INIT(client, link); - client->list = NULL; + ISC_LINK_INIT(client, rlink); + ISC_QLINK_INIT(client, ilink); /* * We call the init routines for the various kinds of client here, @@ -2144,8 +2155,6 @@ client_create(ns_clientmgr_t *manager, ns_client_t **clientp) { if (result != ISC_R_SUCCESS) goto cleanup_query; - client->needshutdown = ns_g_clienttest; - CTRACE("create"); *clientp = client; @@ -2410,10 +2419,8 @@ ns_client_replace(ns_client_t *client) { REQUIRE(client != NULL); REQUIRE(client->manager != NULL); - result = ns_clientmgr_createclients(client->manager, - 1, client->interface, - (TCP_CLIENT(client) ? - ISC_TRUE : ISC_FALSE)); + result = get_client(client->manager, client->interface, + client->dispatch, TCP_CLIENT(client)); if (result != ISC_R_SUCCESS) return (result); @@ -2437,9 +2444,7 @@ clientmgr_destroy(ns_clientmgr_t *manager) { int i; #endif - REQUIRE(ISC_LIST_EMPTY(manager->active)); - REQUIRE(ISC_LIST_EMPTY(manager->inactive)); - REQUIRE(ISC_LIST_EMPTY(manager->recursing)); + REQUIRE(ISC_LIST_EMPTY(manager->clients)); MTRACE("clientmgr_destroy"); @@ -2450,7 +2455,10 @@ clientmgr_destroy(ns_clientmgr_t *manager) { } #endif + ISC_QUEUE_DESTROY(manager->inactive); DESTROYLOCK(&manager->lock); + DESTROYLOCK(&manager->listlock); + DESTROYLOCK(&manager->reclock); manager->magic = 0; isc_mem_put(manager->mctx, manager, sizeof(*manager)); } @@ -2473,13 +2481,21 @@ ns_clientmgr_create(isc_mem_t *mctx, isc_taskmgr_t *taskmgr, if (result != ISC_R_SUCCESS) goto cleanup_manager; + result = isc_mutex_init(&manager->listlock); + if (result != ISC_R_SUCCESS) + goto cleanup_lock; + + result = isc_mutex_init(&manager->reclock); + if (result != ISC_R_SUCCESS) + goto cleanup_listlock; + manager->mctx = mctx; manager->taskmgr = taskmgr; manager->timermgr = timermgr; manager->exiting = ISC_FALSE; - ISC_LIST_INIT(manager->active); - ISC_LIST_INIT(manager->inactive); + ISC_LIST_INIT(manager->clients); ISC_LIST_INIT(manager->recursing); + ISC_QUEUE_INIT(manager->inactive, ilink); #if NMCTXS > 0 manager->nextmctx = 0; for (i = 0; i < NMCTXS; i++) @@ -2493,6 +2509,12 @@ ns_clientmgr_create(isc_mem_t *mctx, isc_taskmgr_t *taskmgr, return (ISC_R_SUCCESS); + cleanup_listlock: + (void) isc_mutex_destroy(&manager->listlock); + + cleanup_lock: + (void) isc_mutex_destroy(&manager->lock); + cleanup_manager: isc_mem_put(manager->mctx, manager, sizeof(*manager)); @@ -2501,9 +2523,10 @@ ns_clientmgr_create(isc_mem_t *mctx, isc_taskmgr_t *taskmgr, void ns_clientmgr_destroy(ns_clientmgr_t **managerp) { + isc_result_t result; ns_clientmgr_t *manager; ns_client_t *client; - isc_boolean_t need_destroy = ISC_FALSE; + isc_boolean_t need_destroy = ISC_FALSE, unlock = ISC_FALSE; REQUIRE(managerp != NULL); manager = *managerp; @@ -2511,31 +2534,27 @@ ns_clientmgr_destroy(ns_clientmgr_t **managerp) { MTRACE("destroy"); - LOCK(&manager->lock); + /* + * Check for success because we may already be task-exclusive + * at this point. Only if we succeed at obtaining an exclusive + * lock now will we need to relinquish it later. + */ + result = isc_task_beginexclusive(ns_g_server->task); + if (result == ISC_R_SUCCESS) + unlock = ISC_TRUE; manager->exiting = ISC_TRUE; - for (client = ISC_LIST_HEAD(manager->recursing); - client != NULL; - client = ISC_LIST_NEXT(client, link)) - isc_task_shutdown(client->task); - - for (client = ISC_LIST_HEAD(manager->active); - client != NULL; - client = ISC_LIST_NEXT(client, link)) - isc_task_shutdown(client->task); - - for (client = ISC_LIST_HEAD(manager->inactive); + for (client = ISC_LIST_HEAD(manager->clients); client != NULL; client = ISC_LIST_NEXT(client, link)) isc_task_shutdown(client->task); - if (ISC_LIST_EMPTY(manager->active) && - ISC_LIST_EMPTY(manager->inactive) && - ISC_LIST_EMPTY(manager->recursing)) + if (ISC_LIST_EMPTY(manager->clients)) need_destroy = ISC_TRUE; - UNLOCK(&manager->lock); + if (unlock) + isc_task_endexclusive(ns_g_server->task); if (need_destroy) clientmgr_destroy(manager); @@ -2543,81 +2562,86 @@ ns_clientmgr_destroy(ns_clientmgr_t **managerp) { *managerp = NULL; } -isc_result_t -ns_clientmgr_createclients(ns_clientmgr_t *manager, unsigned int n, - ns_interface_t *ifp, isc_boolean_t tcp) +static isc_result_t +get_client(ns_clientmgr_t *manager, ns_interface_t *ifp, + dns_dispatch_t *disp, isc_boolean_t tcp) { isc_result_t result = ISC_R_SUCCESS; - unsigned int i; + isc_event_t *ev; ns_client_t *client; + MTRACE("get client"); - REQUIRE(VALID_MANAGER(manager)); - REQUIRE(n > 0); + REQUIRE(manager != NULL); - MTRACE("createclients"); + if (manager->exiting) + return (ISC_R_SHUTTINGDOWN); /* - * We MUST lock the manager lock for the entire client creation - * process. If we didn't do this, then a client could get a - * shutdown event and disappear out from under us. + * Allocate a client. First try to get a recycled one; + * if that fails, make a new one. */ + client = NULL; + if (!ns_g_clienttest) + ISC_QUEUE_POP(manager->inactive, ilink, client); - LOCK(&manager->lock); + if (client != NULL) + MTRACE("recycle"); + else { + MTRACE("create new"); - for (i = 0; i < n; i++) { - isc_event_t *ev; - /* - * Allocate a client. First try to get a recycled one; - * if that fails, make a new one. - */ - client = NULL; - if (!ns_g_clienttest) - client = ISC_LIST_HEAD(manager->inactive); - if (client != NULL) { - MTRACE("recycle"); - ISC_LIST_UNLINK(manager->inactive, client, link); - client->list = NULL; - } else { - MTRACE("create new"); - result = client_create(manager, &client); - if (result != ISC_R_SUCCESS) - break; - } + LOCK(&manager->lock); + result = client_create(manager, &client); + UNLOCK(&manager->lock); + if (result != ISC_R_SUCCESS) + return (result); - ns_interface_attach(ifp, &client->interface); - client->state = NS_CLIENTSTATE_READY; - INSIST(client->recursionquota == NULL); + LOCK(&manager->listlock); + ISC_LIST_APPEND(manager->clients, client, link); + UNLOCK(&manager->listlock); + } - if (tcp) { - client->attributes |= NS_CLIENTATTR_TCP; - isc_socket_attach(ifp->tcpsocket, - &client->tcplistener); - } else { - isc_socket_t *sock; + client->manager = manager; + ns_interface_attach(ifp, &client->interface); + client->state = NS_CLIENTSTATE_READY; + INSIST(client->recursionquota == NULL); - dns_dispatch_attach(ifp->udpdispatch, - &client->dispatch); - sock = dns_dispatch_getsocket(client->dispatch); - isc_socket_attach(sock, &client->udpsocket); - } - client->manager = manager; - ISC_LIST_APPEND(manager->active, client, link); - client->list = &manager->active; + if (tcp) { + client->attributes |= NS_CLIENTATTR_TCP; + isc_socket_attach(ifp->tcpsocket, + &client->tcplistener); + } else { + isc_socket_t *sock; - INSIST(client->nctls == 0); - client->nctls++; - ev = &client->ctlevent; - isc_task_send(client->task, &ev); - } - if (i != 0) { - /* - * We managed to create at least one client, so we - * declare victory. - */ - result = ISC_R_SUCCESS; + dns_dispatch_attach(disp, &client->dispatch); + sock = dns_dispatch_getsocket(client->dispatch); + isc_socket_attach(sock, &client->udpsocket); } - UNLOCK(&manager->lock); + INSIST(client->nctls == 0); + client->nctls++; + ev = &client->ctlevent; + isc_task_send(client->task, &ev); + + return (ISC_R_SUCCESS); +} + +isc_result_t +ns_clientmgr_createclients(ns_clientmgr_t *manager, unsigned int n, + ns_interface_t *ifp, isc_boolean_t tcp) +{ + isc_result_t result = ISC_R_SUCCESS; + unsigned int disp; + + REQUIRE(VALID_MANAGER(manager)); + REQUIRE(n > 0); + + MTRACE("createclients"); + + for (disp = 0; disp < n; disp++) { + result = get_client(manager, ifp, ifp->udpdispatch[disp], tcp); + if (result != ISC_R_SUCCESS) + break; + } return (result); } @@ -2702,19 +2726,41 @@ ns_client_logv(ns_client_t *client, isc_logcategory_t *category, { char msgbuf[2048]; char peerbuf[ISC_SOCKADDR_FORMATSIZE]; - const char *name = ""; - const char *sep = ""; + char signerbuf[DNS_NAME_FORMATSIZE], qnamebuf[DNS_NAME_FORMATSIZE]; + const char *viewname = ""; + const char *sep1 = "", *sep2 = "", *sep3 = "", *sep4 = ""; + const char *signer = "", *qname = ""; + dns_name_t *q = NULL; vsnprintf(msgbuf, sizeof(msgbuf), fmt, ap); + ns_client_name(client, peerbuf, sizeof(peerbuf)); + + if (client->signer != NULL) { + dns_name_format(client->signer, signerbuf, sizeof(signerbuf)); + sep1 = "/key "; + signer = signerbuf; + } + + q = client->query.origqname != NULL + ? client->query.origqname : client->query.qname; + if (q != NULL) { + dns_name_format(q, qnamebuf, sizeof(qnamebuf)); + sep2 = " ("; + sep3 = ")"; + qname = qnamebuf; + } + if (client->view != NULL && strcmp(client->view->name, "_bind") != 0 && strcmp(client->view->name, "_default") != 0) { - name = client->view->name; - sep = ": view "; + sep4 = ": view "; + viewname = client->view->name; } isc_log_write(ns_g_lctx, category, module, level, - "client %s%s%s: %s", peerbuf, sep, name, msgbuf); + "client %s%s%s%s%s%s%s%s: %s", + peerbuf, sep1, signer, sep2, qname, sep3, + sep4, viewname, msgbuf); } void @@ -2796,9 +2842,11 @@ ns_client_dumprecursing(FILE *f, ns_clientmgr_t *manager) { REQUIRE(VALID_MANAGER(manager)); - LOCK(&manager->lock); + LOCK(&manager->reclock); client = ISC_LIST_HEAD(manager->recursing); while (client != NULL) { + INSIST(client->state == NS_CLIENTSTATE_RECURSING); + ns_client_name(client, peerbuf, sizeof(peerbuf)); if (client->view != NULL && strcmp(client->view->name, "_bind") != 0 && @@ -2809,6 +2857,9 @@ ns_client_dumprecursing(FILE *f, ns_clientmgr_t *manager) { name = ""; sep = ""; } + + LOCK(&client->query.fetchlock); + INSIST(client->query.qname != NULL); dns_name_format(client->query.qname, namebuf, sizeof(namebuf)); if (client->query.qname != client->query.origqname && client->query.origqname != NULL) { @@ -2831,20 +2882,19 @@ ns_client_dumprecursing(FILE *f, ns_clientmgr_t *manager) { strcpy(typebuf, "-"); strcpy(classbuf, "-"); } + UNLOCK(&client->query.fetchlock); fprintf(f, "; client %s%s%s: id %u '%s/%s/%s'%s%s " "requesttime %d\n", peerbuf, sep, name, client->message->id, namebuf, typebuf, classbuf, origfor, original, client->requesttime); - client = ISC_LIST_NEXT(client, link); + client = ISC_LIST_NEXT(client, rlink); } - UNLOCK(&manager->lock); + UNLOCK(&manager->reclock); } void ns_client_qnamereplace(ns_client_t *client, dns_name_t *name) { - - if (client->manager != NULL) - LOCK(&client->manager->lock); + LOCK(&client->query.fetchlock); if (client->query.restarts > 0) { /* * client->query.qname was dynamically allocated. @@ -2853,6 +2903,16 @@ ns_client_qnamereplace(ns_client_t *client, dns_name_t *name) { &client->query.qname); } client->query.qname = name; - if (client->manager != NULL) - UNLOCK(&client->manager->lock); + UNLOCK(&client->query.fetchlock); +} + +isc_result_t +ns_client_sourceip(dns_clientinfo_t *ci, isc_sockaddr_t **addrp) { + ns_client_t *client = (ns_client_t *) ci->data; + + REQUIRE(NS_CLIENT_VALID(client)); + REQUIRE(addrp != NULL); + + *addrp = &client->peeraddr; + return (ISC_R_SUCCESS); } diff --git a/contrib/bind9/bin/named/config.c b/contrib/bind9/bin/named/config.c index 25ebac4db0c1..fa349eeade2f 100644 --- a/contrib/bind9/bin/named/config.c +++ b/contrib/bind9/bin/named/config.c @@ -15,7 +15,7 @@ * PERFORMANCE OF THIS SOFTWARE. */ -/* $Id: config.c,v 1.113.16.2 2011/02/28 01:19:58 tbox Exp $ */ +/* $Id: config.c,v 1.123 2012/01/06 23:46:41 tbox Exp $ */ /*! \file */ @@ -73,6 +73,7 @@ options {\n\ listen-on {any;};\n\ listen-on-v6 {none;};\n\ match-mapped-addresses no;\n\ + max-rsa-exponent-size 0; /* no limit */\n\ memstatistics-file \"named.memstats\";\n\ multiple-cnames no;\n\ # named-xfer <obsolete>;\n\ @@ -90,7 +91,7 @@ options {\n\ "\ recursive-clients 1000;\n\ resolver-query-timeout 10;\n\ - rrset-order {type NS order random; order cyclic; };\n\ + rrset-order { order random; };\n\ serial-queries 20;\n\ serial-query-rate 20;\n\ server-id none;\n\ @@ -200,7 +201,8 @@ options {\n\ sig-signing-nodes 100;\n\ sig-signing-signatures 10;\n\ sig-signing-type 65534;\n\ - zone-statistics false;\n\ + inline-signing no;\n\ + zone-statistics terse;\n\ max-journal-size unlimited;\n\ ixfr-from-differences false;\n\ check-wildcard yes;\n\ @@ -210,7 +212,10 @@ options {\n\ check-srv-cname warn;\n\ zero-no-soa-ttl yes;\n\ update-check-ksk yes;\n\ + serial-update-method increment;\n\ + dnssec-update-mode maintain;\n\ dnssec-dnskey-kskonly no;\n\ + dnssec-loadkeys-interval 60;\n\ try-tcp-refresh yes; /* BIND 8 compat */\n\ };\n\ " @@ -292,7 +297,8 @@ ns_checknames_get(const cfg_obj_t **maps, const char *which, if (maps[i] == NULL) return (ISC_R_NOTFOUND); checknames = NULL; - if (cfg_map_get(maps[i], "check-names", &checknames) == ISC_R_SUCCESS) { + if (cfg_map_get(maps[i], "check-names", + &checknames) == ISC_R_SUCCESS) { /* * Zone map entry is not a list. */ @@ -305,7 +311,8 @@ ns_checknames_get(const cfg_obj_t **maps, const char *which, element = cfg_list_next(element)) { value = cfg_listelt_value(element); type = cfg_tuple_get(value, "type"); - if (strcasecmp(cfg_obj_asstring(type), which) == 0) { + if (strcasecmp(cfg_obj_asstring(type), + which) == 0) { *obj = cfg_tuple_get(value, "mode"); return (ISC_R_SUCCESS); } @@ -378,6 +385,8 @@ ns_config_getzonetype(const cfg_obj_t *zonetypeobj) { ztype = dns_zone_stub; else if (strcasecmp(str, "static-stub") == 0) ztype = dns_zone_staticstub; + else if (strcasecmp(str, "redirect") == 0) + ztype = dns_zone_redirect; else INSIST(0); return (ztype); diff --git a/contrib/bind9/bin/named/control.c b/contrib/bind9/bin/named/control.c index 2a1a5a8e734e..fabe442aabc3 100644 --- a/contrib/bind9/bin/named/control.c +++ b/contrib/bind9/bin/named/control.c @@ -1,5 +1,5 @@ /* - * Copyright (C) 2004-2007, 2009, 2010, 2012 Internet Systems Consortium, Inc. ("ISC") + * Copyright (C) 2004-2007, 2009-2012 Internet Systems Consortium, Inc. ("ISC") * Copyright (C) 2001-2003 Internet Software Consortium. * * Permission to use, copy, modify, and/or distribute this software for any @@ -15,7 +15,7 @@ * PERFORMANCE OF THIS SOFTWARE. */ -/* $Id: control.c,v 1.41 2010/12/03 22:05:19 each Exp $ */ +/* $Id$ */ /*! \file */ @@ -154,7 +154,7 @@ ns_control_docommand(isccc_sexpr_t *message, isc_buffer_t *text) { } else if (command_compare(command, NS_COMMAND_DUMPSTATS)) { result = ns_server_dumpstats(ns_g_server); } else if (command_compare(command, NS_COMMAND_QUERYLOG)) { - result = ns_server_togglequerylog(ns_g_server); + result = ns_server_togglequerylog(ns_g_server, command); } else if (command_compare(command, NS_COMMAND_DUMPDB)) { ns_server_dumpdb(ns_g_server, command); result = ISC_R_SUCCESS; @@ -169,7 +169,9 @@ ns_control_docommand(isccc_sexpr_t *message, isc_buffer_t *text) { } else if (command_compare(command, NS_COMMAND_FLUSH)) { result = ns_server_flushcache(ns_g_server, command); } else if (command_compare(command, NS_COMMAND_FLUSHNAME)) { - result = ns_server_flushname(ns_g_server, command); + result = ns_server_flushnode(ns_g_server, command, ISC_FALSE); + } else if (command_compare(command, NS_COMMAND_FLUSHTREE)) { + result = ns_server_flushnode(ns_g_server, command, ISC_TRUE); } else if (command_compare(command, NS_COMMAND_STATUS)) { result = ns_server_status(ns_g_server, text); } else if (command_compare(command, NS_COMMAND_TSIGLIST)) { @@ -183,6 +185,8 @@ ns_control_docommand(isccc_sexpr_t *message, isc_buffer_t *text) { command_compare(command, NS_COMMAND_THAW)) { result = ns_server_freeze(ns_g_server, ISC_FALSE, command, text); + } else if (command_compare(command, NS_COMMAND_SYNC)) { + result = ns_server_sync(ns_g_server, command, text); } else if (command_compare(command, NS_COMMAND_RECURSING)) { result = ns_server_dumprecursing(ns_g_server); } else if (command_compare(command, NS_COMMAND_TIMERPOKE)) { @@ -201,6 +205,8 @@ ns_control_docommand(isccc_sexpr_t *message, isc_buffer_t *text) { result = ns_server_add_zone(ns_g_server, command); } else if (command_compare(command, NS_COMMAND_DELZONE)) { result = ns_server_del_zone(ns_g_server, command); + } else if (command_compare(command, NS_COMMAND_SIGNING)) { + result = ns_server_signing(ns_g_server, command, text); } else { isc_log_write(ns_g_lctx, NS_LOGCATEGORY_GENERAL, NS_LOGMODULE_CONTROL, ISC_LOG_WARNING, diff --git a/contrib/bind9/bin/named/controlconf.c b/contrib/bind9/bin/named/controlconf.c index 73c0f37e9737..c46a6e15f467 100644 --- a/contrib/bind9/bin/named/controlconf.c +++ b/contrib/bind9/bin/named/controlconf.c @@ -15,7 +15,7 @@ * PERFORMANCE OF THIS SOFTWARE. */ -/* $Id: controlconf.c,v 1.60.544.3 2011/12/22 08:10:09 marka Exp $ */ +/* $Id: controlconf.c,v 1.63 2011/12/22 08:07:48 marka Exp $ */ /*! \file */ diff --git a/contrib/bind9/bin/named/include/dlz/dlz_dlopen_driver.h b/contrib/bind9/bin/named/include/dlz/dlz_dlopen_driver.h index 7af325a13b30..602b3c074d12 100644 --- a/contrib/bind9/bin/named/include/dlz/dlz_dlopen_driver.h +++ b/contrib/bind9/bin/named/include/dlz/dlz_dlopen_driver.h @@ -14,7 +14,7 @@ * PERFORMANCE OF THIS SOFTWARE. */ -/* $Id: dlz_dlopen_driver.h,v 1.1.4.4 2011/03/17 09:41:06 fdupont Exp $ */ +/* $Id: dlz_dlopen_driver.h,v 1.4 2011/03/17 09:25:53 fdupont Exp $ */ #ifndef DLZ_DLOPEN_DRIVER_H #define DLZ_DLOPEN_DRIVER_H diff --git a/contrib/bind9/bin/named/include/named/client.h b/contrib/bind9/bin/named/include/named/client.h index e6414d2f7a7a..98e79df70668 100644 --- a/contrib/bind9/bin/named/include/named/client.h +++ b/contrib/bind9/bin/named/include/named/client.h @@ -1,5 +1,5 @@ /* - * Copyright (C) 2004-2009, 2012 Internet Systems Consortium, Inc. ("ISC") + * Copyright (C) 2004-2009, 2011, 2012 Internet Systems Consortium, Inc. ("ISC") * Copyright (C) 1999-2003 Internet Software Consortium. * * Permission to use, copy, modify, and/or distribute this software for any @@ -15,7 +15,7 @@ * PERFORMANCE OF THIS SOFTWARE. */ -/* $Id: client.h,v 1.91.278.2 2012/01/31 23:46:39 tbox Exp $ */ +/* $Id$ */ #ifndef NAMED_CLIENT_H #define NAMED_CLIENT_H 1 @@ -66,7 +66,9 @@ #include <isc/magic.h> #include <isc/stdtime.h> #include <isc/quota.h> +#include <isc/queue.h> +#include <dns/db.h> #include <dns/fixedname.h> #include <dns/name.h> #include <dns/rdataclass.h> @@ -81,8 +83,6 @@ *** Types ***/ -typedef ISC_LIST(ns_client_t) client_list_t; - /*% nameserver client structure */ struct ns_client { unsigned int magic; @@ -155,13 +155,15 @@ struct ns_client { isc_stdtime_t time; dns_messageid_t id; } formerrcache; + ISC_LINK(ns_client_t) link; - /*% - * The list 'link' is part of, or NULL if not on any list. - */ - client_list_t *list; + ISC_LINK(ns_client_t) rlink; + ISC_QLINK(ns_client_t) ilink; }; +typedef ISC_QUEUE(ns_client_t) client_queue_t; +typedef ISC_LIST(ns_client_t) client_list_t; + #define NS_CLIENT_MAGIC ISC_MAGIC('N','S','C','c') #define NS_CLIENT_VALID(c) ISC_MAGIC_VALID(c, NS_CLIENT_MAGIC) @@ -379,4 +381,7 @@ ns_client_isself(dns_view_t *myview, dns_tsigkey_t *mykey, * Isself callback. */ +isc_result_t +ns_client_sourceip(dns_clientinfo_t *ci, isc_sockaddr_t **addrp); + #endif /* NAMED_CLIENT_H */ diff --git a/contrib/bind9/bin/named/include/named/control.h b/contrib/bind9/bin/named/include/named/control.h index 24e59093b4d1..d730a83280cd 100644 --- a/contrib/bind9/bin/named/include/named/control.h +++ b/contrib/bind9/bin/named/include/named/control.h @@ -1,5 +1,5 @@ /* - * Copyright (C) 2004-2007, 2009, 2010 Internet Systems Consortium, Inc. ("ISC") + * Copyright (C) 2004-2007, 2009-2012 Internet Systems Consortium, Inc. ("ISC") * Copyright (C) 2001-2003 Internet Software Consortium. * * Permission to use, copy, modify, and/or distribute this software for any @@ -15,7 +15,7 @@ * PERFORMANCE OF THIS SOFTWARE. */ -/* $Id: control.h,v 1.31 2010/08/16 22:21:06 marka Exp $ */ +/* $Id$ */ #ifndef NAMED_CONTROL_H #define NAMED_CONTROL_H 1 @@ -47,6 +47,7 @@ #define NS_COMMAND_NOTRACE "notrace" #define NS_COMMAND_FLUSH "flush" #define NS_COMMAND_FLUSHNAME "flushname" +#define NS_COMMAND_FLUSHTREE "flushtree" #define NS_COMMAND_STATUS "status" #define NS_COMMAND_TSIGLIST "tsig-list" #define NS_COMMAND_TSIGDELETE "tsig-delete" @@ -62,6 +63,8 @@ #define NS_COMMAND_LOADKEYS "loadkeys" #define NS_COMMAND_ADDZONE "addzone" #define NS_COMMAND_DELZONE "delzone" +#define NS_COMMAND_SYNC "sync" +#define NS_COMMAND_SIGNING "signing" isc_result_t ns_controls_create(ns_server_t *server, ns_controls_t **ctrlsp); diff --git a/contrib/bind9/bin/named/include/named/globals.h b/contrib/bind9/bin/named/include/named/globals.h index 39307f36996b..cbc14d8b72d9 100644 --- a/contrib/bind9/bin/named/include/named/globals.h +++ b/contrib/bind9/bin/named/include/named/globals.h @@ -15,7 +15,7 @@ * PERFORMANCE OF THIS SOFTWARE. */ -/* $Id: globals.h,v 1.89.54.2 2011/06/17 23:47:10 tbox Exp $ */ +/* $Id: globals.h,v 1.92 2011/11/09 18:44:04 each Exp $ */ #ifndef NAMED_GLOBALS_H #define NAMED_GLOBALS_H 1 @@ -51,6 +51,7 @@ EXTERN isc_mem_t * ns_g_mctx INIT(NULL); EXTERN unsigned int ns_g_cpus INIT(0); +EXTERN unsigned int ns_g_udpdisp INIT(0); EXTERN isc_taskmgr_t * ns_g_taskmgr INIT(NULL); EXTERN dns_dispatchmgr_t * ns_g_dispatchmgr INIT(NULL); EXTERN isc_entropy_t * ns_g_entropy INIT(NULL); diff --git a/contrib/bind9/bin/named/include/named/interfacemgr.h b/contrib/bind9/bin/named/include/named/interfacemgr.h index 2724c393cdc5..380dbedd7686 100644 --- a/contrib/bind9/bin/named/include/named/interfacemgr.h +++ b/contrib/bind9/bin/named/include/named/interfacemgr.h @@ -1,5 +1,5 @@ /* - * Copyright (C) 2004, 2005, 2007 Internet Systems Consortium, Inc. ("ISC") + * Copyright (C) 2004, 2005, 2007, 2011 Internet Systems Consortium, Inc. ("ISC") * Copyright (C) 1999-2002 Internet Software Consortium. * * Permission to use, copy, modify, and/or distribute this software for any @@ -15,7 +15,7 @@ * PERFORMANCE OF THIS SOFTWARE. */ -/* $Id: interfacemgr.h,v 1.33 2007/06/19 23:46:59 tbox Exp $ */ +/* $Id: interfacemgr.h,v 1.35 2011/07/28 23:47:58 tbox Exp $ */ #ifndef NAMED_INTERFACEMGR_H #define NAMED_INTERFACEMGR_H 1 @@ -65,7 +65,8 @@ #define NS_INTERFACE_VALID(t) ISC_MAGIC_VALID(t, IFACE_MAGIC) #define NS_INTERFACEFLAG_ANYADDR 0x01U /*%< bound to "any" address */ - +#define MAX_UDP_DISPATCH 128 /*%< Maximum number of UDP dispatchers + to start per interface */ /*% The nameserver interface structure */ struct ns_interface { unsigned int magic; /*%< Magic number. */ @@ -76,11 +77,13 @@ struct ns_interface { isc_sockaddr_t addr; /*%< Address and port. */ unsigned int flags; /*%< Interface characteristics */ char name[32]; /*%< Null terminated. */ - dns_dispatch_t * udpdispatch; /*%< UDP dispatcher. */ + dns_dispatch_t * udpdispatch[MAX_UDP_DISPATCH]; + /*%< UDP dispatchers. */ isc_socket_t * tcpsocket; /*%< TCP socket. */ int ntcptarget; /*%< Desired number of concurrent TCP accepts */ int ntcpcurrent; /*%< Current ditto, locked */ + int nudpdispatch; /*%< Number of UDP dispatches */ ns_clientmgr_t * clientmgr; /*%< Client manager. */ ISC_LINK(ns_interface_t) link; }; diff --git a/contrib/bind9/bin/named/include/named/server.h b/contrib/bind9/bin/named/include/named/server.h index 9982e88e09e4..3ba0c64a712d 100644 --- a/contrib/bind9/bin/named/include/named/server.h +++ b/contrib/bind9/bin/named/include/named/server.h @@ -1,5 +1,5 @@ /* - * Copyright (C) 2004-2010, 2013 Internet Systems Consortium, Inc. ("ISC") + * Copyright (C) 2004-2013 Internet Systems Consortium, Inc. ("ISC") * Copyright (C) 1999-2003 Internet Software Consortium. * * Permission to use, copy, modify, and/or distribute this software for any @@ -15,7 +15,7 @@ * PERFORMANCE OF THIS SOFTWARE. */ -/* $Id: server.h,v 1.110 2010/08/16 23:46:52 tbox Exp $ */ +/* $Id$ */ #ifndef NAMED_SERVER_H #define NAMED_SERVER_H 1 @@ -230,9 +230,10 @@ ns_server_retransfercommand(ns_server_t *server, char *args); */ isc_result_t -ns_server_togglequerylog(ns_server_t *server); +ns_server_togglequerylog(ns_server_t *server, char *args); /*%< - * Toggle logging of queries, as in BIND 8. + * Enable/disable logging of queries. (Takes "yes" or "no" argument, + * but can also be used as a toggle for backward comptibility.) */ /*% @@ -266,10 +267,12 @@ isc_result_t ns_server_flushcache(ns_server_t *server, char *args); /*% - * Flush a particular name from the server's cache(s) + * Flush a particular name from the server's cache. If 'tree' is false, + * also flush the name from the ADB and badcache. If 'tree' is true, also + * flush all the names under the specified name. */ isc_result_t -ns_server_flushname(ns_server_t *server, char *args); +ns_server_flushnode(ns_server_t *server, char *args, isc_boolean_t tree); /*% * Report the server's status. @@ -297,6 +300,12 @@ ns_server_freeze(ns_server_t *server, isc_boolean_t freeze, char *args, isc_buffer_t *text); /*% + * Dump zone updates to disk, optionally removing the journal file + */ +isc_result_t +ns_server_sync(ns_server_t *server, char *args, isc_buffer_t *text); + +/*% * Update a zone's DNSKEY set from the key repository. If * the command that triggered the call to this function was "sign", * then force a full signing of the zone. If it was "loadkeys", @@ -336,4 +345,9 @@ ns_server_add_zone(ns_server_t *server, char *args); isc_result_t ns_server_del_zone(ns_server_t *server, char *args); +/*% + * Lists the status of the signing records for a given zone. + */ +isc_result_t +ns_server_signing(ns_server_t *server, char *args, isc_buffer_t *text); #endif /* NAMED_SERVER_H */ diff --git a/contrib/bind9/bin/named/include/named/zoneconf.h b/contrib/bind9/bin/named/include/named/zoneconf.h index ebaad684ae7a..0e684d2d4c7e 100644 --- a/contrib/bind9/bin/named/include/named/zoneconf.h +++ b/contrib/bind9/bin/named/include/named/zoneconf.h @@ -1,5 +1,5 @@ /* - * Copyright (C) 2004-2007, 2010 Internet Systems Consortium, Inc. ("ISC") + * Copyright (C) 2004-2007, 2010, 2011 Internet Systems Consortium, Inc. ("ISC") * Copyright (C) 1999-2002 Internet Software Consortium. * * Permission to use, copy, modify, and/or distribute this software for any @@ -15,7 +15,7 @@ * PERFORMANCE OF THIS SOFTWARE. */ -/* $Id: zoneconf.h,v 1.28 2010/12/20 23:47:20 tbox Exp $ */ +/* $Id: zoneconf.h,v 1.30 2011/08/30 23:46:51 tbox Exp $ */ #ifndef NS_ZONECONF_H #define NS_ZONECONF_H 1 @@ -33,7 +33,7 @@ ISC_LANG_BEGINDECLS isc_result_t ns_zone_configure(const cfg_obj_t *config, const cfg_obj_t *vconfig, const cfg_obj_t *zconfig, cfg_aclconfctx_t *ac, - dns_zone_t *zone); + dns_zone_t *zone, dns_zone_t *raw); /*%< * Configure or reconfigure a zone according to the named.conf * data in 'cctx' and 'czone'. diff --git a/contrib/bind9/bin/named/interfacemgr.c b/contrib/bind9/bin/named/interfacemgr.c index 15ffe00aa51a..84bf21d77142 100644 --- a/contrib/bind9/bin/named/interfacemgr.c +++ b/contrib/bind9/bin/named/interfacemgr.c @@ -1,5 +1,5 @@ /* - * Copyright (C) 2004-2009, 2011, 2013 Internet Systems Consortium, Inc. ("ISC") + * Copyright (C) 2004-2009, 2011-2013 Internet Systems Consortium, Inc. ("ISC") * Copyright (C) 1999-2002 Internet Software Consortium. * * Permission to use, copy, modify, and/or distribute this software for any @@ -15,13 +15,14 @@ * PERFORMANCE OF THIS SOFTWARE. */ -/* $Id: interfacemgr.c,v 1.95.426.2 2011/03/12 04:59:14 tbox Exp $ */ +/* $Id: interfacemgr.c,v 1.101 2011/11/09 18:44:03 each Exp $ */ /*! \file */ #include <config.h> #include <isc/interfaceiter.h> +#include <isc/os.h> #include <isc/string.h> #include <isc/task.h> #include <isc/util.h> @@ -185,11 +186,14 @@ ns_interface_create(ns_interfacemgr_t *mgr, isc_sockaddr_t *addr, { ns_interface_t *ifp; isc_result_t result; + int disp; REQUIRE(NS_INTERFACEMGR_VALID(mgr)); + ifp = isc_mem_get(mgr->mctx, sizeof(*ifp)); if (ifp == NULL) return (ISC_R_NOMEMORY); + ifp->mgr = NULL; ifp->generation = mgr->generation; ifp->addr = *addr; @@ -212,9 +216,11 @@ ns_interface_create(ns_interfacemgr_t *mgr, isc_sockaddr_t *addr, goto clientmgr_create_failure; } - ifp->udpdispatch = NULL; + for (disp = 0; disp < MAX_UDP_DISPATCH; disp++) + ifp->udpdispatch[disp] = NULL; ifp->tcpsocket = NULL; + /* * Create a single TCP client object. It will replace itself * with a new one as soon as it gets a connection, so the actual @@ -223,6 +229,7 @@ ns_interface_create(ns_interfacemgr_t *mgr, isc_sockaddr_t *addr, */ ifp->ntcptarget = 1; ifp->ntcpcurrent = 0; + ifp->nudpdispatch = 0; ISC_LINK_INIT(ifp, link); @@ -237,6 +244,7 @@ ns_interface_create(ns_interfacemgr_t *mgr, isc_sockaddr_t *addr, clientmgr_create_failure: DESTROYLOCK(&ifp->lock); + lock_create_failure: ifp->magic = 0; isc_mem_put(mgr->mctx, ifp, sizeof(*ifp)); @@ -249,6 +257,7 @@ ns_interface_listenudp(ns_interface_t *ifp) { isc_result_t result; unsigned int attrs; unsigned int attrmask; + int disp, i; attrs = 0; attrs |= DNS_DISPATCHATTR_UDP; @@ -260,18 +269,28 @@ ns_interface_listenudp(ns_interface_t *ifp) { attrmask = 0; attrmask |= DNS_DISPATCHATTR_UDP | DNS_DISPATCHATTR_TCP; attrmask |= DNS_DISPATCHATTR_IPV4 | DNS_DISPATCHATTR_IPV6; - result = dns_dispatch_getudp(ifp->mgr->dispatchmgr, ns_g_socketmgr, - ns_g_taskmgr, &ifp->addr, - 4096, 1000, 32768, 8219, 8237, - attrs, attrmask, &ifp->udpdispatch); - if (result != ISC_R_SUCCESS) { - isc_log_write(IFMGR_COMMON_LOGARGS, ISC_LOG_ERROR, - "could not listen on UDP socket: %s", - isc_result_totext(result)); - goto udp_dispatch_failure; + + ifp->nudpdispatch = ISC_MIN(ns_g_udpdisp, MAX_UDP_DISPATCH); + for (disp = 0; disp < ifp->nudpdispatch; disp++) { + result = dns_dispatch_getudp_dup(ifp->mgr->dispatchmgr, + ns_g_socketmgr, + ns_g_taskmgr, &ifp->addr, + 4096, 1000, 32768, 8219, 8237, + attrs, attrmask, + &ifp->udpdispatch[disp], + disp == 0 + ? NULL + : ifp->udpdispatch[0]); + if (result != ISC_R_SUCCESS) { + isc_log_write(IFMGR_COMMON_LOGARGS, ISC_LOG_ERROR, + "could not listen on UDP socket: %s", + isc_result_totext(result)); + goto udp_dispatch_failure; + } + } - result = ns_clientmgr_createclients(ifp->clientmgr, ns_g_cpus, + result = ns_clientmgr_createclients(ifp->clientmgr, ifp->nudpdispatch, ifp, ISC_FALSE); if (result != ISC_R_SUCCESS) { UNEXPECTED_ERROR(__FILE__, __LINE__, @@ -279,12 +298,17 @@ ns_interface_listenudp(ns_interface_t *ifp) { isc_result_totext(result)); goto addtodispatch_failure; } + return (ISC_R_SUCCESS); addtodispatch_failure: - dns_dispatch_changeattributes(ifp->udpdispatch, 0, - DNS_DISPATCHATTR_NOLISTEN); - dns_dispatch_detach(&ifp->udpdispatch); + for (i = disp - 1; i <= 0; i--) { + dns_dispatch_changeattributes(ifp->udpdispatch[i], 0, + DNS_DISPATCHATTR_NOLISTEN); + dns_dispatch_detach(&(ifp->udpdispatch[i])); + } + ifp->nudpdispatch = 0; + udp_dispatch_failure: return (result); } @@ -398,15 +422,19 @@ ns_interface_shutdown(ns_interface_t *ifp) { static void ns_interface_destroy(ns_interface_t *ifp) { isc_mem_t *mctx = ifp->mgr->mctx; + int disp; + REQUIRE(NS_INTERFACE_VALID(ifp)); ns_interface_shutdown(ifp); - if (ifp->udpdispatch != NULL) { - dns_dispatch_changeattributes(ifp->udpdispatch, 0, - DNS_DISPATCHATTR_NOLISTEN); - dns_dispatch_detach(&ifp->udpdispatch); - } + for (disp = 0; disp < ifp->nudpdispatch; disp++) + if (ifp->udpdispatch[disp] != NULL) { + dns_dispatch_changeattributes(ifp->udpdispatch[disp], 0, + DNS_DISPATCHATTR_NOLISTEN); + dns_dispatch_detach(&(ifp->udpdispatch[disp])); + } + if (ifp->tcpsocket != NULL) isc_socket_detach(&ifp->tcpsocket); diff --git a/contrib/bind9/bin/named/logconf.c b/contrib/bind9/bin/named/logconf.c index f02b97fcddee..b99a167d12f1 100644 --- a/contrib/bind9/bin/named/logconf.c +++ b/contrib/bind9/bin/named/logconf.c @@ -15,7 +15,7 @@ * PERFORMANCE OF THIS SOFTWARE. */ -/* $Id: logconf.c,v 1.42.816.3 2011/03/05 23:52:06 tbox Exp $ */ +/* $Id: logconf.c,v 1.45 2011/03/05 23:52:29 tbox Exp $ */ /*! \file */ diff --git a/contrib/bind9/bin/named/main.c b/contrib/bind9/bin/named/main.c index f6c929e5b967..a5467249082a 100644 --- a/contrib/bind9/bin/named/main.c +++ b/contrib/bind9/bin/named/main.c @@ -15,7 +15,7 @@ * PERFORMANCE OF THIS SOFTWARE. */ -/* $Id: main.c,v 1.180.14.4 2011/11/05 00:45:52 each Exp $ */ +/* $Id$ */ /*! \file */ @@ -418,7 +418,7 @@ parse_command_line(int argc, char *argv[]) { isc_commandline_errprint = ISC_FALSE; while ((ch = isc_commandline_parse(argc, argv, "46c:C:d:E:fFgi:lm:n:N:p:P:" - "sS:t:T:u:vVx:")) != -1) { + "sS:t:T:U:u:vVx:")) != -1) { switch (ch) { case '4': if (disable4) @@ -531,6 +531,11 @@ parse_command_line(int argc, char *argv[]) { fprintf(stderr, "unknown -T flag '%s\n", isc_commandline_argument); break; + case 'U': + ns_g_udpdisp = parse_int(isc_commandline_argument, + "number of UDP listeners " + "per interface"); + break; case 'u': ns_g_username = isc_commandline_argument; break; @@ -595,6 +600,18 @@ create_managers(void) { #else ns_g_cpus = 1; #endif +#ifdef WIN32 + ns_g_udpdisp = 1; +#else + if (ns_g_udpdisp == 0) + ns_g_udpdisp = ns_g_cpus_detected; + if (ns_g_udpdisp > ns_g_cpus) + ns_g_udpdisp = ns_g_cpus; +#endif + isc_log_write(ns_g_lctx, NS_LOGCATEGORY_GENERAL, NS_LOGMODULE_SERVER, + ISC_LOG_INFO, "using %u UDP listener%s per interface", + ns_g_udpdisp, ns_g_udpdisp == 1 ? "" : "s"); + result = isc_taskmgr_create(ns_g_mctx, ns_g_cpus, 0, &ns_g_taskmgr); if (result != ISC_R_SUCCESS) { UNEXPECTED_ERROR(__FILE__, __LINE__, diff --git a/contrib/bind9/bin/named/named.8 b/contrib/bind9/bin/named/named.8 index 222ff426cabd..b27be3185997 100644 --- a/contrib/bind9/bin/named/named.8 +++ b/contrib/bind9/bin/named/named.8 @@ -1,4 +1,4 @@ -.\" Copyright (C) 2004-2009 Internet Systems Consortium, Inc. ("ISC") +.\" Copyright (C) 2004-2009, 2011, 2013 Internet Systems Consortium, Inc. ("ISC") .\" Copyright (C) 2000, 2001, 2003 Internet Software Consortium. .\" .\" Permission to use, copy, modify, and/or distribute this software for any @@ -33,7 +33,7 @@ named \- Internet domain name server .SH "SYNOPSIS" .HP 6 -\fBnamed\fR [\fB\-4\fR] [\fB\-6\fR] [\fB\-c\ \fR\fB\fIconfig\-file\fR\fR] [\fB\-d\ \fR\fB\fIdebug\-level\fR\fR] [\fB\-E\ \fR\fB\fIengine\-name\fR\fR] [\fB\-f\fR] [\fB\-g\fR] [\fB\-m\ \fR\fB\fIflag\fR\fR] [\fB\-n\ \fR\fB\fI#cpus\fR\fR] [\fB\-p\ \fR\fB\fIport\fR\fR] [\fB\-s\fR] [\fB\-S\ \fR\fB\fI#max\-socks\fR\fR] [\fB\-t\ \fR\fB\fIdirectory\fR\fR] [\fB\-u\ \fR\fB\fIuser\fR\fR] [\fB\-v\fR] [\fB\-V\fR] [\fB\-x\ \fR\fB\fIcache\-file\fR\fR] +\fBnamed\fR [\fB\-4\fR] [\fB\-6\fR] [\fB\-c\ \fR\fB\fIconfig\-file\fR\fR] [\fB\-d\ \fR\fB\fIdebug\-level\fR\fR] [\fB\-E\ \fR\fB\fIengine\-name\fR\fR] [\fB\-f\fR] [\fB\-g\fR] [\fB\-m\ \fR\fB\fIflag\fR\fR] [\fB\-n\ \fR\fB\fI#cpus\fR\fR] [\fB\-p\ \fR\fB\fIport\fR\fR] [\fB\-s\fR] [\fB\-S\ \fR\fB\fI#max\-socks\fR\fR] [\fB\-t\ \fR\fB\fIdirectory\fR\fR] [\fB\-U\ \fR\fB\fI#listeners\fR\fR] [\fB\-u\ \fR\fB\fIuser\fR\fR] [\fB\-v\fR] [\fB\-V\fR] [\fB\-x\ \fR\fB\fIcache\-file\fR\fR] .SH "DESCRIPTION" .PP \fBnamed\fR @@ -168,6 +168,19 @@ is defined allows a process with root privileges to escape a chroot jail. .RE .RE .PP +\-U \fI#listeners\fR +.RS 4 +Use +\fI#listeners\fR +worker threads to listen for incoming UDP packets on each address. If not specified, +\fBnamed\fR +will use the number of detected CPUs. If +\fB\-n\fR +has been set to a higher value than the number of CPUs, then +\fB\-U\fR +may be increased as high as that value, but no higher. +.RE +.PP \-u \fIuser\fR .RS 4 Setuid to @@ -267,7 +280,7 @@ BIND 9 Administrator Reference Manual. .PP Internet Systems Consortium .SH "COPYRIGHT" -Copyright \(co 2004\-2009 Internet Systems Consortium, Inc. ("ISC") +Copyright \(co 2004\-2009, 2011, 2013 Internet Systems Consortium, Inc. ("ISC") .br Copyright \(co 2000, 2001, 2003 Internet Software Consortium. .br diff --git a/contrib/bind9/bin/named/named.conf.5 b/contrib/bind9/bin/named/named.conf.5 index 09b147ee7de2..8d0122280b8a 100644 --- a/contrib/bind9/bin/named/named.conf.5 +++ b/contrib/bind9/bin/named/named.conf.5 @@ -289,7 +289,8 @@ options { notify\-delay \fIseconds\fR; notify\-to\-soa \fIboolean\fR; also\-notify [ port \fIinteger\fR ] { ( \fIipv4_address\fR | \fIipv6_address\fR ) - [ port \fIinteger\fR ]; ... }; + [ port \fIinteger\fR ]; ... + [ key \fIkeyname\fR ] ... }; allow\-notify { \fIaddress_match_element\fR; ... }; forward ( first | only ); forwarders [ port \fIinteger\fR ] { @@ -458,7 +459,8 @@ view \fIstring\fR \fIoptional_class\fR { notify\-delay \fIseconds\fR; notify\-to\-soa \fIboolean\fR; also\-notify [ port \fIinteger\fR ] { ( \fIipv4_address\fR | \fIipv6_address\fR ) - [ port \fIinteger\fR ]; ... }; + [ port \fIinteger\fR ]; ... + [ key \fIkeyname\fR ] ... }; allow\-notify { \fIaddress_match_element\fR; ... }; forward ( first | only ); forwarders [ port \fIinteger\fR ] { @@ -502,7 +504,7 @@ view \fIstring\fR \fIoptional_class\fR { .RS 4 .nf zone \fIstring\fR \fIoptional_class\fR { - type ( master | slave | stub | hint | + type ( master | slave | stub | hint | redirect | forward | delegation\-only ); file \fIquoted_string\fR; masters [ port \fIinteger\fR ] { @@ -544,7 +546,8 @@ zone \fIstring\fR \fIoptional_class\fR { notify\-delay \fIseconds\fR; notify\-to\-soa \fIboolean\fR; also\-notify [ port \fIinteger\fR ] { ( \fIipv4_address\fR | \fIipv6_address\fR ) - [ port \fIinteger\fR ]; ... }; + [ port \fIinteger\fR ]; ... + [ key \fIkeyname\fR ] ... }; allow\-notify { \fIaddress_match_element\fR; ... }; forward ( first | only ); forwarders [ port \fIinteger\fR ] { @@ -560,6 +563,7 @@ zone \fIstring\fR \fIoptional_class\fR { max\-refresh\-time \fIinteger\fR; min\-refresh\-time \fIinteger\fR; multi\-master \fIboolean\fR; + request\-ixfr \fIboolean\fR; sig\-validity\-interval \fIinteger\fR; transfer\-source ( \fIipv4_address\fR | * ) [ port ( \fIinteger\fR | * ) ]; diff --git a/contrib/bind9/bin/named/named.conf.docbook b/contrib/bind9/bin/named/named.conf.docbook index 2527ac3ae7e8..d778706930e0 100644 --- a/contrib/bind9/bin/named/named.conf.docbook +++ b/contrib/bind9/bin/named/named.conf.docbook @@ -17,7 +17,7 @@ - PERFORMANCE OF THIS SOFTWARE. --> -<!-- $Id: named.conf.docbook,v 1.49.14.2 2011/11/07 00:31:47 marka Exp $ --> +<!-- $Id: named.conf.docbook,v 1.55 2011/11/07 00:25:53 each Exp $ --> <refentry> <refentryinfo> <date>Aug 13, 2004</date> @@ -326,7 +326,8 @@ options { notify-delay <replaceable>seconds</replaceable>; notify-to-soa <replaceable>boolean</replaceable>; also-notify <optional> port <replaceable>integer</replaceable> </optional> { ( <replaceable>ipv4_address</replaceable> | <replaceable>ipv6_address</replaceable> ) - <optional> port <replaceable>integer</replaceable> </optional>; ... }; + <optional> port <replaceable>integer</replaceable> </optional>; ... + <optional> key <replaceable>keyname</replaceable> </optional> ... }; allow-notify { <replaceable>address_match_element</replaceable>; ... }; forward ( first | only ); @@ -513,7 +514,8 @@ view <replaceable>string</replaceable> <replaceable>optional_class</replaceable> notify-delay <replaceable>seconds</replaceable>; notify-to-soa <replaceable>boolean</replaceable>; also-notify <optional> port <replaceable>integer</replaceable> </optional> { ( <replaceable>ipv4_address</replaceable> | <replaceable>ipv6_address</replaceable> ) - <optional> port <replaceable>integer</replaceable> </optional>; ... }; + <optional> port <replaceable>integer</replaceable> </optional>; ... + <optional> key <replaceable>keyname</replaceable> </optional> ... }; allow-notify { <replaceable>address_match_element</replaceable>; ... }; forward ( first | only ); @@ -563,7 +565,7 @@ view <replaceable>string</replaceable> <replaceable>optional_class</replaceable> <title>ZONE</title> <literallayout> zone <replaceable>string</replaceable> <replaceable>optional_class</replaceable> { - type ( master | slave | stub | hint | + type ( master | slave | stub | hint | redirect | forward | delegation-only ); file <replaceable>quoted_string</replaceable>; @@ -609,7 +611,8 @@ zone <replaceable>string</replaceable> <replaceable>optional_class</replaceable> notify-delay <replaceable>seconds</replaceable>; notify-to-soa <replaceable>boolean</replaceable>; also-notify <optional> port <replaceable>integer</replaceable> </optional> { ( <replaceable>ipv4_address</replaceable> | <replaceable>ipv6_address</replaceable> ) - <optional> port <replaceable>integer</replaceable> </optional>; ... }; + <optional> port <replaceable>integer</replaceable> </optional>; ... + <optional> key <replaceable>keyname</replaceable> </optional> ... }; allow-notify { <replaceable>address_match_element</replaceable>; ... }; forward ( first | only ); @@ -627,6 +630,7 @@ zone <replaceable>string</replaceable> <replaceable>optional_class</replaceable> max-refresh-time <replaceable>integer</replaceable>; min-refresh-time <replaceable>integer</replaceable>; multi-master <replaceable>boolean</replaceable>; + request-ixfr <replaceable>boolean</replaceable>; sig-validity-interval <replaceable>integer</replaceable>; transfer-source ( <replaceable>ipv4_address</replaceable> | * ) diff --git a/contrib/bind9/bin/named/named.conf.html b/contrib/bind9/bin/named/named.conf.html index a8b35edc8602..23d9391af3d0 100644 --- a/contrib/bind9/bin/named/named.conf.html +++ b/contrib/bind9/bin/named/named.conf.html @@ -21,7 +21,7 @@ <meta name="generator" content="DocBook XSL Stylesheets V1.71.1"> </head> <body bgcolor="white" text="black" link="#0000FF" vlink="#840084" alink="#0000FF"><div class="refentry" lang="en"> -<a name="id2476275"></a><div class="titlepage"></div> +<a name="id2476274"></a><div class="titlepage"></div> <div class="refnamediv"> <h2>Name</h2> <p><code class="filename">named.conf</code> — configuration file for named</p> @@ -31,7 +31,7 @@ <div class="cmdsynopsis"><p><code class="command">named.conf</code> </p></div> </div> <div class="refsect1" lang="en"> -<a name="id2543356"></a><h2>DESCRIPTION</h2> +<a name="id2543357"></a><h2>DESCRIPTION</h2> <p><code class="filename">named.conf</code> is the configuration file for <span><strong class="command">named</strong></span>. Statements are enclosed @@ -50,14 +50,14 @@ </p> </div> <div class="refsect1" lang="en"> -<a name="id2543384"></a><h2>ACL</h2> +<a name="id2543385"></a><h2>ACL</h2> <div class="literallayout"><p><br> acl <em class="replaceable"><code>string</code></em> { <em class="replaceable"><code>address_match_element</code></em>; ... };<br> <br> </p></div> </div> <div class="refsect1" lang="en"> -<a name="id2543400"></a><h2>KEY</h2> +<a name="id2543401"></a><h2>KEY</h2> <div class="literallayout"><p><br> key <em class="replaceable"><code>domain_name</code></em> {<br> algorithm <em class="replaceable"><code>string</code></em>;<br> @@ -66,7 +66,7 @@ key <em class="replaceable"><code>domain_name</code></em> {<br> </p></div> </div> <div class="refsect1" lang="en"> -<a name="id2543419"></a><h2>MASTERS</h2> +<a name="id2543420"></a><h2>MASTERS</h2> <div class="literallayout"><p><br> masters <em class="replaceable"><code>string</code></em> [<span class="optional"> port <em class="replaceable"><code>integer</code></em> </span>] {<br> ( <em class="replaceable"><code>masters</code></em> | <em class="replaceable"><code>ipv4_address</code></em> [<span class="optional">port <em class="replaceable"><code>integer</code></em></span>] |<br> @@ -75,7 +75,7 @@ masters <em class="replaceable"><code>string</code></em> [<span class="optional" </p></div> </div> <div class="refsect1" lang="en"> -<a name="id2543465"></a><h2>SERVER</h2> +<a name="id2543466"></a><h2>SERVER</h2> <div class="literallayout"><p><br> server ( <em class="replaceable"><code>ipv4_address[<span class="optional">/prefixlen</span>]</code></em> | <em class="replaceable"><code>ipv6_address[<span class="optional">/prefixlen</span>]</code></em> ) {<br> bogus <em class="replaceable"><code>boolean</code></em>;<br> @@ -97,7 +97,7 @@ server ( <em class="replaceable"><code>ipv4_address[<span class="optional">/pref </p></div> </div> <div class="refsect1" lang="en"> -<a name="id2543533"></a><h2>TRUSTED-KEYS</h2> +<a name="id2543534"></a><h2>TRUSTED-KEYS</h2> <div class="literallayout"><p><br> trusted-keys {<br> <em class="replaceable"><code>domain_name</code></em> <em class="replaceable"><code>flags</code></em> <em class="replaceable"><code>protocol</code></em> <em class="replaceable"><code>algorithm</code></em> <em class="replaceable"><code>key</code></em>; ... <br> @@ -105,7 +105,7 @@ trusted-keys {<br> </p></div> </div> <div class="refsect1" lang="en"> -<a name="id2543559"></a><h2>MANAGED-KEYS</h2> +<a name="id2543560"></a><h2>MANAGED-KEYS</h2> <div class="literallayout"><p><br> managed-keys {<br> <em class="replaceable"><code>domain_name</code></em> <code class="constant">initial-key</code> <em class="replaceable"><code>flags</code></em> <em class="replaceable"><code>protocol</code></em> <em class="replaceable"><code>algorithm</code></em> <em class="replaceable"><code>key</code></em>; ... <br> @@ -113,7 +113,7 @@ managed-keys {<br> </p></div> </div> <div class="refsect1" lang="en"> -<a name="id2543588"></a><h2>CONTROLS</h2> +<a name="id2543589"></a><h2>CONTROLS</h2> <div class="literallayout"><p><br> controls {<br> inet ( <em class="replaceable"><code>ipv4_address</code></em> | <em class="replaceable"><code>ipv6_address</code></em> | * )<br> @@ -125,7 +125,7 @@ controls {<br> </p></div> </div> <div class="refsect1" lang="en"> -<a name="id2543623"></a><h2>LOGGING</h2> +<a name="id2543624"></a><h2>LOGGING</h2> <div class="literallayout"><p><br> logging {<br> channel <em class="replaceable"><code>string</code></em> {<br> @@ -143,7 +143,7 @@ logging {<br> </p></div> </div> <div class="refsect1" lang="en"> -<a name="id2543661"></a><h2>LWRES</h2> +<a name="id2543662"></a><h2>LWRES</h2> <div class="literallayout"><p><br> lwres {<br> listen-on [<span class="optional"> port <em class="replaceable"><code>integer</code></em> </span>] {<br> @@ -156,7 +156,7 @@ lwres {<br> </p></div> </div> <div class="refsect1" lang="en"> -<a name="id2543703"></a><h2>OPTIONS</h2> +<a name="id2543704"></a><h2>OPTIONS</h2> <div class="literallayout"><p><br> options {<br> avoid-v4-udp-ports { <em class="replaceable"><code>port</code></em>; ... };<br> @@ -291,7 +291,8 @@ options {<br> notify-delay <em class="replaceable"><code>seconds</code></em>;<br> notify-to-soa <em class="replaceable"><code>boolean</code></em>;<br> also-notify [<span class="optional"> port <em class="replaceable"><code>integer</code></em> </span>] { ( <em class="replaceable"><code>ipv4_address</code></em> | <em class="replaceable"><code>ipv6_address</code></em> )<br> - [<span class="optional"> port <em class="replaceable"><code>integer</code></em> </span>]; ... };<br> + [<span class="optional"> port <em class="replaceable"><code>integer</code></em> </span>]; ...<br> + [<span class="optional"> key <em class="replaceable"><code>keyname</code></em> </span>] ... };<br> allow-notify { <em class="replaceable"><code>address_match_element</code></em>; ... };<br> <br> forward ( first | only );<br> @@ -360,7 +361,7 @@ options {<br> </p></div> </div> <div class="refsect1" lang="en"> -<a name="id2544578"></a><h2>VIEW</h2> +<a name="id2544585"></a><h2>VIEW</h2> <div class="literallayout"><p><br> view <em class="replaceable"><code>string</code></em> <em class="replaceable"><code>optional_class</code></em> {<br> match-clients { <em class="replaceable"><code>address_match_element</code></em>; ... };<br> @@ -477,7 +478,8 @@ view <em class="replaceable"><code>string</code></em> <em class="replaceable"><c notify-delay <em class="replaceable"><code>seconds</code></em>;<br> notify-to-soa <em class="replaceable"><code>boolean</code></em>;<br> also-notify [<span class="optional"> port <em class="replaceable"><code>integer</code></em> </span>] { ( <em class="replaceable"><code>ipv4_address</code></em> | <em class="replaceable"><code>ipv6_address</code></em> )<br> - [<span class="optional"> port <em class="replaceable"><code>integer</code></em> </span>]; ... };<br> + [<span class="optional"> port <em class="replaceable"><code>integer</code></em> </span>]; ...<br> + [<span class="optional"> key <em class="replaceable"><code>keyname</code></em> </span>] ... };<br> allow-notify { <em class="replaceable"><code>address_match_element</code></em>; ... };<br> <br> forward ( first | only );<br> @@ -523,10 +525,10 @@ view <em class="replaceable"><code>string</code></em> <em class="replaceable"><c </p></div> </div> <div class="refsect1" lang="en"> -<a name="id2545287"></a><h2>ZONE</h2> +<a name="id2545301"></a><h2>ZONE</h2> <div class="literallayout"><p><br> zone <em class="replaceable"><code>string</code></em> <em class="replaceable"><code>optional_class</code></em> {<br> - type ( master | slave | stub | hint |<br> + type ( master | slave | stub | hint | redirect |<br> forward | delegation-only );<br> file <em class="replaceable"><code>quoted_string</code></em>;<br> <br> @@ -572,7 +574,8 @@ zone <em class="replaceable"><code>string</code></em> <em class="replaceable"><c notify-delay <em class="replaceable"><code>seconds</code></em>;<br> notify-to-soa <em class="replaceable"><code>boolean</code></em>;<br> also-notify [<span class="optional"> port <em class="replaceable"><code>integer</code></em> </span>] { ( <em class="replaceable"><code>ipv4_address</code></em> | <em class="replaceable"><code>ipv6_address</code></em> )<br> - [<span class="optional"> port <em class="replaceable"><code>integer</code></em> </span>]; ... };<br> + [<span class="optional"> port <em class="replaceable"><code>integer</code></em> </span>]; ...<br> + [<span class="optional"> key <em class="replaceable"><code>keyname</code></em> </span>] ... };<br> allow-notify { <em class="replaceable"><code>address_match_element</code></em>; ... };<br> <br> forward ( first | only );<br> @@ -590,6 +593,7 @@ zone <em class="replaceable"><code>string</code></em> <em class="replaceable"><c max-refresh-time <em class="replaceable"><code>integer</code></em>;<br> min-refresh-time <em class="replaceable"><code>integer</code></em>;<br> multi-master <em class="replaceable"><code>boolean</code></em>;<br> + request-ixfr <em class="replaceable"><code>boolean</code></em>;<br> sig-validity-interval <em class="replaceable"><code>integer</code></em>;<br> <br> transfer-source ( <em class="replaceable"><code>ipv4_address</code></em> | * )<br> @@ -618,12 +622,12 @@ zone <em class="replaceable"><code>string</code></em> <em class="replaceable"><c </p></div> </div> <div class="refsect1" lang="en"> -<a name="id2545667"></a><h2>FILES</h2> +<a name="id2545690"></a><h2>FILES</h2> <p><code class="filename">/etc/named.conf</code> </p> </div> <div class="refsect1" lang="en"> -<a name="id2545678"></a><h2>SEE ALSO</h2> +<a name="id2545702"></a><h2>SEE ALSO</h2> <p><span class="citerefentry"><span class="refentrytitle">named</span>(8)</span>, <span class="citerefentry"><span class="refentrytitle">named-checkconf</span>(8)</span>, <span class="citerefentry"><span class="refentrytitle">rndc</span>(8)</span>, diff --git a/contrib/bind9/bin/named/named.docbook b/contrib/bind9/bin/named/named.docbook index c748911e24a1..1f08e196e040 100644 --- a/contrib/bind9/bin/named/named.docbook +++ b/contrib/bind9/bin/named/named.docbook @@ -2,7 +2,7 @@ "http://www.oasis-open.org/docbook/xml/4.2/docbookx.dtd" [<!ENTITY mdash "—">]> <!-- - - Copyright (C) 2004-2009 Internet Systems Consortium, Inc. ("ISC") + - Copyright (C) 2004-2009, 2011, 2013 Internet Systems Consortium, Inc. ("ISC") - Copyright (C) 2000, 2001, 2003 Internet Software Consortium. - - Permission to use, copy, modify, and/or distribute this software for any @@ -18,7 +18,7 @@ - PERFORMANCE OF THIS SOFTWARE. --> -<!-- $Id: named.docbook,v 1.26 2009/10/05 17:30:49 fdupont Exp $ --> +<!-- $Id: named.docbook,v 1.28 2011/11/09 23:46:23 tbox Exp $ --> <refentry id="man.named"> <refentryinfo> <date>May 21, 2009</date> @@ -43,6 +43,8 @@ <year>2007</year> <year>2008</year> <year>2009</year> + <year>2011</year> + <year>2013</year> <holder>Internet Systems Consortium, Inc. ("ISC")</holder> </copyright> <copyright> @@ -69,6 +71,7 @@ <arg><option>-s</option></arg> <arg><option>-S <replaceable class="parameter">#max-socks</replaceable></option></arg> <arg><option>-t <replaceable class="parameter">directory</replaceable></option></arg> + <arg><option>-U <replaceable class="parameter">#listeners</replaceable></option></arg> <arg><option>-u <replaceable class="parameter">user</replaceable></option></arg> <arg><option>-v</option></arg> <arg><option>-V</option></arg> @@ -282,6 +285,21 @@ </varlistentry> <varlistentry> + <term>-U <replaceable class="parameter">#listeners</replaceable></term> + <listitem> + <para> + Use <replaceable class="parameter">#listeners</replaceable> + worker threads to listen for incoming UDP packets on each + address. If not specified, <command>named</command> will + use the number of detected CPUs. If <option>-n</option> + has been set to a higher value than the number of CPUs, + then <option>-U</option> may be increased as high as that + value, but no higher. + </para> + </listitem> + </varlistentry> + + <varlistentry> <term>-u <replaceable class="parameter">user</replaceable></term> <listitem> <para>Setuid diff --git a/contrib/bind9/bin/named/named.html b/contrib/bind9/bin/named/named.html index cf3cb2678f39..fc8de5147ad8 100644 --- a/contrib/bind9/bin/named/named.html +++ b/contrib/bind9/bin/named/named.html @@ -1,5 +1,5 @@ <!-- - - Copyright (C) 2004-2009 Internet Systems Consortium, Inc. ("ISC") + - Copyright (C) 2004-2009, 2011, 2013 Internet Systems Consortium, Inc. ("ISC") - Copyright (C) 2000, 2001, 2003 Internet Software Consortium. - - Permission to use, copy, modify, and/or distribute this software for any @@ -29,10 +29,10 @@ </div> <div class="refsynopsisdiv"> <h2>Synopsis</h2> -<div class="cmdsynopsis"><p><code class="command">named</code> [<code class="option">-4</code>] [<code class="option">-6</code>] [<code class="option">-c <em class="replaceable"><code>config-file</code></em></code>] [<code class="option">-d <em class="replaceable"><code>debug-level</code></em></code>] [<code class="option">-E <em class="replaceable"><code>engine-name</code></em></code>] [<code class="option">-f</code>] [<code class="option">-g</code>] [<code class="option">-m <em class="replaceable"><code>flag</code></em></code>] [<code class="option">-n <em class="replaceable"><code>#cpus</code></em></code>] [<code class="option">-p <em class="replaceable"><code>port</code></em></code>] [<code class="option">-s</code>] [<code class="option">-S <em class="replaceable"><code>#max-socks</code></em></code>] [<code class="option">-t <em class="replaceable"><code>directory</code></em></code>] [<code class="option">-u <em class="replaceable"><code>user</code></em></code>] [<code class="option">-v</code>] [<code class="option">-V</code>] [<code class="option">-x <em class="replaceable"><code>cache-file</code></em></code>]</p></div> +<div class="cmdsynopsis"><p><code class="command">named</code> [<code class="option">-4</code>] [<code class="option">-6</code>] [<code class="option">-c <em class="replaceable"><code>config-file</code></em></code>] [<code class="option">-d <em class="replaceable"><code>debug-level</code></em></code>] [<code class="option">-E <em class="replaceable"><code>engine-name</code></em></code>] [<code class="option">-f</code>] [<code class="option">-g</code>] [<code class="option">-m <em class="replaceable"><code>flag</code></em></code>] [<code class="option">-n <em class="replaceable"><code>#cpus</code></em></code>] [<code class="option">-p <em class="replaceable"><code>port</code></em></code>] [<code class="option">-s</code>] [<code class="option">-S <em class="replaceable"><code>#max-socks</code></em></code>] [<code class="option">-t <em class="replaceable"><code>directory</code></em></code>] [<code class="option">-U <em class="replaceable"><code>#listeners</code></em></code>] [<code class="option">-u <em class="replaceable"><code>user</code></em></code>] [<code class="option">-v</code>] [<code class="option">-V</code>] [<code class="option">-x <em class="replaceable"><code>cache-file</code></em></code>]</p></div> </div> <div class="refsect1" lang="en"> -<a name="id2543482"></a><h2>DESCRIPTION</h2> +<a name="id2543497"></a><h2>DESCRIPTION</h2> <p><span><strong class="command">named</strong></span> is a Domain Name System (DNS) server, part of the BIND 9 distribution from ISC. For more @@ -47,7 +47,7 @@ </p> </div> <div class="refsect1" lang="en"> -<a name="id2543507"></a><h2>OPTIONS</h2> +<a name="id2543522"></a><h2>OPTIONS</h2> <div class="variablelist"><dl> <dt><span class="term">-4</span></dt> <dd><p> @@ -178,6 +178,16 @@ </p> </div> </dd> +<dt><span class="term">-U <em class="replaceable"><code>#listeners</code></em></span></dt> +<dd><p> + Use <em class="replaceable"><code>#listeners</code></em> + worker threads to listen for incoming UDP packets on each + address. If not specified, <span><strong class="command">named</strong></span> will + use the number of detected CPUs. If <code class="option">-n</code> + has been set to a higher value than the number of CPUs, + then <code class="option">-U</code> may be increased as high as that + value, but no higher. + </p></dd> <dt><span class="term">-u <em class="replaceable"><code>user</code></em></span></dt> <dd> <p>Setuid @@ -228,7 +238,7 @@ </dl></div> </div> <div class="refsect1" lang="en"> -<a name="id2543964"></a><h2>SIGNALS</h2> +<a name="id2544012"></a><h2>SIGNALS</h2> <p> In routine operation, signals should not be used to control the nameserver; <span><strong class="command">rndc</strong></span> should be used @@ -249,7 +259,7 @@ </p> </div> <div class="refsect1" lang="en"> -<a name="id2544012"></a><h2>CONFIGURATION</h2> +<a name="id2544060"></a><h2>CONFIGURATION</h2> <p> The <span><strong class="command">named</strong></span> configuration file is too complex to describe in detail here. A complete description is provided @@ -266,7 +276,7 @@ </p> </div> <div class="refsect1" lang="en"> -<a name="id2544049"></a><h2>FILES</h2> +<a name="id2544233"></a><h2>FILES</h2> <div class="variablelist"><dl> <dt><span class="term"><code class="filename">/etc/named.conf</code></span></dt> <dd><p> @@ -279,7 +289,7 @@ </dl></div> </div> <div class="refsect1" lang="en"> -<a name="id2544088"></a><h2>SEE ALSO</h2> +<a name="id2544273"></a><h2>SEE ALSO</h2> <p><em class="citetitle">RFC 1033</em>, <em class="citetitle">RFC 1034</em>, <em class="citetitle">RFC 1035</em>, @@ -292,7 +302,7 @@ </p> </div> <div class="refsect1" lang="en"> -<a name="id2544295"></a><h2>AUTHOR</h2> +<a name="id2544343"></a><h2>AUTHOR</h2> <p><span class="corpauthor">Internet Systems Consortium</span> </p> </div> diff --git a/contrib/bind9/bin/named/query.c b/contrib/bind9/bin/named/query.c index 8c589841396b..5093cb243da4 100644 --- a/contrib/bind9/bin/named/query.c +++ b/contrib/bind9/bin/named/query.c @@ -15,7 +15,7 @@ * PERFORMANCE OF THIS SOFTWARE. */ -/* $Id: query.c,v 1.353.8.24 2012/02/07 01:14:39 marka Exp $ */ +/* $Id$ */ /*! \file */ @@ -172,39 +172,66 @@ rpz_st_clear(ns_client_t *client); static inline void inc_stats(ns_client_t *client, isc_statscounter_t counter) { dns_zone_t *zone = client->query.authzone; + isc_stats_t *zonestats; +#ifdef NEWSTATS + dns_rdatatype_t qtype; + dns_rdataset_t *rdataset; + dns_stats_t *querystats = NULL; +#endif isc_stats_increment(ns_g_server->nsstats, counter); - if (zone != NULL) { - isc_stats_t *zonestats = dns_zone_getrequeststats(zone); - if (zonestats != NULL) - isc_stats_increment(zonestats, counter); + if (zone == NULL) + return; + + /* Do regular response type stats */ + zonestats = dns_zone_getrequeststats(zone); + + if (zonestats != NULL) + isc_stats_increment(zonestats, counter); + +#ifdef NEWSTATS + /* Do query type statistics + * + * We only increment per-type if we're using the authoriative + * answer counter, preventing double-counting. + */ + if (counter == dns_nsstatscounter_authans) { + querystats = dns_zone_getrcvquerystats(zone); + if (querystats != NULL) { + rdataset = ISC_LIST_HEAD(client->query.qname->list); + if (rdataset != NULL) { + qtype = rdataset->type; + dns_rdatatypestats_increment(querystats, qtype); + } + } } +#endif } static void query_send(ns_client_t *client) { isc_statscounter_t counter; + if ((client->message->flags & DNS_MESSAGEFLAG_AA) == 0) inc_stats(client, dns_nsstatscounter_nonauthans); else inc_stats(client, dns_nsstatscounter_authans); + if (client->message->rcode == dns_rcode_noerror) { - if (ISC_LIST_EMPTY(client->message->sections[DNS_SECTION_ANSWER])) { - if (client->query.isreferral) { + dns_section_t answer = DNS_SECTION_ANSWER; + if (ISC_LIST_EMPTY(client->message->sections[answer])) { + if (client->query.isreferral) counter = dns_nsstatscounter_referral; - } else { + else counter = dns_nsstatscounter_nxrrset; - } - } else { + } else counter = dns_nsstatscounter_success; - } - } else if (client->message->rcode == dns_rcode_nxdomain) { + } else if (client->message->rcode == dns_rcode_nxdomain) counter = dns_nsstatscounter_nxdomain; - } else { - /* We end up here in case of YXDOMAIN, and maybe others */ + else /* We end up here in case of YXDOMAIN, and maybe others */ counter = dns_nsstatscounter_failure; - } + inc_stats(client, counter); ns_client_send(client); } @@ -1180,6 +1207,8 @@ query_addadditional(void *arg, dns_name_t *name, dns_rdatatype_t qtype) { isc_boolean_t added_something, need_addname; dns_zone_t *zone; dns_rdatatype_t type; + dns_clientinfomethods_t cm; + dns_clientinfo_t ci; REQUIRE(NS_CLIENT_VALID(client)); REQUIRE(qtype != dns_rdatatype_any); @@ -1204,6 +1233,9 @@ query_addadditional(void *arg, dns_name_t *name, dns_rdatatype_t qtype) { need_addname = ISC_FALSE; zone = NULL; + dns_clientinfomethods_init(&cm, ns_client_sourceip); + dns_clientinfo_init(&ci, client); + /* * We treat type A additional section processing as if it * were "any address type" additional section processing. @@ -1248,9 +1280,10 @@ query_addadditional(void *arg, dns_name_t *name, dns_rdatatype_t qtype) { * necessarily in the same database. */ node = NULL; - result = dns_db_find(db, name, version, type, client->query.dboptions, - client->now, &node, fname, rdataset, - sigrdataset); + result = dns_db_findext(db, name, version, type, + client->query.dboptions, + client->now, &node, fname, &cm, &ci, + rdataset, sigrdataset); if (result == ISC_R_SUCCESS) { if (sigrdataset != NULL && !dns_db_issecure(db) && dns_rdataset_isassociated(sigrdataset)) @@ -1286,11 +1319,11 @@ query_addadditional(void *arg, dns_name_t *name, dns_rdatatype_t qtype) { if (sigrdataset == NULL) goto cleanup; } - result = dns_db_find(db, name, version, type, - client->query.dboptions | - DNS_DBFIND_GLUEOK | DNS_DBFIND_ADDITIONALOK, - client->now, &node, fname, rdataset, - sigrdataset); + result = dns_db_findext(db, name, version, type, + client->query.dboptions | + DNS_DBFIND_GLUEOK | DNS_DBFIND_ADDITIONALOK, + client->now, &node, fname, &cm, &ci, + rdataset, sigrdataset); if (result == DNS_R_GLUE && validate(client, db, fname, rdataset, sigrdataset)) result = ISC_R_SUCCESS; @@ -1333,10 +1366,10 @@ query_addadditional(void *arg, dns_name_t *name, dns_rdatatype_t qtype) { goto cleanup; dns_db_attach(client->query.gluedb, &db); - result = dns_db_find(db, name, version, type, - client->query.dboptions | DNS_DBFIND_GLUEOK, - client->now, &node, fname, rdataset, - sigrdataset); + result = dns_db_findext(db, name, version, type, + client->query.dboptions | DNS_DBFIND_GLUEOK, + client->now, &node, fname, &cm, &ci, + rdataset, sigrdataset); if (!(result == ISC_R_SUCCESS || result == DNS_R_ZONECUT || result == DNS_R_GLUE)) @@ -1410,8 +1443,8 @@ query_addadditional(void *arg, dns_name_t *name, dns_rdatatype_t qtype) { goto aaaa_lookup; result = dns_db_findrdataset(db, node, version, dns_rdatatype_a, 0, - client->now, rdataset, - sigrdataset); + client->now, + rdataset, sigrdataset); if (result == DNS_R_NCACHENXDOMAIN) goto addname; if (result == DNS_R_NCACHENXRRSET) { @@ -1461,8 +1494,8 @@ query_addadditional(void *arg, dns_name_t *name, dns_rdatatype_t qtype) { goto addname; result = dns_db_findrdataset(db, node, version, dns_rdatatype_aaaa, 0, - client->now, rdataset, - sigrdataset); + client->now, + rdataset, sigrdataset); if (result == DNS_R_NCACHENXDOMAIN) goto addname; if (result == DNS_R_NCACHENXRRSET) { @@ -1636,6 +1669,8 @@ query_addadditional2(void *arg, dns_name_t *name, dns_rdatatype_t qtype) { dns_zone_t *zone; dns_rdatatype_t type; dns_rdatasetadditional_t additionaltype; + dns_clientinfomethods_t cm; + dns_clientinfo_t ci; /* * If we don't have an additional cache call query_addadditional. @@ -1674,6 +1709,8 @@ query_addadditional2(void *arg, dns_name_t *name, dns_rdatatype_t qtype) { POST(needadditionalcache); additionaltype = dns_rdatasetadditional_fromauth; dns_name_init(&cfname, NULL); + dns_clientinfomethods_init(&cm, ns_client_sourceip); + dns_clientinfo_init(&ci, client); CTRACE("query_addadditional2"); @@ -1776,8 +1813,10 @@ query_addadditional2(void *arg, dns_name_t *name, dns_rdatatype_t qtype) { * necessarily in the same database. */ node = NULL; - result = dns_db_find(db, name, version, type, client->query.dboptions, - client->now, &node, fname, NULL, NULL); + result = dns_db_findext(db, name, version, type, + client->query.dboptions, + client->now, &node, fname, &cm, &ci, + NULL, NULL); if (result == ISC_R_SUCCESS) goto found; @@ -1804,10 +1843,11 @@ query_addadditional2(void *arg, dns_name_t *name, dns_rdatatype_t qtype) { */ goto try_glue; - result = dns_db_find(db, name, version, type, - client->query.dboptions | - DNS_DBFIND_GLUEOK | DNS_DBFIND_ADDITIONALOK, - client->now, &node, fname, NULL, NULL); + result = dns_db_findext(db, name, version, type, + client->query.dboptions | + DNS_DBFIND_GLUEOK | DNS_DBFIND_ADDITIONALOK, + client->now, &node, fname, &cm, &ci, + NULL, NULL); if (result == ISC_R_SUCCESS) goto found; @@ -1876,9 +1916,10 @@ query_addadditional2(void *arg, dns_name_t *name, dns_rdatatype_t qtype) { findglue: dns_db_attach(client->query.gluedb, &db); - result = dns_db_find(db, name, version, type, - client->query.dboptions | DNS_DBFIND_GLUEOK, - client->now, &node, fname, NULL, NULL); + result = dns_db_findext(db, name, version, type, + client->query.dboptions | DNS_DBFIND_GLUEOK, + client->now, &node, fname, &cm, &ci, + NULL, NULL); if (!(result == ISC_R_SUCCESS || result == DNS_R_ZONECUT || result == DNS_R_GLUE)) { @@ -2528,6 +2569,8 @@ query_addsoa(ns_client_t *client, dns_db_t *db, dns_dbversion_t *version, isc_result_t result, eresult; dns_rdataset_t *rdataset = NULL, *sigrdataset = NULL; dns_rdataset_t **sigrdatasetp = NULL; + dns_clientinfomethods_t cm; + dns_clientinfo_t ci; CTRACE("query_addsoa"); /* @@ -2538,6 +2581,9 @@ query_addsoa(ns_client_t *client, dns_db_t *db, dns_dbversion_t *version, rdataset = NULL; node = NULL; + dns_clientinfomethods_init(&cm, ns_client_sourceip); + dns_clientinfo_init(&ci, client); + /* * Don't add the SOA record for test which set "-T nosoa". */ @@ -2571,9 +2617,8 @@ query_addsoa(ns_client_t *client, dns_db_t *db, dns_dbversion_t *version, result = dns_db_getoriginnode(db, &node); if (result == ISC_R_SUCCESS) { result = dns_db_findrdataset(db, node, version, - dns_rdatatype_soa, - 0, client->now, rdataset, - sigrdataset); + dns_rdatatype_soa, 0, client->now, + rdataset, sigrdataset); } else { dns_fixedname_t foundname; dns_name_t *fname; @@ -2581,9 +2626,9 @@ query_addsoa(ns_client_t *client, dns_db_t *db, dns_dbversion_t *version, dns_fixedname_init(&foundname); fname = dns_fixedname_name(&foundname); - result = dns_db_find(db, name, version, dns_rdatatype_soa, - client->query.dboptions, 0, &node, - fname, rdataset, sigrdataset); + result = dns_db_findext(db, name, version, dns_rdatatype_soa, + client->query.dboptions, 0, &node, + fname, &cm, &ci, rdataset, sigrdataset); } if (result != ISC_R_SUCCESS) { /* @@ -2648,6 +2693,8 @@ query_addns(ns_client_t *client, dns_db_t *db, dns_dbversion_t *version) { dns_fixedname_t foundname; dns_rdataset_t *rdataset = NULL, *sigrdataset = NULL; dns_rdataset_t **sigrdatasetp = NULL; + dns_clientinfomethods_t cm; + dns_clientinfo_t ci; CTRACE("query_addns"); /* @@ -2659,6 +2706,8 @@ query_addns(ns_client_t *client, dns_db_t *db, dns_dbversion_t *version) { node = NULL; dns_fixedname_init(&foundname); fname = dns_fixedname_name(&foundname); + dns_clientinfomethods_init(&cm, ns_client_sourceip); + dns_clientinfo_init(&ci, client); /* * Get resources and make 'name' be the database origin. @@ -2691,14 +2740,13 @@ query_addns(ns_client_t *client, dns_db_t *db, dns_dbversion_t *version) { result = dns_db_getoriginnode(db, &node); if (result == ISC_R_SUCCESS) { result = dns_db_findrdataset(db, node, version, - dns_rdatatype_ns, - 0, client->now, rdataset, - sigrdataset); + dns_rdatatype_ns, 0, client->now, + rdataset, sigrdataset); } else { CTRACE("query_addns: calling dns_db_find"); - result = dns_db_find(db, name, NULL, dns_rdatatype_ns, - client->query.dboptions, 0, &node, - fname, rdataset, sigrdataset); + result = dns_db_findext(db, name, NULL, dns_rdatatype_ns, + client->query.dboptions, 0, &node, + fname, &cm, &ci, rdataset, sigrdataset); CTRACE("query_addns: dns_db_find complete"); } if (result != ISC_R_SUCCESS) { @@ -2820,15 +2868,19 @@ mark_secure(ns_client_t *client, dns_db_t *db, dns_name_t *name, { isc_result_t result; dns_dbnode_t *node = NULL; + dns_clientinfomethods_t cm; + dns_clientinfo_t ci; isc_stdtime_t now; rdataset->trust = dns_trust_secure; sigrdataset->trust = dns_trust_secure; + dns_clientinfomethods_init(&cm, ns_client_sourceip); + dns_clientinfo_init(&ci, client); /* * Save the updated secure state. Ignore failures. */ - result = dns_db_findnode(db, name, ISC_TRUE, &node); + result = dns_db_findnodeext(db, name, ISC_TRUE, &cm, &ci, &node); if (result != ISC_R_SUCCESS) return; @@ -2856,9 +2908,15 @@ get_key(ns_client_t *client, dns_db_t *db, dns_rdata_rrsig_t *rrsig, isc_result_t result; dns_dbnode_t *node = NULL; isc_boolean_t secure = ISC_FALSE; + dns_clientinfomethods_t cm; + dns_clientinfo_t ci; + + dns_clientinfomethods_init(&cm, ns_client_sourceip); + dns_clientinfo_init(&ci, client); if (!dns_rdataset_isassociated(keyrdataset)) { - result = dns_db_findnode(db, &rrsig->signer, ISC_FALSE, &node); + result = dns_db_findnodeext(db, &rrsig->signer, ISC_FALSE, + &cm, &ci, &node); if (result != ISC_R_SUCCESS) return (ISC_FALSE); @@ -2901,7 +2959,7 @@ get_key(ns_client_t *client, dns_db_t *db, dns_rdata_rrsig_t *rrsig, static isc_boolean_t verify(dst_key_t *key, dns_name_t *name, dns_rdataset_t *rdataset, - dns_rdata_t *rdata, isc_mem_t *mctx, isc_boolean_t acceptexpired) + dns_rdata_t *rdata, ns_client_t *client) { isc_result_t result; dns_fixedname_t fixed; @@ -2910,9 +2968,10 @@ verify(dst_key_t *key, dns_name_t *name, dns_rdataset_t *rdataset, dns_fixedname_init(&fixed); again: - result = dns_dnssec_verify2(name, rdataset, key, ignore, mctx, + result = dns_dnssec_verify3(name, rdataset, key, ignore, + client->view->maxbits, client->mctx, rdata, NULL); - if (result == DNS_R_SIGEXPIRED && acceptexpired) { + if (result == DNS_R_SIGEXPIRED && client->view->acceptexpired) { ignore = ISC_TRUE; goto again; } @@ -2955,8 +3014,7 @@ validate(ns_client_t *client, dns_db_t *db, dns_name_t *name, do { if (!get_key(client, db, &rrsig, &keyrdataset, &key)) break; - if (verify(key, name, rdataset, &rdata, client->mctx, - client->view->acceptexpired)) { + if (verify(key, name, rdataset, &rdata, client)) { dst_key_free(&key); dns_rdataset_disassociate(&keyrdataset); mark_secure(client, db, name, &rrsig, @@ -2983,6 +3041,8 @@ query_addbestns(ns_client_t *client) { dns_dbversion_t *version; dns_zone_t *zone; isc_buffer_t b; + dns_clientinfomethods_t cm; + dns_clientinfo_t ci; CTRACE("query_addbestns"); fname = NULL; @@ -2999,6 +3059,9 @@ query_addbestns(ns_client_t *client) { is_zone = ISC_FALSE; use_zone = ISC_FALSE; + dns_clientinfomethods_init(&cm, ns_client_sourceip); + dns_clientinfo_init(&ci, client); + /* * Find the right database. */ @@ -3032,10 +3095,11 @@ query_addbestns(ns_client_t *client) { * Now look for the zonecut. */ if (is_zone) { - result = dns_db_find(db, client->query.qname, version, - dns_rdatatype_ns, client->query.dboptions, - client->now, &node, fname, - rdataset, sigrdataset); + result = dns_db_findext(db, client->query.qname, version, + dns_rdatatype_ns, + client->query.dboptions, + client->now, &node, fname, + &cm, &ci, rdataset, sigrdataset); if (result != DNS_R_DELEGATION) goto cleanup; if (USECACHE(client)) { @@ -3312,6 +3376,8 @@ query_addwildcardproof(ns_client_t *client, dns_db_t *db, int order; dns_fixedname_t cfixed; dns_name_t *cname; + dns_clientinfomethods_t cm; + dns_clientinfo_t ci; CTRACE("query_addwildcardproof"); fname = NULL; @@ -3319,6 +3385,9 @@ query_addwildcardproof(ns_client_t *client, dns_db_t *db, sigrdataset = NULL; node = NULL; + dns_clientinfomethods_init(&cm, ns_client_sourceip); + dns_clientinfo_init(&ci, client); + /* * Get the NOQNAME proof then if !ispositive * get the NOWILDCARD proof. @@ -3378,8 +3447,9 @@ query_addwildcardproof(ns_client_t *client, dns_db_t *db, if (fname == NULL || rdataset == NULL || sigrdataset == NULL) goto cleanup; - result = dns_db_find(db, name, version, dns_rdatatype_nsec, options, - 0, &node, fname, rdataset, sigrdataset); + result = dns_db_findext(db, name, version, dns_rdatatype_nsec, + options, 0, &node, fname, &cm, &ci, + rdataset, sigrdataset); if (node != NULL) dns_db_detachnode(db, &node); @@ -3401,10 +3471,10 @@ query_addwildcardproof(ns_client_t *client, dns_db_t *db, if (labels == 0U) goto cleanup; dns_name_split(cname, labels, NULL, cname); - result = dns_db_find(db, cname, version, - dns_rdatatype_nsec, - options, 0, NULL, fname, - NULL, NULL); + result = dns_db_findext(db, cname, version, + dns_rdatatype_nsec, + options, 0, NULL, fname, + &cm, &ci, NULL, NULL); } /* * Add closest (provable) encloser NSEC3. @@ -3904,6 +3974,11 @@ rpz_rrset_find(ns_client_t *client, dns_rpz_type_t rpz_type, dns_fixedname_t fixed; dns_name_t *found; isc_result_t result; + dns_clientinfomethods_t cm; + dns_clientinfo_t ci; + + dns_clientinfomethods_init(&cm, ns_client_sourceip); + dns_clientinfo_init(&ci, client); st = client->query.rpz_st; if ((st->state & DNS_RPZ_RECURSING) != 0) { @@ -3959,8 +4034,9 @@ rpz_rrset_find(ns_client_t *client, dns_rpz_type_t rpz_type, node = NULL; dns_fixedname_init(&fixed); found = dns_fixedname_name(&fixed); - result = dns_db_find(*dbp, name, version, type, DNS_DBFIND_GLUEOK, - client->now, &node, found, *rdatasetp, NULL); + result = dns_db_findext(*dbp, name, version, type, DNS_DBFIND_GLUEOK, + client->now, &node, found, + &cm, &ci, *rdatasetp, NULL); if (result == DNS_R_DELEGATION && is_zone && USECACHE(client)) { /* * Try the cache if we're authoritative for an @@ -3969,9 +4045,9 @@ rpz_rrset_find(ns_client_t *client, dns_rpz_type_t rpz_type, rpz_clean(NULL, dbp, &node, rdatasetp); version = NULL; dns_db_attach(client->view->cachedb, dbp); - result = dns_db_find(*dbp, name, version, dns_rdatatype_ns, - 0, client->now, &node, found, - *rdatasetp, NULL); + result = dns_db_findext(*dbp, name, version, dns_rdatatype_ns, + 0, client->now, &node, found, + &cm, &ci, *rdatasetp, NULL); } rpz_clean(NULL, dbp, &node, NULL); if (result == DNS_R_DELEGATION) { @@ -4169,9 +4245,14 @@ rpz_find(ns_client_t *client, dns_rdatatype_t qtype, dns_name_t *qnamef, dns_fixedname_t fixed; dns_name_t *found; isc_result_t result; + dns_clientinfomethods_t cm; + dns_clientinfo_t ci; REQUIRE(nodep != NULL); + dns_clientinfomethods_init(&cm, ns_client_sourceip); + dns_clientinfo_init(&ci, client); + result = rpz_ready(client, zonep, dbp, nodep, rdatasetp); if (result != ISC_R_SUCCESS) { *policyp = DNS_RPZ_POLICY_ERROR; @@ -4191,8 +4272,9 @@ rpz_find(ns_client_t *client, dns_rdatatype_t qtype, dns_name_t *qnamef, dns_fixedname_init(&fixed); found = dns_fixedname_name(&fixed); - result = dns_db_find(*dbp, qnamef, *versionp, dns_rdatatype_any, 0, - client->now, nodep, found, *rdatasetp, NULL); + result = dns_db_findext(*dbp, qnamef, *versionp, dns_rdatatype_any, 0, + client->now, nodep, found, &cm, &ci, + *rdatasetp, NULL); if (result == ISC_R_SUCCESS) { dns_rdatasetiter_t *rdsiter; @@ -4236,10 +4318,10 @@ rpz_find(ns_client_t *client, dns_rdatatype_t qtype, dns_name_t *qnamef, qtype == dns_rdatatype_sig) result = DNS_R_NXRRSET; else - result = dns_db_find(*dbp, qnamef, *versionp, - qtype, 0, client->now, - nodep, found, *rdatasetp, - NULL); + result = dns_db_findext(*dbp, qnamef, *versionp, + qtype, 0, client->now, + nodep, found, &cm, &ci, + *rdatasetp, NULL); } } switch (result) { @@ -5183,6 +5265,8 @@ query_findclosestnsec3(dns_name_t *qname, dns_db_t *db, dns_rdata_nsec3_t nsec3; dns_rdata_t rdata = DNS_RDATA_INIT; isc_boolean_t optout; + dns_clientinfomethods_t cm; + dns_clientinfo_t ci; salt_length = sizeof(salt); result = dns_db_getnsec3parameters(db, version, &hash, NULL, @@ -5192,6 +5276,8 @@ query_findclosestnsec3(dns_name_t *qname, dns_db_t *db, dns_name_init(&name, NULL); dns_name_clone(qname, &name); + dns_clientinfomethods_init(&cm, ns_client_sourceip); + dns_clientinfo_init(&ci, client); /* * Map unknown algorithm to known value. @@ -5208,9 +5294,9 @@ query_findclosestnsec3(dns_name_t *qname, dns_db_t *db, return; dboptions = client->query.dboptions | DNS_DBFIND_FORCENSEC3; - result = dns_db_find(db, dns_fixedname_name(&fixed), version, - dns_rdatatype_nsec3, dboptions, client->now, - NULL, fname, rdataset, sigrdataset); + result = dns_db_findext(db, dns_fixedname_name(&fixed), version, + dns_rdatatype_nsec3, dboptions, client->now, + NULL, fname, &cm, &ci, rdataset, sigrdataset); if (result == DNS_R_NXDOMAIN) { if (!dns_rdataset_isassociated(rdataset)) { @@ -5350,6 +5436,121 @@ dns64_aaaaok(ns_client_t *client, dns_rdataset_t *rdataset, } /* + * Look for the name and type in the redirection zone. If found update + * the arguments as appropriate. Return ISC_TRUE if a update was + * performed. + * + * Only perform the update if the client is in the allow query acl and + * returning the update would not cause a DNSSEC validation failure. + */ +static isc_boolean_t +redirect(ns_client_t *client, dns_name_t *name, dns_rdataset_t *rdataset, + dns_dbnode_t **nodep, dns_db_t **dbp, dns_dbversion_t **versionp, + dns_rdatatype_t qtype) +{ + dns_db_t *db = NULL; + dns_dbnode_t *node = NULL; + dns_fixedname_t fixed; + dns_name_t *found; + dns_rdataset_t trdataset; + isc_result_t result; + dns_rdatatype_t type; + dns_clientinfomethods_t cm; + dns_clientinfo_t ci; + ns_dbversion_t *dbversion; + + CTRACE("redirect"); + + if (client->view->redirect == NULL) + return (ISC_FALSE); + + dns_fixedname_init(&fixed); + found = dns_fixedname_name(&fixed); + dns_rdataset_init(&trdataset); + + dns_clientinfomethods_init(&cm, ns_client_sourceip); + dns_clientinfo_init(&ci, client); + + if (WANTDNSSEC(client) && dns_db_iszone(*dbp) && dns_db_issecure(*dbp)) + return (ISC_FALSE); + + if (WANTDNSSEC(client) && dns_rdataset_isassociated(rdataset)) { + if (rdataset->trust == dns_trust_secure) + return (ISC_FALSE); + if (rdataset->trust == dns_trust_ultimate && + (rdataset->type == dns_rdatatype_nsec || + rdataset->type == dns_rdatatype_nsec3)) + return (ISC_FALSE); + if ((rdataset->attributes & DNS_RDATASETATTR_NEGATIVE) != 0) { + for (result = dns_rdataset_first(rdataset); + result == ISC_R_SUCCESS; + result = dns_rdataset_next(rdataset)) { + dns_ncache_current(rdataset, found, &trdataset); + type = trdataset.type; + dns_rdataset_disassociate(&trdataset); + if (type == dns_rdatatype_nsec || + type == dns_rdatatype_nsec3 || + type == dns_rdatatype_rrsig) + return (ISC_FALSE); + } + } + } + + result = ns_client_checkaclsilent(client, NULL, + dns_zone_getqueryacl(client->view->redirect), + ISC_TRUE); + if (result != ISC_R_SUCCESS) + return (ISC_FALSE); + + result = dns_zone_getdb(client->view->redirect, &db); + if (result != ISC_R_SUCCESS) + return (ISC_FALSE); + + dbversion = query_findversion(client, db); + if (dbversion == NULL) { + dns_db_detach(&db); + return (ISC_FALSE); + } + + /* + * Lookup the requested data in the redirect zone. + */ + result = dns_db_findext(db, client->query.qname, dbversion->version, + qtype, 0, client->now, &node, found, &cm, &ci, + &trdataset, NULL); + if (result != ISC_R_SUCCESS) { + if (dns_rdataset_isassociated(&trdataset)) + dns_rdataset_disassociate(&trdataset); + if (node != NULL) + dns_db_detachnode(db, &node); + dns_db_detach(&db); + return (ISC_FALSE); + } + CTRACE("redirect: found data: done"); + + dns_name_copy(found, name, NULL); + if (dns_rdataset_isassociated(rdataset)) + dns_rdataset_disassociate(rdataset); + if (dns_rdataset_isassociated(&trdataset)) { + dns_rdataset_clone(&trdataset, rdataset); + dns_rdataset_disassociate(&trdataset); + } + if (*nodep != NULL) + dns_db_detachnode(*dbp, nodep); + dns_db_detach(dbp); + dns_db_attachnode(db, node, nodep); + dns_db_attach(db, dbp); + dns_db_detachnode(db, &node); + dns_db_detach(&db); + *versionp = dbversion->version; + + client->query.attributes |= (NS_QUERYATTR_NOAUTHORITY | + NS_QUERYATTR_NOADDITIONAL); + + return (ISC_TRUE); +} + +/* * Do the bulk of query processing for the current query of 'client'. * If 'event' is non-NULL, we are returning from recursion and 'qtype' * is ignored. Otherwise, 'qtype' is the query type. @@ -5387,6 +5588,8 @@ query_find(ns_client_t *client, dns_fetchevent_t *event, dns_rdatatype_t qtype) isc_boolean_t resuming; int line = -1; isc_boolean_t dns64_exclude, dns64; + dns_clientinfomethods_t cm; + dns_clientinfo_t ci; CTRACE("query_find"); @@ -5418,6 +5621,9 @@ query_find(ns_client_t *client, dns_fetchevent_t *event, dns_rdatatype_t qtype) is_zone = ISC_FALSE; is_staticstub_zone = ISC_FALSE; + dns_clientinfomethods_init(&cm, ns_client_sourceip); + dns_clientinfo_init(&ci, client); + if (event != NULL) { /* * We're returning from recursion. Restore the query context @@ -5652,9 +5858,9 @@ query_find(ns_client_t *client, dns_fetchevent_t *event, dns_rdatatype_t qtype) /* * Now look for an answer in the database. */ - result = dns_db_find(db, client->query.qname, version, type, - client->query.dboptions, client->now, - &node, fname, rdataset, sigrdataset); + result = dns_db_findext(db, client->query.qname, version, type, + client->query.dboptions, client->now, + &node, fname, &cm, &ci, rdataset, sigrdataset); resume: CTRACE("query_find: resume"); @@ -5828,10 +6034,11 @@ query_find(ns_client_t *client, dns_fetchevent_t *event, dns_rdatatype_t qtype) result = ISC_R_FAILURE; } else { dns_db_attach(client->view->hints, &db); - result = dns_db_find(db, dns_rootname, - NULL, dns_rdatatype_ns, - 0, client->now, &node, fname, - rdataset, sigrdataset); + result = dns_db_findext(db, dns_rootname, + NULL, dns_rdatatype_ns, + 0, client->now, &node, + fname, &cm, &ci, + rdataset, sigrdataset); } if (result != ISC_R_SUCCESS) { /* @@ -6301,6 +6508,10 @@ query_find(ns_client_t *client, dns_fetchevent_t *event, dns_rdatatype_t qtype) case DNS_R_NXDOMAIN: INSIST(is_zone); + if (!empty_wild && + redirect(client, fname, rdataset, &node, &db, &version, + type)) + break; if (dns_rdataset_isassociated(rdataset)) { /* * If we've got a NSEC record, we need to save the @@ -6360,6 +6571,9 @@ query_find(ns_client_t *client, dns_fetchevent_t *event, dns_rdatatype_t qtype) goto cleanup; case DNS_R_NCACHENXDOMAIN: + if (redirect(client, fname, rdataset, &node, &db, &version, + type)) + break; case DNS_R_NCACHENXRRSET: ncache_nxrrset: INSIST(!is_zone); @@ -6862,9 +7076,9 @@ query_find(ns_client_t *client, dns_fetchevent_t *event, dns_rdatatype_t qtype) if (qtype == dns_rdatatype_aaaa) { trdataset = query_newrdataset(client); result = dns_db_findrdataset(db, node, version, - dns_rdatatype_a, 0, - client->now, - trdataset, NULL); + dns_rdatatype_a, 0, + client->now, + trdataset, NULL); if (dns_rdataset_isassociated(trdataset)) dns_rdataset_disassociate(trdataset); query_putrdataset(client, &trdataset); @@ -7340,6 +7554,7 @@ ns_query_start(ns_client_t *client) { INSIST(rdataset != NULL); qtype = rdataset->type; dns_rdatatypestats_increment(ns_g_server->rcvquerystats, qtype); + if (dns_rdatatype_ismeta(qtype)) { switch (qtype) { case dns_rdatatype_any: diff --git a/contrib/bind9/bin/named/server.c b/contrib/bind9/bin/named/server.c index 05c68b992ec4..aef922bb73bc 100644 --- a/contrib/bind9/bin/named/server.c +++ b/contrib/bind9/bin/named/server.c @@ -15,7 +15,7 @@ * PERFORMANCE OF THIS SOFTWARE. */ -/* $Id: server.c,v 1.599.8.19 2012/02/22 00:33:32 each Exp $ */ +/* $Id$ */ /*! \file */ @@ -34,11 +34,13 @@ #include <isc/entropy.h> #include <isc/file.h> #include <isc/hash.h> +#include <isc/hex.h> #include <isc/httpd.h> #include <isc/lex.h> #include <isc/parseint.h> #include <isc/portset.h> #include <isc/print.h> +#include <isc/refcount.h> #include <isc/resource.h> #include <isc/sha2.h> #include <isc/socket.h> @@ -72,6 +74,7 @@ #include <dns/order.h> #include <dns/peer.h> #include <dns/portlist.h> +#include <dns/private.h> #include <dns/rbt.h> #include <dns/rdataclass.h> #include <dns/rdataset.h> @@ -112,6 +115,10 @@ #define PATH_MAX 1024 #endif +#ifndef SIZE_MAX +#define SIZE_MAX ((size_t)-1) +#endif + /*% * Check an operation for failure. Assumes that the function * using it has a 'result' variable and a 'cleanup' label. @@ -215,122 +222,129 @@ struct cfg_context { cfg_aclconfctx_t * actx; }; +/*% + * Holds state information for the initial zone loading process. + * Uses the isc_refcount structure to count the number of views + * with pending zone loads, dereferencing as each view finishes. + */ +typedef struct { + ns_server_t *server; + isc_refcount_t refs; +} ns_zoneload_t; + /* * These zones should not leak onto the Internet. */ -static const struct { - const char *zone; - isc_boolean_t rfc1918; -} empty_zones[] = { +const char *empty_zones[] = { /* RFC 1918 */ - { "10.IN-ADDR.ARPA", ISC_TRUE }, - { "16.172.IN-ADDR.ARPA", ISC_TRUE }, - { "17.172.IN-ADDR.ARPA", ISC_TRUE }, - { "18.172.IN-ADDR.ARPA", ISC_TRUE }, - { "19.172.IN-ADDR.ARPA", ISC_TRUE }, - { "20.172.IN-ADDR.ARPA", ISC_TRUE }, - { "21.172.IN-ADDR.ARPA", ISC_TRUE }, - { "22.172.IN-ADDR.ARPA", ISC_TRUE }, - { "23.172.IN-ADDR.ARPA", ISC_TRUE }, - { "24.172.IN-ADDR.ARPA", ISC_TRUE }, - { "25.172.IN-ADDR.ARPA", ISC_TRUE }, - { "26.172.IN-ADDR.ARPA", ISC_TRUE }, - { "27.172.IN-ADDR.ARPA", ISC_TRUE }, - { "28.172.IN-ADDR.ARPA", ISC_TRUE }, - { "29.172.IN-ADDR.ARPA", ISC_TRUE }, - { "30.172.IN-ADDR.ARPA", ISC_TRUE }, - { "31.172.IN-ADDR.ARPA", ISC_TRUE }, - { "168.192.IN-ADDR.ARPA", ISC_TRUE }, + "10.IN-ADDR.ARPA", + "16.172.IN-ADDR.ARPA", + "17.172.IN-ADDR.ARPA", + "18.172.IN-ADDR.ARPA", + "19.172.IN-ADDR.ARPA", + "20.172.IN-ADDR.ARPA", + "21.172.IN-ADDR.ARPA", + "22.172.IN-ADDR.ARPA", + "23.172.IN-ADDR.ARPA", + "24.172.IN-ADDR.ARPA", + "25.172.IN-ADDR.ARPA", + "26.172.IN-ADDR.ARPA", + "27.172.IN-ADDR.ARPA", + "28.172.IN-ADDR.ARPA", + "29.172.IN-ADDR.ARPA", + "30.172.IN-ADDR.ARPA", + "31.172.IN-ADDR.ARPA", + "168.192.IN-ADDR.ARPA", /* RFC 6598 */ - { "64.100.IN-ADDR.ARPA", ISC_FALSE }, - { "65.100.IN-ADDR.ARPA", ISC_FALSE }, - { "66.100.IN-ADDR.ARPA", ISC_FALSE }, - { "67.100.IN-ADDR.ARPA", ISC_FALSE }, - { "68.100.IN-ADDR.ARPA", ISC_FALSE }, - { "69.100.IN-ADDR.ARPA", ISC_FALSE }, - { "70.100.IN-ADDR.ARPA", ISC_FALSE }, - { "71.100.IN-ADDR.ARPA", ISC_FALSE }, - { "72.100.IN-ADDR.ARPA", ISC_FALSE }, - { "73.100.IN-ADDR.ARPA", ISC_FALSE }, - { "74.100.IN-ADDR.ARPA", ISC_FALSE }, - { "75.100.IN-ADDR.ARPA", ISC_FALSE }, - { "76.100.IN-ADDR.ARPA", ISC_FALSE }, - { "77.100.IN-ADDR.ARPA", ISC_FALSE }, - { "78.100.IN-ADDR.ARPA", ISC_FALSE }, - { "79.100.IN-ADDR.ARPA", ISC_FALSE }, - { "80.100.IN-ADDR.ARPA", ISC_FALSE }, - { "81.100.IN-ADDR.ARPA", ISC_FALSE }, - { "82.100.IN-ADDR.ARPA", ISC_FALSE }, - { "83.100.IN-ADDR.ARPA", ISC_FALSE }, - { "84.100.IN-ADDR.ARPA", ISC_FALSE }, - { "85.100.IN-ADDR.ARPA", ISC_FALSE }, - { "86.100.IN-ADDR.ARPA", ISC_FALSE }, - { "87.100.IN-ADDR.ARPA", ISC_FALSE }, - { "88.100.IN-ADDR.ARPA", ISC_FALSE }, - { "89.100.IN-ADDR.ARPA", ISC_FALSE }, - { "90.100.IN-ADDR.ARPA", ISC_FALSE }, - { "91.100.IN-ADDR.ARPA", ISC_FALSE }, - { "92.100.IN-ADDR.ARPA", ISC_FALSE }, - { "93.100.IN-ADDR.ARPA", ISC_FALSE }, - { "94.100.IN-ADDR.ARPA", ISC_FALSE }, - { "95.100.IN-ADDR.ARPA", ISC_FALSE }, - { "96.100.IN-ADDR.ARPA", ISC_FALSE }, - { "97.100.IN-ADDR.ARPA", ISC_FALSE }, - { "98.100.IN-ADDR.ARPA", ISC_FALSE }, - { "99.100.IN-ADDR.ARPA", ISC_FALSE }, - { "100.100.IN-ADDR.ARPA", ISC_FALSE }, - { "101.100.IN-ADDR.ARPA", ISC_FALSE }, - { "102.100.IN-ADDR.ARPA", ISC_FALSE }, - { "103.100.IN-ADDR.ARPA", ISC_FALSE }, - { "104.100.IN-ADDR.ARPA", ISC_FALSE }, - { "105.100.IN-ADDR.ARPA", ISC_FALSE }, - { "106.100.IN-ADDR.ARPA", ISC_FALSE }, - { "107.100.IN-ADDR.ARPA", ISC_FALSE }, - { "108.100.IN-ADDR.ARPA", ISC_FALSE }, - { "109.100.IN-ADDR.ARPA", ISC_FALSE }, - { "110.100.IN-ADDR.ARPA", ISC_FALSE }, - { "111.100.IN-ADDR.ARPA", ISC_FALSE }, - { "112.100.IN-ADDR.ARPA", ISC_FALSE }, - { "113.100.IN-ADDR.ARPA", ISC_FALSE }, - { "114.100.IN-ADDR.ARPA", ISC_FALSE }, - { "115.100.IN-ADDR.ARPA", ISC_FALSE }, - { "116.100.IN-ADDR.ARPA", ISC_FALSE }, - { "117.100.IN-ADDR.ARPA", ISC_FALSE }, - { "118.100.IN-ADDR.ARPA", ISC_FALSE }, - { "119.100.IN-ADDR.ARPA", ISC_FALSE }, - { "120.100.IN-ADDR.ARPA", ISC_FALSE }, - { "121.100.IN-ADDR.ARPA", ISC_FALSE }, - { "122.100.IN-ADDR.ARPA", ISC_FALSE }, - { "123.100.IN-ADDR.ARPA", ISC_FALSE }, - { "124.100.IN-ADDR.ARPA", ISC_FALSE }, - { "125.100.IN-ADDR.ARPA", ISC_FALSE }, - { "126.100.IN-ADDR.ARPA", ISC_FALSE }, - { "127.100.IN-ADDR.ARPA", ISC_FALSE }, + "64.100.IN-ADDR.ARPA", + "65.100.IN-ADDR.ARPA", + "66.100.IN-ADDR.ARPA", + "67.100.IN-ADDR.ARPA", + "68.100.IN-ADDR.ARPA", + "69.100.IN-ADDR.ARPA", + "70.100.IN-ADDR.ARPA", + "71.100.IN-ADDR.ARPA", + "72.100.IN-ADDR.ARPA", + "73.100.IN-ADDR.ARPA", + "74.100.IN-ADDR.ARPA", + "75.100.IN-ADDR.ARPA", + "76.100.IN-ADDR.ARPA", + "77.100.IN-ADDR.ARPA", + "78.100.IN-ADDR.ARPA", + "79.100.IN-ADDR.ARPA", + "80.100.IN-ADDR.ARPA", + "81.100.IN-ADDR.ARPA", + "82.100.IN-ADDR.ARPA", + "83.100.IN-ADDR.ARPA", + "84.100.IN-ADDR.ARPA", + "85.100.IN-ADDR.ARPA", + "86.100.IN-ADDR.ARPA", + "87.100.IN-ADDR.ARPA", + "88.100.IN-ADDR.ARPA", + "89.100.IN-ADDR.ARPA", + "90.100.IN-ADDR.ARPA", + "91.100.IN-ADDR.ARPA", + "92.100.IN-ADDR.ARPA", + "93.100.IN-ADDR.ARPA", + "94.100.IN-ADDR.ARPA", + "95.100.IN-ADDR.ARPA", + "96.100.IN-ADDR.ARPA", + "97.100.IN-ADDR.ARPA", + "98.100.IN-ADDR.ARPA", + "99.100.IN-ADDR.ARPA", + "100.100.IN-ADDR.ARPA", + "101.100.IN-ADDR.ARPA", + "102.100.IN-ADDR.ARPA", + "103.100.IN-ADDR.ARPA", + "104.100.IN-ADDR.ARPA", + "105.100.IN-ADDR.ARPA", + "106.100.IN-ADDR.ARPA", + "107.100.IN-ADDR.ARPA", + "108.100.IN-ADDR.ARPA", + "109.100.IN-ADDR.ARPA", + "110.100.IN-ADDR.ARPA", + "111.100.IN-ADDR.ARPA", + "112.100.IN-ADDR.ARPA", + "113.100.IN-ADDR.ARPA", + "114.100.IN-ADDR.ARPA", + "115.100.IN-ADDR.ARPA", + "116.100.IN-ADDR.ARPA", + "117.100.IN-ADDR.ARPA", + "118.100.IN-ADDR.ARPA", + "119.100.IN-ADDR.ARPA", + "120.100.IN-ADDR.ARPA", + "121.100.IN-ADDR.ARPA", + "122.100.IN-ADDR.ARPA", + "123.100.IN-ADDR.ARPA", + "124.100.IN-ADDR.ARPA", + "125.100.IN-ADDR.ARPA", + "126.100.IN-ADDR.ARPA", + "127.100.IN-ADDR.ARPA", /* RFC 5735 and RFC 5737 */ - { "0.IN-ADDR.ARPA", ISC_FALSE }, /* THIS NETWORK */ - { "127.IN-ADDR.ARPA", ISC_FALSE }, /* LOOPBACK */ - { "254.169.IN-ADDR.ARPA", ISC_FALSE }, /* LINK LOCAL */ - { "2.0.192.IN-ADDR.ARPA", ISC_FALSE }, /* TEST NET */ - { "100.51.198.IN-ADDR.ARPA", ISC_FALSE }, /* TEST NET 2 */ - { "113.0.203.IN-ADDR.ARPA", ISC_FALSE }, /* TEST NET 3 */ - { "255.255.255.255.IN-ADDR.ARPA", ISC_FALSE }, /* BROADCAST */ + "0.IN-ADDR.ARPA", /* THIS NETWORK */ + "127.IN-ADDR.ARPA", /* LOOPBACK */ + "254.169.IN-ADDR.ARPA", /* LINK LOCAL */ + "2.0.192.IN-ADDR.ARPA", /* TEST NET */ + "100.51.198.IN-ADDR.ARPA", /* TEST NET 2 */ + "113.0.203.IN-ADDR.ARPA", /* TEST NET 3 */ + "255.255.255.255.IN-ADDR.ARPA", /* BROADCAST */ /* Local IPv6 Unicast Addresses */ - { "0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.IP6.ARPA", ISC_FALSE }, - { "1.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.IP6.ARPA", ISC_FALSE }, + "0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.IP6.ARPA", + "1.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.IP6.ARPA", /* LOCALLY ASSIGNED LOCAL ADDRESS SCOPE */ - { "D.F.IP6.ARPA", ISC_FALSE }, - { "8.E.F.IP6.ARPA", ISC_FALSE }, /* LINK LOCAL */ - { "9.E.F.IP6.ARPA", ISC_FALSE }, /* LINK LOCAL */ - { "A.E.F.IP6.ARPA", ISC_FALSE }, /* LINK LOCAL */ - { "B.E.F.IP6.ARPA", ISC_FALSE }, /* LINK LOCAL */ + "D.F.IP6.ARPA", + "8.E.F.IP6.ARPA", /* LINK LOCAL */ + "9.E.F.IP6.ARPA", /* LINK LOCAL */ + "A.E.F.IP6.ARPA", /* LINK LOCAL */ + "B.E.F.IP6.ARPA", /* LINK LOCAL */ /* Example Prefix, RFC 3849. */ - { "8.B.D.0.1.0.0.2.IP6.ARPA", ISC_FALSE }, + "8.B.D.0.1.0.0.2.IP6.ARPA", - { NULL, ISC_FALSE } + NULL }; ISC_PLATFORM_NORETURN_PRE static void @@ -1334,12 +1348,14 @@ check_dbtype(dns_zone_t **zonep, unsigned int dbtypec, const char **dbargv, } static isc_result_t -setquerystats(dns_zone_t *zone, isc_mem_t *mctx, isc_boolean_t on) { +setquerystats(dns_zone_t *zone, isc_mem_t *mctx, dns_zonestat_level_t level) { isc_result_t result; isc_stats_t *zoneqrystats; + dns_zone_setstatlevel(zone, level); + zoneqrystats = NULL; - if (on) { + if (level == dns_zonestat_full) { result = isc_stats_create(mctx, &zoneqrystats, dns_nsstatscounter_max); if (result != ISC_R_SUCCESS) @@ -1387,7 +1403,7 @@ static isc_boolean_t cache_sharable(dns_view_t *originview, dns_view_t *view, isc_boolean_t new_zero_no_soattl, unsigned int new_cleaning_interval, - isc_uint32_t new_max_cache_size) + isc_uint64_t new_max_cache_size) { /* * If the cache cannot even reused for the same view, it cannot be @@ -1420,11 +1436,11 @@ dlzconfigure_callback(dns_view_t *view, dns_zone_t *zone) { result = dns_zonemgr_managezone(ns_g_server->zonemgr, zone); if (result != ISC_R_SUCCESS) - return result; + return (result); dns_zone_setstats(zone, ns_g_server->zonestats); - return ns_zone_configure_writeable_dlz(view->dlzdatabase, - zone, zclass, origin); + return (ns_zone_configure_writeable_dlz(view->dlzdatabase, + zone, zclass, origin)); } static isc_result_t @@ -1493,7 +1509,7 @@ dns64_reverse(dns_view_t *view, isc_mem_t *mctx, isc_netaddr_t *na, dns_zone_setdialup(zone, dns_dialuptype_no); dns_zone_setnotifytype(zone, dns_notifytype_no); dns_zone_setoption(zone, DNS_ZONEOPT_NOCHECKNS, ISC_TRUE); - CHECK(setquerystats(zone, mctx, ISC_FALSE)); /* XXXMPA */ + CHECK(setquerystats(zone, mctx, dns_zonestat_none)); /* XXXMPA */ CHECK(dns_view_addzone(view, zone)); isc_log_write(ns_g_lctx, NS_LOGCATEGORY_GENERAL, NS_LOGMODULE_SERVER, ISC_LOG_INFO, "dns64 reverse zone%s%s: %s", sep, @@ -1654,10 +1670,10 @@ configure_view(dns_view_t *view, cfg_obj_t *config, cfg_obj_t *vconfig, in_port_t port; dns_cache_t *cache = NULL; isc_result_t result; - isc_uint32_t max_adb_size; unsigned int cleaning_interval; - isc_uint32_t max_cache_size; - isc_uint32_t max_acache_size; + size_t max_cache_size; + size_t max_acache_size; + size_t max_adb_size; isc_uint32_t lame_ttl; dns_tsig_keyring_t *ring = NULL; dns_view_t *pview = NULL; /* Production view */ @@ -1671,13 +1687,13 @@ configure_view(dns_view_t *view, cfg_obj_t *config, cfg_obj_t *vconfig, const char *cachename = NULL; dns_order_t *order = NULL; isc_uint32_t udpsize; + isc_uint32_t maxbits; unsigned int resopts = 0; dns_zone_t *zone = NULL; isc_uint32_t max_clients_per_query; const char *sep = ": view "; const char *viewname = view->name; const char *forview = " for view "; - isc_boolean_t rfc1918; isc_boolean_t empty_zones_enable; const cfg_obj_t *disablelist = NULL; isc_stats_t *resstats = NULL; @@ -1687,7 +1703,7 @@ configure_view(dns_view_t *view, cfg_obj_t *config, cfg_obj_t *vconfig, ns_cache_t *nsc; isc_boolean_t zero_no_soattl; dns_acl_t *clients = NULL, *mapped = NULL, *excluded = NULL; - unsigned int query_timeout; + unsigned int query_timeout, ndisp; struct cfg_context *nzctx; dns_rpz_zone_t *rpz; @@ -1763,18 +1779,18 @@ configure_view(dns_view_t *view, cfg_obj_t *config, cfg_obj_t *vconfig, max_acache_size = ISC_UINT32_MAX; } else { isc_resourcevalue_t value; - value = cfg_obj_asuint64(obj); - if (value > ISC_UINT32_MAX) { - cfg_obj_log(obj, ns_g_lctx, ISC_LOG_ERROR, + if (value > SIZE_MAX) { + cfg_obj_log(obj, ns_g_lctx, + ISC_LOG_WARNING, "'max-acache-size " - "%" ISC_PRINT_QUADFORMAT - "d' is too large", - value); - result = ISC_R_RANGE; - goto cleanup; + "%" ISC_PRINT_QUADFORMAT "u' " + "is too large for this " + "system; reducing to %lu", + value, (unsigned long)SIZE_MAX); + value = SIZE_MAX; } - max_acache_size = (isc_uint32_t)value; + max_acache_size = (size_t) value; } dns_acache_setcachesize(view->acache, max_acache_size); } @@ -1961,15 +1977,17 @@ configure_view(dns_view_t *view, cfg_obj_t *config, cfg_obj_t *vconfig, } else { isc_resourcevalue_t value; value = cfg_obj_asuint64(obj); - if (value > ISC_UINT32_MAX) { - cfg_obj_log(obj, ns_g_lctx, ISC_LOG_ERROR, + if (value > SIZE_MAX) { + cfg_obj_log(obj, ns_g_lctx, + ISC_LOG_WARNING, "'max-cache-size " - "%" ISC_PRINT_QUADFORMAT "d' is too large", - value); - result = ISC_R_RANGE; - goto cleanup; + "%" ISC_PRINT_QUADFORMAT "u' " + "is too large for this " + "system; reducing to %lu", + value, (unsigned long)SIZE_MAX); + value = SIZE_MAX; } - max_cache_size = (isc_uint32_t)value; + max_cache_size = (size_t) value; } /* Check-names. */ @@ -2278,7 +2296,9 @@ configure_view(dns_view_t *view, cfg_obj_t *config, cfg_obj_t *vconfig, result = ISC_R_UNEXPECTED; goto cleanup; } - CHECK(dns_view_createresolver(view, ns_g_taskmgr, 31, + + ndisp = 4 * ISC_MIN(ns_g_udpdisp, MAX_UDP_DISPATCH); + CHECK(dns_view_createresolver(view, ns_g_taskmgr, 31, ndisp, ns_g_socketmgr, ns_g_timermgr, resopts, ns_g_dispatchmgr, dispatch4, dispatch6)); @@ -2363,6 +2383,19 @@ configure_view(dns_view_t *view, cfg_obj_t *config, cfg_obj_t *vconfig, view->maxudp = udpsize; /* + * Set the maximum rsa exponent bits. + */ + obj = NULL; + result = ns_config_get(maps, "max-rsa-exponent-size", &obj); + INSIST(result == ISC_R_SUCCESS); + maxbits = cfg_obj_asuint32(obj); + if (maxbits != 0 && maxbits < 35) + maxbits = 35; + if (maxbits > 4096) + maxbits = 4096; + view->maxbits = maxbits; + + /* * Set supported DNSSEC algorithms. */ dns_resolver_reset_algorithms(view->resolver); @@ -2690,11 +2723,6 @@ configure_view(dns_view_t *view, cfg_obj_t *config, cfg_obj_t *vconfig, ns_g_mctx, &view->upfwdacl)); obj = NULL; - result = ns_config_get(maps, "request-ixfr", &obj); - INSIST(result == ISC_R_SUCCESS); - view->requestixfr = cfg_obj_asboolean(obj); - - obj = NULL; result = ns_config_get(maps, "provide-ixfr", &obj); INSIST(result == ISC_R_SUCCESS); view->provideixfr = cfg_obj_asboolean(obj); @@ -2847,16 +2875,13 @@ configure_view(dns_view_t *view, cfg_obj_t *config, cfg_obj_t *vconfig, (void)ns_config_get(maps, "disable-empty-zone", &disablelist); if (obj == NULL && disablelist == NULL && view->rdclass == dns_rdataclass_in) { - rfc1918 = ISC_FALSE; empty_zones_enable = view->recursion; } else if (view->rdclass == dns_rdataclass_in) { - rfc1918 = ISC_TRUE; if (obj != NULL) empty_zones_enable = cfg_obj_asboolean(obj); else empty_zones_enable = view->recursion; } else { - rfc1918 = ISC_FALSE; empty_zones_enable = ISC_FALSE; } if (empty_zones_enable && !lwresd_g_useresolvconf) { @@ -2868,11 +2893,10 @@ configure_view(dns_view_t *view, cfg_obj_t *config, cfg_obj_t *vconfig, const char *str; char server[DNS_NAME_FORMATSIZE + 1]; char contact[DNS_NAME_FORMATSIZE + 1]; - isc_boolean_t logit; const char *empty_dbtype[4] = { "_builtin", "empty", NULL, NULL }; int empty_dbtypec = 4; - isc_boolean_t zonestats_on; + dns_zonestat_level_t statlevel; dns_fixedname_init(&fixed); name = dns_fixedname_name(&fixed); @@ -2910,12 +2934,26 @@ configure_view(dns_view_t *view, cfg_obj_t *config, cfg_obj_t *vconfig, obj = NULL; result = ns_config_get(maps, "zone-statistics", &obj); INSIST(result == ISC_R_SUCCESS); - zonestats_on = cfg_obj_asboolean(obj); + if (cfg_obj_isboolean(obj)) { + if (cfg_obj_asboolean(obj)) + statlevel = dns_zonestat_full; + else + statlevel = dns_zonestat_terse; /* XXX */ + } else { + const char *levelstr = cfg_obj_asstring(obj); + if (strcasecmp(levelstr, "full") == 0) + statlevel = dns_zonestat_full; + else if (strcasecmp(levelstr, "terse") == 0) + statlevel = dns_zonestat_terse; + else if (strcasecmp(levelstr, "none") == 0) + statlevel = dns_zonestat_none; + else + INSIST(0); + } - logit = ISC_TRUE; - for (empty = empty_zones[empty_zone].zone; + for (empty = empty_zones[empty_zone]; empty != NULL; - empty = empty_zones[++empty_zone].zone) + empty = empty_zones[++empty_zone]) { dns_forwarders_t *forwarders = NULL; dns_view_t *pview = NULL; @@ -2950,23 +2988,6 @@ configure_view(dns_view_t *view, cfg_obj_t *config, cfg_obj_t *vconfig, forwarders->fwdpolicy == dns_fwdpolicy_only) continue; - if (!rfc1918 && empty_zones[empty_zone].rfc1918) { - if (logit) { - isc_log_write(ns_g_lctx, - NS_LOGCATEGORY_GENERAL, - NS_LOGMODULE_SERVER, - ISC_LOG_WARNING, - "Warning%s%s: " - "'empty-zones-enable/" - "disable-empty-zone' " - "not set: disabling " - "RFC 1918 empty zones", - sep, viewname); - logit = ISC_FALSE; - } - continue; - } - /* * See if we can re-use a existing zone. */ @@ -2987,13 +3008,14 @@ configure_view(dns_view_t *view, cfg_obj_t *config, cfg_obj_t *vconfig, dns_zone_setview(zone, view); CHECK(dns_view_addzone(view, zone)); CHECK(setquerystats(zone, mctx, - zonestats_on)); + statlevel)); dns_zone_detach(&zone); continue; } } - CHECK(dns_zone_create(&zone, mctx)); + CHECK(dns_zonemgr_createzone(ns_g_server->zonemgr, + &zone)); CHECK(dns_zone_setorigin(zone, name)); dns_zone_setview(zone, view); CHECK(dns_zonemgr_managezone(ns_g_server->zonemgr, @@ -3011,7 +3033,7 @@ configure_view(dns_view_t *view, cfg_obj_t *config, cfg_obj_t *vconfig, dns_zone_setnotifytype(zone, dns_notifytype_no); dns_zone_setoption(zone, DNS_ZONEOPT_NOCHECKNS, ISC_TRUE); - CHECK(setquerystats(zone, mctx, zonestats_on)); + CHECK(setquerystats(zone, mctx, statlevel)); CHECK(dns_view_addzone(view, zone)); isc_log_write(ns_g_lctx, NS_LOGCATEGORY_GENERAL, NS_LOGMODULE_SERVER, ISC_LOG_INFO, @@ -3357,6 +3379,7 @@ configure_zone(const cfg_obj_t *config, const cfg_obj_t *zconfig, { dns_view_t *pview = NULL; /* Production view */ dns_zone_t *zone = NULL; /* New or reused zone */ + dns_zone_t *raw = NULL; /* New or reused raw zone */ dns_zone_t *dupzone = NULL; const cfg_obj_t *options = NULL; const cfg_obj_t *zoptions = NULL; @@ -3364,6 +3387,7 @@ configure_zone(const cfg_obj_t *config, const cfg_obj_t *zconfig, const cfg_obj_t *forwarders = NULL; const cfg_obj_t *forwardtype = NULL; const cfg_obj_t *only = NULL; + const cfg_obj_t *signing = NULL; isc_result_t result; isc_result_t tresult; isc_buffer_t buffer; @@ -3487,6 +3511,38 @@ configure_zone(const cfg_obj_t *config, const cfg_obj_t *zconfig, } /* + * Redirect zones only require minimal configuration. + */ + if (strcasecmp(ztypestr, "redirect") == 0) { + if (view->redirect != NULL) { + cfg_obj_log(zconfig, ns_g_lctx, ISC_LOG_ERROR, + "redirect zone already exists"); + result = ISC_R_EXISTS; + goto cleanup; + } + result = dns_viewlist_find(&ns_g_server->viewlist, view->name, + view->rdclass, &pview); + if (result != ISC_R_NOTFOUND && result != ISC_R_SUCCESS) + goto cleanup; + if (pview != NULL && pview->redirect != NULL) { + dns_zone_attach(pview->redirect, &zone); + dns_zone_setview(zone, view); + } else { + CHECK(dns_zonemgr_createzone(ns_g_server->zonemgr, + &zone)); + CHECK(dns_zone_setorigin(zone, origin)); + dns_zone_setview(zone, view); + CHECK(dns_zonemgr_managezone(ns_g_server->zonemgr, + zone)); + dns_zone_setstats(zone, ns_g_server->zonestats); + } + CHECK(ns_zone_configure(config, vconfig, zconfig, aclconf, + zone, NULL)); + dns_zone_attach(zone, &view->redirect); + goto cleanup; + } + + /* * Check for duplicates in the new zone table. */ result = dns_view_findzone(view, origin, &dupzone); @@ -3527,15 +3583,15 @@ configure_zone(const cfg_obj_t *config, const cfg_obj_t *zconfig, * be reused if the options specify a slave zone) * - The zone was and is or was not and is not a policy zone */ - result = dns_viewlist_find(&ns_g_server->viewlist, - view->name, view->rdclass, - &pview); + result = dns_viewlist_find(&ns_g_server->viewlist, view->name, + view->rdclass, &pview); if (result != ISC_R_NOTFOUND && result != ISC_R_SUCCESS) goto cleanup; if (pview != NULL) result = dns_view_findzone(pview, origin, &zone); if (result != ISC_R_NOTFOUND && result != ISC_R_SUCCESS) goto cleanup; + if (zone != NULL && !ns_zone_reusable(zone, zconfig)) dns_zone_detach(&zone); @@ -3555,7 +3611,7 @@ configure_zone(const cfg_obj_t *config, const cfg_obj_t *zconfig, * We cannot reuse an existing zone, we have * to create a new one. */ - CHECK(dns_zone_create(&zone, mctx)); + CHECK(dns_zonemgr_createzone(ns_g_server->zonemgr, &zone)); CHECK(dns_zone_setorigin(zone, origin)); dns_zone_setview(zone, view); if (view->acache != NULL) @@ -3605,10 +3661,28 @@ configure_zone(const cfg_obj_t *config, const cfg_obj_t *zconfig, */ dns_zone_setadded(zone, added); + signing = NULL; + if ((strcasecmp(ztypestr, "master") == 0 || + strcasecmp(ztypestr, "slave") == 0) && + cfg_map_get(zoptions, "inline-signing", &signing) == ISC_R_SUCCESS && + cfg_obj_asboolean(signing)) + { + dns_zone_getraw(zone, &raw); + if (raw == NULL) { + CHECK(dns_zone_create(&raw, mctx)); + CHECK(dns_zone_setorigin(raw, origin)); + dns_zone_setview(raw, view); + if (view->acache != NULL) + dns_zone_setacache(raw, view->acache); + dns_zone_setstats(raw, ns_g_server->zonestats); + CHECK(dns_zone_link(zone, raw)); + } + } + /* * Configure the zone. */ - CHECK(ns_zone_configure(config, vconfig, zconfig, aclconf, zone)); + CHECK(ns_zone_configure(config, vconfig, zconfig, aclconf, zone, raw)); /* * Add the zone to its view in the new view list. @@ -3624,6 +3698,8 @@ configure_zone(const cfg_obj_t *config, const cfg_obj_t *zconfig, cleanup: if (zone != NULL) dns_zone_detach(&zone); + if (raw != NULL) + dns_zone_detach(&raw); if (pview != NULL) dns_view_detach(&pview); @@ -3666,7 +3742,7 @@ add_keydata_zone(dns_view_t *view, const char *directory, isc_mem_t *mctx) { } /* No existing keydata zone was found; create one */ - CHECK(dns_zone_create(&zone, mctx)); + CHECK(dns_zonemgr_createzone(ns_g_server->zonemgr, &zone)); CHECK(dns_zone_setorigin(zone, dns_rootname)); isc_sha256_data((void *)view->name, strlen(view->name), buffer); @@ -3700,7 +3776,7 @@ add_keydata_zone(dns_view_t *view, const char *directory, isc_mem_t *mctx) { dns_zone_setjournalsize(zone, 0); dns_zone_setstats(zone, ns_g_server->zonestats); - CHECK(setquerystats(zone, mctx, ISC_FALSE)); + CHECK(setquerystats(zone, mctx, dns_zonestat_none)); if (view->managed_keys != NULL) dns_zone_detach(&view->managed_keys); @@ -4108,6 +4184,9 @@ removed(dns_zone_t *zone, void *uap) { case dns_zone_stub: type = "stub"; break; + case dns_zone_redirect: + type = "redirect"; + break; default: type = "other"; break; @@ -5337,32 +5416,102 @@ load_configuration(const char *filename, ns_server_t *server, } static isc_result_t -load_zones(ns_server_t *server, isc_boolean_t stop) { +view_loaded(void *arg) { + isc_result_t result; + ns_zoneload_t *zl = (ns_zoneload_t *) arg; + ns_server_t *server = zl->server; + unsigned int refs; + + + /* + * Force zone maintenance. Do this after loading + * so that we know when we need to force AXFR of + * slave zones whose master files are missing. + * + * We use the zoneload reference counter to let us + * know when all views are finished. + */ + isc_refcount_decrement(&zl->refs, &refs); + if (refs != 0) + return (ISC_R_SUCCESS); + + isc_refcount_destroy(&zl->refs); + isc_mem_put(server->mctx, zl, sizeof (*zl)); + + isc_log_write(ns_g_lctx, NS_LOGCATEGORY_GENERAL, NS_LOGMODULE_SERVER, + ISC_LOG_NOTICE, "all zones loaded"); + CHECKFATAL(dns_zonemgr_forcemaint(server->zonemgr), + "forcing zone maintenance"); + + ns_os_started(); + isc_log_write(ns_g_lctx, NS_LOGCATEGORY_GENERAL, NS_LOGMODULE_SERVER, + ISC_LOG_NOTICE, "running"); + + return (ISC_R_SUCCESS); +} + +static isc_result_t +load_zones(ns_server_t *server) { isc_result_t result; dns_view_t *view; + ns_zoneload_t *zl; + unsigned int refs = 0; + + zl = isc_mem_get(server->mctx, sizeof (*zl)); + if (zl == NULL) + return (ISC_R_NOMEMORY); + zl->server = server; result = isc_task_beginexclusive(server->task); RUNTIME_CHECK(result == ISC_R_SUCCESS); + isc_refcount_init(&zl->refs, 1); + /* - * Load zone data from disk. + * Schedule zones to be loaded from disk. */ for (view = ISC_LIST_HEAD(server->viewlist); view != NULL; view = ISC_LIST_NEXT(view, link)) { - CHECK(dns_view_load(view, stop)); - if (view->managed_keys != NULL) - CHECK(dns_zone_load(view->managed_keys)); + if (view->managed_keys != NULL) { + result = dns_zone_load(view->managed_keys); + if (result != ISC_R_SUCCESS && + result != DNS_R_UPTODATE && + result != DNS_R_CONTINUE) + goto cleanup; + } + if (view->redirect != NULL) { + result = dns_zone_load(view->redirect); + if (result != ISC_R_SUCCESS && + result != DNS_R_UPTODATE && + result != DNS_R_CONTINUE) + goto cleanup; + } + + /* + * 'dns_view_asyncload' calls view_loaded if there are no + * zones. + */ + isc_refcount_increment(&zl->refs, NULL); + CHECK(dns_view_asyncload(view, view_loaded, zl)); } - /* - * Force zone maintenance. Do this after loading - * so that we know when we need to force AXFR of - * slave zones whose master files are missing. - */ - CHECK(dns_zonemgr_forcemaint(server->zonemgr)); cleanup: + isc_refcount_decrement(&zl->refs, &refs); + if (refs == 0) { + isc_refcount_destroy(&zl->refs); + isc_mem_put(server->mctx, zl, sizeof (*zl)); + } else { + /* + * Place the task manager into privileged mode. This + * ensures that after we leave task-exclusive mode, no + * other tasks will be able to run except for the ones + * that are loading zones. + */ + isc_taskmgr_setmode(ns_g_taskmgr, isc_taskmgrmode_privileged); + } + isc_task_endexclusive(server->task); return (result); } @@ -5387,6 +5536,8 @@ load_new_zones(ns_server_t *server, isc_boolean_t stop) { /* Load managed-keys data */ if (view->managed_keys != NULL) CHECK(dns_zone_loadnew(view->managed_keys)); + if (view->redirect != NULL) + CHECK(dns_zone_loadnew(view->redirect)); } /* @@ -5448,11 +5599,7 @@ run_server(isc_task_t *task, isc_event_t *event) { isc_hash_init(); - CHECKFATAL(load_zones(server, ISC_FALSE), "loading zones"); - - ns_os_started(); - isc_log_write(ns_g_lctx, NS_LOGCATEGORY_GENERAL, NS_LOGMODULE_SERVER, - ISC_LOG_NOTICE, "running"); + CHECKFATAL(load_zones(server), "loading zones"); } void @@ -5889,7 +6036,7 @@ reload(ns_server_t *server) { isc_result_t result; CHECK(loadconfig(server)); - result = load_zones(server, ISC_FALSE); + result = load_zones(server); if (result == ISC_R_SUCCESS) isc_log_write(ns_g_lctx, NS_LOGCATEGORY_GENERAL, NS_LOGMODULE_SERVER, ISC_LOG_INFO, @@ -5970,11 +6117,10 @@ next_token(char **stringp, const char *delim) { * set '*zonep' to NULL. */ static isc_result_t -zone_from_args(ns_server_t *server, char *args, dns_zone_t **zonep, - const char **zonename) +zone_from_args(ns_server_t *server, char *args, const char *zonetxt, + dns_zone_t **zonep, const char **zonename, isc_boolean_t skip) { char *input, *ptr; - const char *zonetxt; char *classtxt; const char *viewtxt = NULL; dns_fixedname_t name; @@ -5988,13 +6134,16 @@ zone_from_args(ns_server_t *server, char *args, dns_zone_t **zonep, input = args; - /* Skip the command name. */ - ptr = next_token(&input, " \t"); - if (ptr == NULL) - return (ISC_R_UNEXPECTEDEND); + if (skip) { + /* Skip the command name. */ + ptr = next_token(&input, " \t"); + if (ptr == NULL) + return (ISC_R_UNEXPECTEDEND); + } /* Look for the zone name. */ - zonetxt = next_token(&input, " \t"); + if (zonetxt == NULL) + zonetxt = next_token(&input, " \t"); if (zonetxt == NULL) return (ISC_R_SUCCESS); if (zonename != NULL) @@ -6057,13 +6206,20 @@ isc_result_t ns_server_retransfercommand(ns_server_t *server, char *args) { isc_result_t result; dns_zone_t *zone = NULL; + dns_zone_t *raw = NULL; dns_zonetype_t type; - result = zone_from_args(server, args, &zone, NULL); + result = zone_from_args(server, args, NULL, &zone, NULL, ISC_TRUE); if (result != ISC_R_SUCCESS) return (result); if (zone == NULL) return (ISC_R_UNEXPECTEDEND); + dns_zone_getraw(zone, &raw); + if (raw != NULL) { + dns_zone_detach(&zone); + dns_zone_attach(raw, &zone); + dns_zone_detach(&raw); + } type = dns_zone_gettype(zone); if (type == dns_zone_slave || type == dns_zone_stub) dns_zone_forcereload(zone); @@ -6083,7 +6239,7 @@ ns_server_reloadcommand(ns_server_t *server, char *args, isc_buffer_t *text) { dns_zonetype_t type; const char *msg = NULL; - result = zone_from_args(server, args, &zone, NULL); + result = zone_from_args(server, args, NULL, &zone, NULL, ISC_TRUE); if (result != ISC_R_SUCCESS) return (result); if (zone == NULL) { @@ -6143,7 +6299,7 @@ ns_server_notifycommand(ns_server_t *server, char *args, isc_buffer_t *text) { dns_zone_t *zone = NULL; const unsigned char msg[] = "zone notify queued"; - result = zone_from_args(server, args, &zone, NULL); + result = zone_from_args(server, args, NULL, &zone, NULL, ISC_TRUE); if (result != ISC_R_SUCCESS) return (result); if (zone == NULL) @@ -6168,7 +6324,7 @@ ns_server_refreshcommand(ns_server_t *server, char *args, isc_buffer_t *text) { const unsigned char msg2[] = "not a slave or stub zone"; dns_zonetype_t type; - result = zone_from_args(server, args, &zone, NULL); + result = zone_from_args(server, args, NULL, &zone, NULL, ISC_TRUE); if (result != ISC_R_SUCCESS) return (result); if (zone == NULL) @@ -6190,8 +6346,29 @@ ns_server_refreshcommand(ns_server_t *server, char *args, isc_buffer_t *text) { } isc_result_t -ns_server_togglequerylog(ns_server_t *server) { - server->log_queries = server->log_queries ? ISC_FALSE : ISC_TRUE; +ns_server_togglequerylog(ns_server_t *server, char *args) { + isc_boolean_t value; + char *ptr; + + /* Skip the command name. */ + ptr = next_token(&args, " \t"); + if (ptr == NULL) + return (ISC_R_UNEXPECTEDEND); + + ptr = next_token(&args, " \t"); + if (ptr == NULL) + value = server->log_queries ? ISC_FALSE : ISC_TRUE; + else if (strcasecmp(ptr, "yes") == 0 || strcasecmp(ptr, "on") == 0) + value = ISC_TRUE; + else if (strcasecmp(ptr, "no") == 0 || strcasecmp(ptr, "off") == 0) + value = ISC_FALSE; + else + return (ISC_R_NOTFOUND); + + if (server->log_queries == value) + return (ISC_R_SUCCESS); + + server->log_queries = value; isc_log_write(ns_g_lctx, NS_LOGCATEGORY_GENERAL, NS_LOGMODULE_SERVER, ISC_LOG_INFO, @@ -6598,6 +6775,7 @@ ns_server_dumpsecroots(ns_server_t *server, char *args) { ptr = next_token(&args, " \t"); if (ptr == NULL) return (ISC_R_UNEXPECTEDEND); + ptr = next_token(&args, " \t"); CHECKMF(isc_stdio_open(server->secrootsfile, "w", &fp), @@ -6895,7 +7073,7 @@ ns_server_flushcache(ns_server_t *server, char *args) { } isc_result_t -ns_server_flushname(ns_server_t *server, char *args) { +ns_server_flushnode(ns_server_t *server, char *args, isc_boolean_t tree) { char *ptr, *target, *viewname; dns_view_t *view; isc_boolean_t flushed; @@ -6942,13 +7120,15 @@ ns_server_flushname(ns_server_t *server, char *args) { * if some of the views share a single cache. But since the * operation is lightweight we prefer simplicity here. */ - result = dns_view_flushname(view, name); + result = dns_view_flushnode(view, name, tree); if (result != ISC_R_SUCCESS) { flushed = ISC_FALSE; isc_log_write(ns_g_lctx, NS_LOGCATEGORY_GENERAL, NS_LOGMODULE_SERVER, ISC_LOG_ERROR, - "flushing name '%s' in cache view '%s' " - "failed: %s", target, view->name, + "flushing %s '%s' in cache view '%s' " + "failed: %s", + tree ? "tree" : "name", + target, view->name, isc_result_totext(result)); } } @@ -6956,21 +7136,26 @@ ns_server_flushname(ns_server_t *server, char *args) { if (viewname != NULL) isc_log_write(ns_g_lctx, NS_LOGCATEGORY_GENERAL, NS_LOGMODULE_SERVER, ISC_LOG_INFO, - "flushing name '%s' in cache view '%s' " - "succeeded", target, viewname); + "flushing %s '%s' in cache view '%s' " + "succeeded", + tree ? "tree" : "name", + target, viewname); else isc_log_write(ns_g_lctx, NS_LOGCATEGORY_GENERAL, NS_LOGMODULE_SERVER, ISC_LOG_INFO, - "flushing name '%s' in all cache views " - "succeeded", target); + "flushing %s '%s' in all cache views " + "succeeded", + tree ? "tree" : "name", + target); result = ISC_R_SUCCESS; } else { if (!found) isc_log_write(ns_g_lctx, NS_LOGCATEGORY_GENERAL, NS_LOGMODULE_SERVER, ISC_LOG_ERROR, - "flushing name '%s' in cache view '%s' " - "failed: view not found", target, - viewname); + "flushing %s '%s' in cache view '%s' " + "failed: view not found", + tree ? "tree" : "name", + target, viewname); result = ISC_R_FAILURE; } isc_task_endexclusive(server->task); @@ -7005,6 +7190,7 @@ ns_server_status(ns_server_t *server, isc_buffer_t *text) { #ifdef ISC_PLATFORM_USETHREADS "CPUs found: %u\n" "worker threads: %u\n" + "UDP listeners per interface: %u\n" #endif "number of zones: %u\n" "debug level: %d\n" @@ -7017,7 +7203,7 @@ ns_server_status(ns_server_t *server, isc_buffer_t *text) { "server is up and running", ns_g_version, ob, alt, cb, #ifdef ISC_PLATFORM_USETHREADS - ns_g_cpus_detected, ns_g_cpus, + ns_g_cpus_detected, ns_g_cpus, ns_g_udpdisp, #endif zonecount, ns_g_debuglevel, xferrunning, xferdeferred, soaqueries, server->log_queries ? "ON" : "OFF", @@ -7269,7 +7455,7 @@ ns_server_rekey(ns_server_t *server, char *args) { if (strncasecmp(args, NS_COMMAND_SIGN, strlen(NS_COMMAND_SIGN)) == 0) fullsign = ISC_TRUE; - result = zone_from_args(server, args, &zone, NULL); + result = zone_from_args(server, args, NULL, &zone, NULL, ISC_TRUE); if (result != ISC_R_SUCCESS) return (result); if (zone == NULL) @@ -7296,6 +7482,112 @@ ns_server_rekey(ns_server_t *server, char *args) { } /* + * Act on a "sync" command from the command channel. +*/ +static isc_result_t +synczone(dns_zone_t *zone, void *uap) { + isc_boolean_t cleanup = *(isc_boolean_t *)uap; + isc_result_t result; + dns_zone_t *raw = NULL; + char *journal; + + dns_zone_getraw(zone, &raw); + if (raw != NULL) { + synczone(raw, uap); + dns_zone_detach(&raw); + } + + result = dns_zone_flush(zone); + if (result != ISC_R_SUCCESS) + cleanup = ISC_FALSE; + if (cleanup) { + journal = dns_zone_getjournal(zone); + if (journal != NULL) + (void)isc_file_remove(journal); + } + + return (result); +} + +isc_result_t +ns_server_sync(ns_server_t *server, char *args, isc_buffer_t *text) { + isc_result_t result, tresult; + dns_view_t *view; + dns_zone_t *zone = NULL; + char classstr[DNS_RDATACLASS_FORMATSIZE]; + char zonename[DNS_NAME_FORMATSIZE]; + const char *vname, *sep, *msg = NULL, *arg; + isc_boolean_t cleanup = ISC_FALSE; + + (void) next_token(&args, " \t"); + + arg = next_token(&args, " \t"); + if (arg != NULL && + (strcmp(arg, "-clean") == 0 || strcmp(arg, "-clear") == 0)) { + cleanup = ISC_TRUE; + arg = next_token(&args, " \t"); + } + + result = zone_from_args(server, args, arg, &zone, NULL, ISC_FALSE); + if (result != ISC_R_SUCCESS) + return (result); + + if (zone == NULL) { + result = isc_task_beginexclusive(server->task); + RUNTIME_CHECK(result == ISC_R_SUCCESS); + tresult = ISC_R_SUCCESS; + for (view = ISC_LIST_HEAD(server->viewlist); + view != NULL; + view = ISC_LIST_NEXT(view, link)) { + result = dns_zt_apply(view->zonetable, ISC_FALSE, + synczone, &cleanup); + if (result != ISC_R_SUCCESS && + tresult == ISC_R_SUCCESS) + tresult = result; + } + isc_task_endexclusive(server->task); + isc_log_write(ns_g_lctx, NS_LOGCATEGORY_GENERAL, + NS_LOGMODULE_SERVER, ISC_LOG_INFO, + "dumping all zones%s: %s", + cleanup ? ", removing journal files" : "", + isc_result_totext(result)); + return (tresult); + } + + result = isc_task_beginexclusive(server->task); + RUNTIME_CHECK(result == ISC_R_SUCCESS); + result = synczone(zone, &cleanup); + isc_task_endexclusive(server->task); + + if (msg != NULL && strlen(msg) < isc_buffer_availablelength(text)) + isc_buffer_putmem(text, (const unsigned char *)msg, + strlen(msg) + 1); + + view = dns_zone_getview(zone); + if (strcmp(view->name, "_default") == 0 || + strcmp(view->name, "_bind") == 0) + { + vname = ""; + sep = ""; + } else { + vname = view->name; + sep = " "; + } + dns_rdataclass_format(dns_zone_getclass(zone), classstr, + sizeof(classstr)); + dns_name_format(dns_zone_getorigin(zone), + zonename, sizeof(zonename)); + isc_log_write(ns_g_lctx, NS_LOGCATEGORY_GENERAL, + NS_LOGMODULE_SERVER, ISC_LOG_INFO, + "sync: dumping zone '%s/%s'%s%s%s: %s", + zonename, classstr, sep, vname, + cleanup ? ", removing journal file" : "", + isc_result_totext(result)); + dns_zone_detach(&zone); + return (result); +} + +/* * Act on a "freeze" or "thaw" command from the command channel. */ isc_result_t @@ -7303,17 +7595,16 @@ ns_server_freeze(ns_server_t *server, isc_boolean_t freeze, char *args, isc_buffer_t *text) { isc_result_t result, tresult; - dns_zone_t *zone = NULL; + dns_zone_t *zone = NULL, *raw = NULL; dns_zonetype_t type; char classstr[DNS_RDATACLASS_FORMATSIZE]; char zonename[DNS_NAME_FORMATSIZE]; dns_view_t *view; - char *journal; const char *vname, *sep; isc_boolean_t frozen; const char *msg = NULL; - result = zone_from_args(server, args, &zone, NULL); + result = zone_from_args(server, args, NULL, &zone, NULL, ISC_TRUE); if (result != ISC_R_SUCCESS) return (result); if (zone == NULL) { @@ -7336,12 +7627,23 @@ ns_server_freeze(ns_server_t *server, isc_boolean_t freeze, char *args, isc_result_totext(tresult)); return (tresult); } + dns_zone_getraw(zone, &raw); + if (raw != NULL) { + dns_zone_detach(&zone); + dns_zone_attach(raw, &zone); + dns_zone_detach(&raw); + } type = dns_zone_gettype(zone); if (type != dns_zone_master) { dns_zone_detach(&zone); return (DNS_R_NOTMASTER); } + if (freeze && !dns_zone_isdynamic(zone, ISC_TRUE)) { + dns_zone_detach(&zone); + return (DNS_R_NOTDYNAMIC); + } + result = isc_task_beginexclusive(server->task); RUNTIME_CHECK(result == ISC_R_SUCCESS); frozen = dns_zone_getupdatedisabled(zone); @@ -7358,11 +7660,6 @@ ns_server_freeze(ns_server_t *server, isc_boolean_t freeze, char *args, msg = "Flushing the zone updates to " "disk failed."; } - if (result == ISC_R_SUCCESS) { - journal = dns_zone_getjournal(zone); - if (journal != NULL) - (void)isc_file_remove(journal); - } if (result == ISC_R_SUCCESS) dns_zone_setupdatedisabled(zone, freeze); } else { @@ -7642,7 +7939,7 @@ ns_server_del_zone(ns_server_t *server, char *args) { FILE *ifp = NULL, *ofp = NULL; /* Parse parameters */ - CHECK(zone_from_args(server, args, &zone, &zonename)); + CHECK(zone_from_args(server, args, NULL, &zone, &zonename, ISC_TRUE)); if (zone == NULL) { result = ISC_R_UNEXPECTEDEND; @@ -7809,3 +8106,162 @@ newzone_cfgctx_destroy(void **cfgp) { isc_mem_putanddetach(&cfg->mctx, cfg, sizeof(*cfg)); *cfgp = NULL; } + +isc_result_t +ns_server_signing(ns_server_t *server, char *args, isc_buffer_t *text) { + isc_result_t result = ISC_R_SUCCESS; + dns_zone_t *zone = NULL; + dns_name_t *origin; + dns_db_t *db = NULL; + dns_dbnode_t *node = NULL; + dns_dbversion_t *version = NULL; + dns_rdatatype_t privatetype; + dns_rdataset_t privset; + isc_boolean_t first = ISC_TRUE; + isc_boolean_t list = ISC_FALSE, clear = ISC_FALSE; + isc_boolean_t chain = ISC_FALSE; + char keystr[DNS_SECALG_FORMATSIZE + 7]; + unsigned short hash = 0, flags = 0, iter = 0, saltlen = 0; + unsigned char salt[255]; + const char *ptr; + size_t n; + + dns_rdataset_init(&privset); + + /* Skip the command name. */ + ptr = next_token(&args, " \t"); + if (ptr == NULL) + return (ISC_R_UNEXPECTEDEND); + + /* Find out what we are to do. */ + ptr = next_token(&args, " \t"); + if (ptr == NULL) + return (ISC_R_UNEXPECTEDEND); + + if (strcasecmp(ptr, "-list") == 0) + list = ISC_TRUE; + else if ((strcasecmp(ptr, "-clear") == 0) || + (strcasecmp(ptr, "-clean") == 0)) { + clear = ISC_TRUE; + ptr = next_token(&args, " \t"); + if (ptr == NULL) + return (ISC_R_UNEXPECTEDEND); + memcpy(keystr, ptr, sizeof(keystr)); + } else if(strcasecmp(ptr, "-nsec3param") == 0) { + const char *hashstr, *flagstr, *iterstr; + char nbuf[512]; + + chain = ISC_TRUE; + hashstr = next_token(&args, " \t"); + if (hashstr == NULL) + return (ISC_R_UNEXPECTEDEND); + + if (strcasecmp(hashstr, "none") == 0) + hash = 0; + else { + flagstr = next_token(&args, " \t"); + iterstr = next_token(&args, " \t"); + if (flagstr == NULL || iterstr == NULL) + return (ISC_R_UNEXPECTEDEND); + + n = snprintf(nbuf, sizeof(nbuf), "%s %s %s", + hashstr, flagstr, iterstr); + if (n == sizeof(nbuf)) + return (ISC_R_NOSPACE); + n = sscanf(nbuf, "%hu %hu %hu", &hash, &flags, &iter); + if (n != 3U) + return (ISC_R_BADNUMBER); + + if (hash > 0xffU || flags > 0xffU) + return (ISC_R_RANGE); + + ptr = next_token(&args, " \t"); + if (ptr == NULL) + return (ISC_R_UNEXPECTEDEND); + if (strcmp(ptr, "-") != 0) { + isc_buffer_t buf; + + isc_buffer_init(&buf, salt, sizeof(salt)); + CHECK(isc_hex_decodestring(ptr, &buf)); + saltlen = isc_buffer_usedlength(&buf); + } + } + } else + CHECK(DNS_R_SYNTAX); + + CHECK(zone_from_args(server, args, NULL, &zone, NULL, ISC_FALSE)); + if (zone == NULL) + CHECK(ISC_R_UNEXPECTEDEND); + + if (clear) { + CHECK(dns_zone_keydone(zone, keystr)); + isc_buffer_putstr(text, "request queued"); + isc_buffer_putuint8(text, 0); + } else if (chain) { + CHECK(dns_zone_setnsec3param(zone, (isc_uint8_t)hash, + (isc_uint8_t)flags, iter, + (isc_uint8_t)saltlen, salt, + ISC_TRUE)); + isc_buffer_putstr(text, "request queued"); + isc_buffer_putuint8(text, 0); + } else if (list) { + privatetype = dns_zone_getprivatetype(zone); + origin = dns_zone_getorigin(zone); + CHECK(dns_zone_getdb(zone, &db)); + CHECK(dns_db_findnode(db, origin, ISC_FALSE, &node)); + dns_db_currentversion(db, &version); + + result = dns_db_findrdataset(db, node, version, privatetype, + dns_rdatatype_none, 0, + &privset, NULL); + if (result == ISC_R_NOTFOUND) { + isc_buffer_putstr(text, "No signing records found"); + isc_buffer_putuint8(text, 0); + result = ISC_R_SUCCESS; + goto cleanup; + } + + for (result = dns_rdataset_first(&privset); + result == ISC_R_SUCCESS; + result = dns_rdataset_next(&privset)) + { + dns_rdata_t priv = DNS_RDATA_INIT; + char output[BUFSIZ]; + isc_buffer_t buf; + + dns_rdataset_current(&privset, &priv); + + isc_buffer_init(&buf, output, sizeof(output)); + CHECK(dns_private_totext(&priv, &buf)); + + if (!first) + isc_buffer_putstr(text, "\n"); + first = ISC_FALSE; + + n = snprintf((char *)isc_buffer_used(text), + isc_buffer_availablelength(text), + "%s", output); + if (n >= isc_buffer_availablelength(text)) + CHECK(ISC_R_NOSPACE); + + isc_buffer_add(text, n); + } + + if (result == ISC_R_NOMORE) + result = ISC_R_SUCCESS; + } + + cleanup: + if (dns_rdataset_isassociated(&privset)) + dns_rdataset_disassociate(&privset); + if (node != NULL) + dns_db_detachnode(db, &node); + if (version != NULL) + dns_db_closeversion(db, &version, ISC_FALSE); + if (db != NULL) + dns_db_detach(&db); + if (zone != NULL) + dns_zone_detach(&zone); + + return (result); +} diff --git a/contrib/bind9/bin/named/statschannel.c b/contrib/bind9/bin/named/statschannel.c index 8d30b452f2bd..bb642cc374bf 100644 --- a/contrib/bind9/bin/named/statschannel.c +++ b/contrib/bind9/bin/named/statschannel.c @@ -14,7 +14,7 @@ * PERFORMANCE OF THIS SOFTWARE. */ -/* $Id: statschannel.c,v 1.26.150.2 2011/03/12 04:59:14 tbox Exp $ */ +/* $Id: statschannel.c,v 1.28 2011/03/12 04:59:46 tbox Exp $ */ /*! \file */ @@ -43,7 +43,11 @@ #include <named/server.h> #include <named/statschannel.h> -#include "bind9.xsl.h" +#ifdef NEWSTATS + #include "bind9.ver3.xsl.h" +#else /* OLDSTATS */ + #include "bind9.xsl.h" +#endif /* NEWSTATS */ struct ns_statschannel { /* Unlocked */ @@ -187,7 +191,7 @@ init_desc(void) { SET_NSSTATDESC(servfail, "queries resulted in SERVFAIL", "QrySERVFAIL"); SET_NSSTATDESC(formerr, "queries resulted in FORMERR", "QryFORMERR"); SET_NSSTATDESC(nxdomain, "queries resulted in NXDOMAIN", "QryNXDOMAIN"); - SET_NSSTATDESC(recursion, "queries caused recursion","QryRecursion"); + SET_NSSTATDESC(recursion, "queries caused recursion", "QryRecursion"); SET_NSSTATDESC(duplicate, "duplicate queries received", "QryDuplicate"); SET_NSSTATDESC(dropped, "queries dropped", "QryDropped"); SET_NSSTATDESC(failure, "other query failures", "QryFailure"); @@ -304,7 +308,8 @@ init_desc(void) { SET_ZONESTATDESC(axfrreqv6, "IPv6 AXFR requested", "AXFRReqv6"); SET_ZONESTATDESC(ixfrreqv4, "IPv4 IXFR requested", "IXFRReqv4"); SET_ZONESTATDESC(ixfrreqv6, "IPv6 IXFR requested", "IXFRReqv6"); - SET_ZONESTATDESC(xfrsuccess, "transfer requests succeeded","XfrSuccess"); + SET_ZONESTATDESC(xfrsuccess, "transfer requests succeeded", + "XfrSuccess"); SET_ZONESTATDESC(xfrfail, "transfer requests failed", "XfrFail"); INSIST(i == dns_zonestatscounter_max); @@ -427,7 +432,7 @@ init_desc(void) { do { \ set_desc(dns_dnssecstats_ ## counterid, \ dns_dnssecstats_max, \ - desc, dnssecstats_desc,\ + desc, dnssecstats_desc, \ xmldesc, dnssecstats_xmldesc); \ dnssecstats_index[i++] = dns_dnssecstats_ ## counterid; \ } while (0) @@ -519,6 +524,51 @@ dump_counters(isc_stats_t *stats, statsformat_t type, void *arg, break; case statsformat_xml: #ifdef HAVE_LIBXML2 +#ifdef NEWSTATS + writer = arg; + + if (category != NULL) { + /* <NameOfCategory> */ + TRY0(xmlTextWriterStartElement(writer, + ISC_XMLCHAR + category)); + /* <name> inside category */ + TRY0(xmlTextWriterStartElement(writer, + ISC_XMLCHAR + "name")); + TRY0(xmlTextWriterWriteString(writer, + ISC_XMLCHAR + desc[index])); + TRY0(xmlTextWriterEndElement(writer)); + /* </name> */ + + /* <counter> */ + TRY0(xmlTextWriterStartElement(writer, + ISC_XMLCHAR + "counter")); + TRY0(xmlTextWriterWriteFormatString(writer, + "%" ISC_PRINT_QUADFORMAT "u", value)); + + TRY0(xmlTextWriterEndElement(writer)); + /* </counter> */ + TRY0(xmlTextWriterEndElement(writer)); + /* </NameOfCategory> */ + + } else { + TRY0(xmlTextWriterStartElement(writer, + ISC_XMLCHAR + "counter")); + TRY0(xmlTextWriterWriteAttribute(writer, + ISC_XMLCHAR + "name", + ISC_XMLCHAR + desc[index])); + TRY0(xmlTextWriterWriteFormatString(writer, + "%" ISC_PRINT_QUADFORMAT "u", value)); + TRY0(xmlTextWriterEndElement(writer)); + /* counter */ + } +#else /* !NEWSTATS */ writer = arg; if (category != NULL) { @@ -548,17 +598,73 @@ dump_counters(isc_stats_t *stats, statsformat_t type, void *arg, TRY0(xmlTextWriterEndElement(writer)); /* counter */ if (category != NULL) TRY0(xmlTextWriterEndElement(writer)); /* category */ -#endif +#endif /* NEWSTATS */ +#endif /* LIBXML2 */ break; } } return (ISC_R_SUCCESS); #ifdef HAVE_LIBXML2 error: + isc_log_write(ns_g_lctx, NS_LOGCATEGORY_GENERAL, NS_LOGMODULE_SERVER, + ISC_LOG_ERROR, "failed at dump_counters()"); return (ISC_R_FAILURE); #endif } +#ifdef NEWSTATS +static void +rdtypestat_dump(dns_rdatastatstype_t type, isc_uint64_t val, void *arg) { + char typebuf[64]; + const char *typestr; + stats_dumparg_t *dumparg = arg; + FILE *fp; +#ifdef HAVE_LIBXML2 + xmlTextWriterPtr writer; + int xmlrc; +#endif + + if ((DNS_RDATASTATSTYPE_ATTR(type) & DNS_RDATASTATSTYPE_ATTR_OTHERTYPE) + == 0) { + dns_rdatatype_format(DNS_RDATASTATSTYPE_BASE(type), typebuf, + sizeof(typebuf)); + typestr = typebuf; + } else + typestr = "Others"; + + switch (dumparg->type) { + case statsformat_file: + fp = dumparg->arg; + fprintf(fp, "%20" ISC_PRINT_QUADFORMAT "u %s\n", val, typestr); + break; + case statsformat_xml: +#ifdef HAVE_LIBXML2 + + writer = dumparg->arg; + + + TRY0(xmlTextWriterStartElement(writer, ISC_XMLCHAR "counter")); + TRY0(xmlTextWriterWriteAttribute(writer, ISC_XMLCHAR "name", + ISC_XMLCHAR typestr)); + + TRY0(xmlTextWriterWriteFormatString(writer, + "%" ISC_PRINT_QUADFORMAT "u", + val)); + + TRY0(xmlTextWriterEndElement(writer)); /* type */ +#endif + break; + } + return; +#ifdef HAVE_LIBXML2 + error: + isc_log_write(ns_g_lctx, NS_LOGCATEGORY_GENERAL, NS_LOGMODULE_SERVER, + ISC_LOG_ERROR, "failed at rdtypestat_dump()"); + dumparg->result = ISC_R_FAILURE; + return; +#endif +} +#else /* NEWSTATS */ static void rdtypestat_dump(dns_rdatastatstype_t type, isc_uint64_t val, void *arg) { char typebuf[64]; @@ -610,6 +716,7 @@ rdtypestat_dump(dns_rdatastatstype_t type, isc_uint64_t val, void *arg) { return; #endif } +#endif /* NEWSTATS */ static void rdatasetstats_dump(dns_rdatastatstype_t type, isc_uint64_t val, void *arg) { @@ -668,11 +775,58 @@ rdatasetstats_dump(dns_rdatastatstype_t type, isc_uint64_t val, void *arg) { return; #ifdef HAVE_LIBXML2 error: + isc_log_write(ns_g_lctx, NS_LOGCATEGORY_GENERAL, NS_LOGMODULE_SERVER, + ISC_LOG_ERROR, "failed at rdatasetstats_dump()"); dumparg->result = ISC_R_FAILURE; #endif } +#ifdef NEWSTATS +static void +opcodestat_dump(dns_opcode_t code, isc_uint64_t val, void *arg) { + FILE *fp; + isc_buffer_t b; + char codebuf[64]; + stats_dumparg_t *dumparg = arg; +#ifdef HAVE_LIBXML2 + xmlTextWriterPtr writer; + int xmlrc; +#endif + + isc_buffer_init(&b, codebuf, sizeof(codebuf) - 1); + dns_opcode_totext(code, &b); + codebuf[isc_buffer_usedlength(&b)] = '\0'; + + switch (dumparg->type) { + case statsformat_file: + fp = dumparg->arg; + fprintf(fp, "%20" ISC_PRINT_QUADFORMAT "u %s\n", val, codebuf); + break; + case statsformat_xml: +#ifdef HAVE_LIBXML2 + writer = dumparg->arg; + TRY0(xmlTextWriterStartElement(writer, ISC_XMLCHAR "counter")); + TRY0(xmlTextWriterWriteAttribute(writer, ISC_XMLCHAR "name", + ISC_XMLCHAR codebuf )); + TRY0(xmlTextWriterWriteFormatString(writer, + "%" ISC_PRINT_QUADFORMAT "u", + val)); + TRY0(xmlTextWriterEndElement(writer)); /* counter */ +#endif + break; + } + return; + +#ifdef HAVE_LIBXML2 + error: + isc_log_write(ns_g_lctx, NS_LOGCATEGORY_GENERAL, NS_LOGMODULE_SERVER, + ISC_LOG_ERROR, "failed at opcodestat_dump()"); + dumparg->result = ISC_R_FAILURE; + return; +#endif +} +#else /* NEWSTATS */ static void opcodestat_dump(dns_opcode_t code, isc_uint64_t val, void *arg) { FILE *fp; @@ -721,12 +875,96 @@ opcodestat_dump(dns_opcode_t code, isc_uint64_t val, void *arg) { return; #endif } +#endif /* NEWSTATS */ #ifdef HAVE_LIBXML2 -/* XXXMLG below here sucks. */ +/* XXXMLG below here sucks. (not so much) */ + +#ifdef NEWSTATS +static isc_result_t +zone_xmlrender(dns_zone_t *zone, void *arg) { + isc_result_t result; + char buf[1024 + 32]; /* sufficiently large for zone name and class */ + char *zone_name_only = NULL; + dns_rdataclass_t rdclass; + isc_uint32_t serial; + xmlTextWriterPtr writer = arg; + isc_stats_t *zonestats; + dns_stats_t *rcvquerystats; + dns_zonestat_level_t statlevel; + isc_uint64_t nsstat_values[dns_nsstatscounter_max]; + int xmlrc; + stats_dumparg_t dumparg; + + statlevel = dns_zone_getstatlevel(zone); + if (statlevel == dns_zonestat_none) + return (ISC_R_SUCCESS); + + dumparg.type = statsformat_xml; + dumparg.arg = writer; + + TRY0(xmlTextWriterStartElement(writer, ISC_XMLCHAR "zone")); + dns_zone_name(zone, buf, sizeof(buf)); + zone_name_only = strtok(buf, "/"); + if(zone_name_only == NULL) + zone_name_only = buf; + TRY0(xmlTextWriterWriteAttribute(writer, ISC_XMLCHAR "name", + ISC_XMLCHAR zone_name_only)); + rdclass = dns_zone_getclass(zone); + dns_rdataclass_format(rdclass, buf, sizeof(buf)); + TRY0(xmlTextWriterWriteAttribute(writer, ISC_XMLCHAR "rdataclass", + ISC_XMLCHAR buf)); + TRY0(xmlTextWriterStartElement(writer, ISC_XMLCHAR "serial")); + if (dns_zone_getserial2(zone, &serial) == ISC_R_SUCCESS) + TRY0(xmlTextWriterWriteFormatString(writer, "%u", serial)); + else + TRY0(xmlTextWriterWriteString(writer, ISC_XMLCHAR "-")); + TRY0(xmlTextWriterEndElement(writer)); /* serial */ + + zonestats = dns_zone_getrequeststats(zone); + rcvquerystats = dns_zone_getrcvquerystats(zone); + if (statlevel == dns_zonestat_full && zonestats != NULL) { + TRY0(xmlTextWriterStartElement(writer, ISC_XMLCHAR "counters")); + TRY0(xmlTextWriterWriteAttribute(writer, ISC_XMLCHAR "type", + ISC_XMLCHAR "rcode")); + + result = dump_counters(zonestats, statsformat_xml, writer, + NULL, nsstats_xmldesc, + dns_nsstatscounter_max, nsstats_index, + nsstat_values, ISC_STATSDUMP_VERBOSE); + if (result != ISC_R_SUCCESS) + goto error; + /* counters type="rcode"*/ + TRY0(xmlTextWriterEndElement(writer)); + } + + if (statlevel == dns_zonestat_full && rcvquerystats != NULL) { + TRY0(xmlTextWriterStartElement(writer, ISC_XMLCHAR "counters")); + TRY0(xmlTextWriterWriteAttribute(writer, ISC_XMLCHAR "type", + ISC_XMLCHAR "qtype")); + + dumparg.result = ISC_R_SUCCESS; + dns_rdatatypestats_dump(rcvquerystats, rdtypestat_dump, + &dumparg, 0); + if(dumparg.result != ISC_R_SUCCESS) + goto error; + + /* counters type="qtype"*/ + TRY0(xmlTextWriterEndElement(writer)); + } + + TRY0(xmlTextWriterEndElement(writer)); /* zone */ + + return (ISC_R_SUCCESS); + error: + isc_log_write(ns_g_lctx, NS_LOGCATEGORY_GENERAL, NS_LOGMODULE_SERVER, + ISC_LOG_ERROR, "Failed at zone_xmlrender()"); + return (ISC_R_FAILURE); +} +#else /* NEWSTATS */ static isc_result_t zone_xmlrender(dns_zone_t *zone, void *arg) { char buf[1024 + 32]; /* sufficiently large for zone name and class */ @@ -776,7 +1014,237 @@ zone_xmlrender(dns_zone_t *zone, void *arg) { error: return (ISC_R_FAILURE); } +#endif /* NEWSTATS */ + +#ifdef NEWSTATS +static isc_result_t +generatexml(ns_server_t *server, int *buflen, xmlChar **buf) { + char boottime[sizeof "yyyy-mm-ddThh:mm:ssZ"]; + char nowstr[sizeof "yyyy-mm-ddThh:mm:ssZ"]; + isc_time_t now; + xmlTextWriterPtr writer = NULL; + xmlDocPtr doc = NULL; + int xmlrc; + dns_view_t *view; + stats_dumparg_t dumparg; + dns_stats_t *cacherrstats; + isc_uint64_t nsstat_values[dns_nsstatscounter_max]; + isc_uint64_t resstat_values[dns_resstatscounter_max]; + isc_uint64_t zonestat_values[dns_zonestatscounter_max]; + isc_uint64_t sockstat_values[isc_sockstatscounter_max]; + isc_result_t result; + + isc_time_now(&now); + isc_time_formatISO8601(&ns_g_boottime, boottime, sizeof boottime); + isc_time_formatISO8601(&now, nowstr, sizeof nowstr); + + writer = xmlNewTextWriterDoc(&doc, 0); + if (writer == NULL) + goto error; + TRY0(xmlTextWriterStartDocument(writer, NULL, "UTF-8", NULL)); + TRY0(xmlTextWriterWritePI(writer, ISC_XMLCHAR "xml-stylesheet", + ISC_XMLCHAR "type=\"text/xsl\" href=\"/bind9.ver3.xsl\"")); + TRY0(xmlTextWriterStartElement(writer, ISC_XMLCHAR "statistics")); + TRY0(xmlTextWriterWriteAttribute(writer, ISC_XMLCHAR "version", + ISC_XMLCHAR "3.0")); + + /* Set common fields for statistics dump */ + dumparg.type = statsformat_xml; + dumparg.arg = writer; + + /* + * Start by rendering the views we know of here. For each view we + * know of, call its rendering function. + */ + view = ISC_LIST_HEAD(server->viewlist); + TRY0(xmlTextWriterStartElement(writer, ISC_XMLCHAR "views")); + while (view != NULL) { + TRY0(xmlTextWriterStartElement(writer, ISC_XMLCHAR "view")); + TRY0(xmlTextWriterWriteAttribute(writer, ISC_XMLCHAR "name", + ISC_XMLCHAR view->name)); + + TRY0(xmlTextWriterStartElement(writer, ISC_XMLCHAR "zones")); + result = dns_zt_apply(view->zonetable, ISC_TRUE, zone_xmlrender, + writer); + if (result != ISC_R_SUCCESS) + goto error; + TRY0(xmlTextWriterEndElement(writer)); /* zones */ + + TRY0(xmlTextWriterStartElement(writer, + ISC_XMLCHAR "counters")); + TRY0(xmlTextWriterWriteAttribute(writer, ISC_XMLCHAR "type", + ISC_XMLCHAR "resqtype")); + + if (view->resquerystats != NULL) { + dumparg.result = ISC_R_SUCCESS; + dns_rdatatypestats_dump(view->resquerystats, + rdtypestat_dump, &dumparg, 0); + if (dumparg.result != ISC_R_SUCCESS) + goto error; + } + TRY0(xmlTextWriterEndElement(writer)); + + /* <resstats> */ + TRY0(xmlTextWriterStartElement(writer, ISC_XMLCHAR "counters")); + TRY0(xmlTextWriterWriteAttribute(writer, ISC_XMLCHAR "type", + ISC_XMLCHAR "resstats")); + if (view->resstats != NULL) { + result = dump_counters(view->resstats, + statsformat_xml, writer, + NULL, resstats_xmldesc, + dns_resstatscounter_max, + resstats_index, resstat_values, + ISC_STATSDUMP_VERBOSE); + if (result != ISC_R_SUCCESS) + goto error; + } + TRY0(xmlTextWriterEndElement(writer)); /* </resstats> */ + + cacherrstats = dns_db_getrrsetstats(view->cachedb); + if (cacherrstats != NULL) { + TRY0(xmlTextWriterStartElement(writer, + ISC_XMLCHAR "cache")); + TRY0(xmlTextWriterWriteAttribute(writer, + ISC_XMLCHAR "name", + ISC_XMLCHAR + dns_cache_getname(view->cache))); + dumparg.result = ISC_R_SUCCESS; + dns_rdatasetstats_dump(cacherrstats, rdatasetstats_dump, + &dumparg, 0); + if (dumparg.result != ISC_R_SUCCESS) + goto error; + TRY0(xmlTextWriterEndElement(writer)); /* cache */ + } + + TRY0(xmlTextWriterEndElement(writer)); /* view */ + + view = ISC_LIST_NEXT(view, link); + } + TRY0(xmlTextWriterEndElement(writer)); /* views */ + + TRY0(xmlTextWriterStartElement(writer, ISC_XMLCHAR "socketmgr")); + isc_socketmgr_renderxml(ns_g_socketmgr, writer); + TRY0(xmlTextWriterEndElement(writer)); /* socketmgr */ + + TRY0(xmlTextWriterStartElement(writer, ISC_XMLCHAR "taskmgr")); + isc_taskmgr_renderxml(ns_g_taskmgr, writer); + TRY0(xmlTextWriterEndElement(writer)); /* taskmgr */ + + TRY0(xmlTextWriterStartElement(writer, ISC_XMLCHAR "server")); + TRY0(xmlTextWriterStartElement(writer, ISC_XMLCHAR "boot-time")); + TRY0(xmlTextWriterWriteString(writer, ISC_XMLCHAR boottime)); + TRY0(xmlTextWriterEndElement(writer)); /* boot-time */ + TRY0(xmlTextWriterStartElement(writer, ISC_XMLCHAR "current-time")); + TRY0(xmlTextWriterWriteString(writer, ISC_XMLCHAR nowstr)); + TRY0(xmlTextWriterEndElement(writer)); /* current-time */ + + dumparg.result = ISC_R_SUCCESS; + + TRY0(xmlTextWriterStartElement(writer, ISC_XMLCHAR "counters")); + TRY0(xmlTextWriterWriteAttribute(writer, ISC_XMLCHAR "type", + ISC_XMLCHAR "opcode")); + + dns_opcodestats_dump(server->opcodestats, opcodestat_dump, &dumparg, + 0); + if (dumparg.result != ISC_R_SUCCESS) + goto error; + + TRY0(xmlTextWriterEndElement(writer)); /* counters type=opcode */ + + TRY0(xmlTextWriterStartElement(writer, ISC_XMLCHAR "counters")); + TRY0(xmlTextWriterWriteAttribute(writer, ISC_XMLCHAR "type", + ISC_XMLCHAR "qtype")); + + dumparg.result = ISC_R_SUCCESS; + dns_rdatatypestats_dump(server->rcvquerystats, rdtypestat_dump, + &dumparg, 0); + if (dumparg.result != ISC_R_SUCCESS) + goto error; + TRY0(xmlTextWriterEndElement(writer)); /* counters */ + TRY0(xmlTextWriterStartElement(writer, ISC_XMLCHAR "counters")); + TRY0(xmlTextWriterWriteAttribute(writer, ISC_XMLCHAR "type", + ISC_XMLCHAR "nsstat")); + + result = dump_counters(server->nsstats, statsformat_xml, + writer, NULL, nsstats_xmldesc, + dns_nsstatscounter_max, + nsstats_index, nsstat_values, + ISC_STATSDUMP_VERBOSE); + if (result != ISC_R_SUCCESS) + goto error; + + TRY0(xmlTextWriterEndElement(writer)); /* counters type=nsstat */ + + TRY0(xmlTextWriterStartElement(writer, ISC_XMLCHAR "counters")); + TRY0(xmlTextWriterWriteAttribute(writer, ISC_XMLCHAR "type", + ISC_XMLCHAR "zonestat")); + + result = dump_counters(server->zonestats, statsformat_xml, writer, + NULL, zonestats_xmldesc, + dns_zonestatscounter_max, zonestats_index, + zonestat_values, ISC_STATSDUMP_VERBOSE); + if (result != ISC_R_SUCCESS) + goto error; + + TRY0(xmlTextWriterEndElement(writer)); /* counters type=zonestat */ + + /* + * Most of the common resolver statistics entries are 0, so we don't + * use the verbose dump here. + */ + + TRY0(xmlTextWriterStartElement(writer, ISC_XMLCHAR "counters")); + TRY0(xmlTextWriterWriteAttribute(writer, ISC_XMLCHAR "type", + ISC_XMLCHAR "resstat")); + result = dump_counters(server->resolverstats, statsformat_xml, + writer, NULL, resstats_xmldesc, + dns_resstatscounter_max, resstats_index, + resstat_values, 0); + if (result != ISC_R_SUCCESS) + goto error; + + TRY0(xmlTextWriterEndElement(writer)); /* counters type=resstat */ + + TRY0(xmlTextWriterStartElement(writer, ISC_XMLCHAR "counters")); + TRY0(xmlTextWriterWriteAttribute(writer, ISC_XMLCHAR "type", + ISC_XMLCHAR "sockstat")); + + result = dump_counters(server->sockstats, statsformat_xml, + writer, NULL, sockstats_xmldesc, + isc_sockstatscounter_max, sockstats_index, + sockstat_values, ISC_STATSDUMP_VERBOSE); + if (result != ISC_R_SUCCESS) + goto error; + + TRY0(xmlTextWriterEndElement(writer)); /* counters type=sockstat */ + + TRY0(xmlTextWriterEndElement(writer)); /* server */ + + TRY0(xmlTextWriterStartElement(writer, ISC_XMLCHAR "memory")); + isc_mem_renderxml(writer); + TRY0(xmlTextWriterEndElement(writer)); /* memory */ + + TRY0(xmlTextWriterEndElement(writer)); /* statistics */ + + TRY0(xmlTextWriterEndDocument(writer)); + + xmlFreeTextWriter(writer); + + xmlDocDumpFormatMemoryEnc(doc, buf, buflen, "UTF-8", 0); + xmlFreeDoc(doc); + return (ISC_R_SUCCESS); + + error: + isc_log_write(ns_g_lctx, NS_LOGCATEGORY_GENERAL, NS_LOGMODULE_SERVER, + ISC_LOG_ERROR, "failed generating XML response"); + if (writer != NULL) + xmlFreeTextWriter(writer); + if (doc != NULL) + xmlFreeDoc(doc); + return (ISC_R_FAILURE); +} +#else /* OLDSTATS */ static isc_result_t generatexml(ns_server_t *server, int *buflen, xmlChar **buf) { char boottime[sizeof "yyyy-mm-ddThh:mm:ssZ"]; @@ -968,6 +1436,7 @@ generatexml(ns_server_t *server, int *buflen, xmlChar **buf) { xmlFreeDoc(doc); return (ISC_R_FAILURE); } +#endif /* NEWSTATS */ static void wrap_xmlfree(isc_buffer_t *buffer, void *arg) { @@ -1000,7 +1469,10 @@ render_index(const char *url, const char *querystring, void *arg, isc_buffer_add(b, msglen); *freecb = wrap_xmlfree; *freecb_args = NULL; - } + } else + isc_log_write(ns_g_lctx, NS_LOGCATEGORY_GENERAL, + NS_LOGMODULE_SERVER, ISC_LOG_ERROR, + "failed at rendering XML()"); return (result); } @@ -1032,7 +1504,7 @@ static void shutdown_listener(ns_statschannel_t *listener) { char socktext[ISC_SOCKADDR_FORMATSIZE]; isc_sockaddr_format(&listener->address, socktext, sizeof(socktext)); - isc_log_write(ns_g_lctx, NS_LOGCATEGORY_GENERAL,NS_LOGMODULE_SERVER, + isc_log_write(ns_g_lctx, NS_LOGCATEGORY_GENERAL, NS_LOGMODULE_SERVER, ISC_LOG_NOTICE, "stopping statistics channel on %s", socktext); @@ -1150,10 +1622,22 @@ add_listener(ns_server_t *server, ns_statschannel_t **listenerp, #ifdef HAVE_LIBXML2 isc_httpdmgr_addurl(listener->httpdmgr, "/", render_index, server); + isc_httpdmgr_addurl(listener->httpdmgr, "/xml", render_index, server); +#ifdef NEWSTATS + isc_httpdmgr_addurl(listener->httpdmgr, "/xml/v3", render_index, + server); +#else /* OLDSTATS */ + isc_httpdmgr_addurl(listener->httpdmgr, "/xml/v2", render_index, + server); +#endif /* NEWSTATS */ #endif +#ifdef NEWSTATS + isc_httpdmgr_addurl(listener->httpdmgr, "/bind9.ver3.xsl", render_xsl, + server); +#else /* OLDSTATS */ isc_httpdmgr_addurl(listener->httpdmgr, "/bind9.xsl", render_xsl, server); - +#endif /* NEWSTATS */ *listenerp = listener; isc_log_write(ns_g_lctx, NS_LOGCATEGORY_GENERAL, NS_LOGMODULE_SERVER, ISC_LOG_NOTICE, @@ -1285,7 +1769,8 @@ ns_statschannels_configure(ns_server_t *server, const cfg_obj_t *config, obj = cfg_tuple_get(listen_params, "address"); addr = *cfg_obj_assockaddr(obj); if (isc_sockaddr_getport(&addr) == 0) - isc_sockaddr_setport(&addr, NS_STATSCHANNEL_HTTPPORT); + isc_sockaddr_setport(&addr, + NS_STATSCHANNEL_HTTPPORT); isc_sockaddr_format(&addr, socktext, sizeof(socktext)); diff --git a/contrib/bind9/bin/named/unix/Makefile.in b/contrib/bind9/bin/named/unix/Makefile.in index ff2eccea86a4..17bb43e36aae 100644 --- a/contrib/bind9/bin/named/unix/Makefile.in +++ b/contrib/bind9/bin/named/unix/Makefile.in @@ -13,7 +13,7 @@ # OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR # PERFORMANCE OF THIS SOFTWARE. -# $Id: Makefile.in,v 1.13.244.2 2011/03/10 23:47:26 tbox Exp $ +# $Id: Makefile.in,v 1.15 2011/03/10 23:47:49 tbox Exp $ srcdir = @srcdir@ VPATH = @srcdir@ diff --git a/contrib/bind9/bin/named/unix/dlz_dlopen_driver.c b/contrib/bind9/bin/named/unix/dlz_dlopen_driver.c index 98dfc5a75ba1..2ba8a028a37a 100644 --- a/contrib/bind9/bin/named/unix/dlz_dlopen_driver.c +++ b/contrib/bind9/bin/named/unix/dlz_dlopen_driver.c @@ -14,7 +14,7 @@ * PERFORMANCE OF THIS SOFTWARE. */ -/* $Id: dlz_dlopen_driver.c,v 1.1.4.6 2012/02/22 23:46:35 tbox Exp $ */ +/* $Id$ */ #include <config.h> @@ -143,7 +143,7 @@ dlopen_dlz_allowzonexfr(void *driverarg, void *dbdata, const char *name, static isc_result_t dlopen_dlz_authority(const char *zone, void *driverarg, void *dbdata, - dns_sdlzlookup_t *lookup) + dns_sdlzlookup_t *lookup) { dlopen_data_t *cd = (dlopen_data_t *) dbdata; isc_result_t result; @@ -177,7 +177,9 @@ dlopen_dlz_findzonedb(void *driverarg, void *dbdata, const char *name) static isc_result_t dlopen_dlz_lookup(const char *zone, const char *name, void *driverarg, - void *dbdata, dns_sdlzlookup_t *lookup) + void *dbdata, dns_sdlzlookup_t *lookup, + dns_clientinfomethods_t *methods, + dns_clientinfo_t *clientinfo) { dlopen_data_t *cd = (dlopen_data_t *) dbdata; isc_result_t result; @@ -185,7 +187,8 @@ dlopen_dlz_lookup(const char *zone, const char *name, void *driverarg, UNUSED(driverarg); MAYBE_LOCK(cd); - result = cd->dlz_lookup(zone, name, cd->dbdata, lookup); + result = cd->dlz_lookup(zone, name, cd->dbdata, lookup, + methods, clientinfo); MAYBE_UNLOCK(cd); return (result); } diff --git a/contrib/bind9/bin/named/unix/os.c b/contrib/bind9/bin/named/unix/os.c index 9637ded473e5..4f5f55c3eedb 100644 --- a/contrib/bind9/bin/named/unix/os.c +++ b/contrib/bind9/bin/named/unix/os.c @@ -15,7 +15,7 @@ * PERFORMANCE OF THIS SOFTWARE. */ -/* $Id: os.c,v 1.104.38.3 2011/03/02 00:04:01 marka Exp $ */ +/* $Id: os.c,v 1.107 2011/03/02 00:02:54 marka Exp $ */ /*! \file */ diff --git a/contrib/bind9/bin/named/update.c b/contrib/bind9/bin/named/update.c index abf5c08c6d30..0df00c083c55 100644 --- a/contrib/bind9/bin/named/update.c +++ b/contrib/bind9/bin/named/update.c @@ -15,7 +15,7 @@ * PERFORMANCE OF THIS SOFTWARE. */ -/* $Id: update.c,v 1.186.16.7 2011/11/03 02:55:34 each Exp $ */ +/* $Id: update.c,v 1.199 2011/12/22 07:32:40 each Exp $ */ #include <config.h> @@ -47,6 +47,7 @@ #include <dns/soa.h> #include <dns/ssu.h> #include <dns/tsig.h> +#include <dns/update.h> #include <dns/view.h> #include <dns/zone.h> #include <dns/zt.h> @@ -268,6 +269,11 @@ update_log(ns_client_t *client, dns_zone_t *zone, namebuf, classbuf, message); } +static void +update_log_cb(void *arg, dns_zone_t *zone, int level, const char *message) { + update_log(arg, zone, level, "%s", message); +} + /*% * Increment updated-related statistics counters. */ @@ -721,45 +727,6 @@ rrset_exists(dns_db_t *db, dns_dbversion_t *ver, dns_name_t *name, } /*% - * Set '*visible' to true if the RRset exists and is part of the - * visible zone. Otherwise '*visible' is set to false unless a - * error occurs. - */ -static isc_result_t -rrset_visible(dns_db_t *db, dns_dbversion_t *ver, dns_name_t *name, - dns_rdatatype_t type, isc_boolean_t *visible) -{ - isc_result_t result; - dns_fixedname_t fixed; - - dns_fixedname_init(&fixed); - result = dns_db_find(db, name, ver, type, DNS_DBFIND_NOWILD, - (isc_stdtime_t) 0, NULL, - dns_fixedname_name(&fixed), NULL, NULL); - switch (result) { - case ISC_R_SUCCESS: - *visible = ISC_TRUE; - break; - /* - * Glue, obscured, deleted or replaced records. - */ - case DNS_R_DELEGATION: - case DNS_R_DNAME: - case DNS_R_CNAME: - case DNS_R_NXDOMAIN: - case DNS_R_NXRRSET: - case DNS_R_EMPTYNAME: - case DNS_R_COVERINGNSEC: - *visible = ISC_FALSE; - result = ISC_R_SUCCESS; - break; - default: - break; - } - return (result); -} - -/*% * Helper function for cname_incompatible_rrset_exists. */ static isc_result_t @@ -1174,16 +1141,6 @@ true_p(dns_rdata_t *update_rr, dns_rdata_t *db_rr) { } /*% - * Return true if the record is a RRSIG. - */ -static isc_boolean_t -rrsig_p(dns_rdata_t *update_rr, dns_rdata_t *db_rr) { - UNUSED(update_rr); - return ((db_rr->type == dns_rdatatype_rrsig) ? - ISC_TRUE : ISC_FALSE); -} - -/*% * Return true iff the two RRs have identical rdata. */ static isc_boolean_t @@ -1425,8 +1382,8 @@ get_current_rr(dns_message_t *msg, dns_section_t section, */ static isc_result_t -increment_soa_serial(dns_db_t *db, dns_dbversion_t *ver, - dns_diff_t *diff, isc_mem_t *mctx) +update_soa_serial(dns_db_t *db, dns_dbversion_t *ver, dns_diff_t *diff, + isc_mem_t *mctx, dns_updatemethod_t method) { dns_difftuple_t *deltuple = NULL; dns_difftuple_t *addtuple = NULL; @@ -1438,12 +1395,7 @@ increment_soa_serial(dns_db_t *db, dns_dbversion_t *ver, addtuple->op = DNS_DIFFOP_ADD; serial = dns_soa_getserial(&addtuple->rdata); - - /* RFC1982 */ - serial = (serial + 1) & 0xFFFFFFFF; - if (serial == 0) - serial = 1; - + serial = dns_update_soaserial(serial, method); dns_soa_setserial(serial, &addtuple->rdata); CHECK(do_one_tuple(&deltuple, db, ver, diff)); CHECK(do_one_tuple(&addtuple, db, ver, diff)); @@ -1502,1129 +1454,6 @@ check_soa_increment(dns_db_t *db, dns_dbversion_t *ver, } /**************************************************************************/ -/* - * Incremental updating of NSECs and RRSIGs. - */ - -/*% - * We abuse the dns_diff_t type to represent a set of domain names - * affected by the update. - */ -static isc_result_t -namelist_append_name(dns_diff_t *list, dns_name_t *name) { - isc_result_t result; - dns_difftuple_t *tuple = NULL; - static dns_rdata_t dummy_rdata = DNS_RDATA_INIT; - - CHECK(dns_difftuple_create(list->mctx, DNS_DIFFOP_EXISTS, name, 0, - &dummy_rdata, &tuple)); - dns_diff_append(list, &tuple); - failure: - return (result); -} - -static isc_result_t -namelist_append_subdomain(dns_db_t *db, dns_name_t *name, dns_diff_t *affected) -{ - isc_result_t result; - dns_fixedname_t fixedname; - dns_name_t *child; - dns_dbiterator_t *dbit = NULL; - - dns_fixedname_init(&fixedname); - child = dns_fixedname_name(&fixedname); - - CHECK(dns_db_createiterator(db, DNS_DB_NONSEC3, &dbit)); - - for (result = dns_dbiterator_seek(dbit, name); - result == ISC_R_SUCCESS; - result = dns_dbiterator_next(dbit)) - { - dns_dbnode_t *node = NULL; - CHECK(dns_dbiterator_current(dbit, &node, child)); - dns_db_detachnode(db, &node); - if (! dns_name_issubdomain(child, name)) - break; - CHECK(namelist_append_name(affected, child)); - } - if (result == ISC_R_NOMORE) - result = ISC_R_SUCCESS; - failure: - if (dbit != NULL) - dns_dbiterator_destroy(&dbit); - return (result); -} - - - -/*% - * Helper function for non_nsec_rrset_exists(). - */ -static isc_result_t -is_non_nsec_action(void *data, dns_rdataset_t *rrset) { - UNUSED(data); - if (!(rrset->type == dns_rdatatype_nsec || - rrset->type == dns_rdatatype_nsec3 || - (rrset->type == dns_rdatatype_rrsig && - (rrset->covers == dns_rdatatype_nsec || - rrset->covers == dns_rdatatype_nsec3)))) - return (ISC_R_EXISTS); - return (ISC_R_SUCCESS); -} - -/*% - * Check whether there is an rrset other than a NSEC or RRSIG NSEC, - * i.e., anything that justifies the continued existence of a name - * after a secure update. - * - * If such an rrset exists, set '*exists' to ISC_TRUE. - * Otherwise, set it to ISC_FALSE. - */ -static isc_result_t -non_nsec_rrset_exists(dns_db_t *db, dns_dbversion_t *ver, - dns_name_t *name, isc_boolean_t *exists) -{ - isc_result_t result; - result = foreach_rrset(db, ver, name, is_non_nsec_action, NULL); - RETURN_EXISTENCE_FLAG; -} - -/*% - * A comparison function for sorting dns_diff_t:s by name. - */ -static int -name_order(const void *av, const void *bv) { - dns_difftuple_t const * const *ap = av; - dns_difftuple_t const * const *bp = bv; - dns_difftuple_t const *a = *ap; - dns_difftuple_t const *b = *bp; - return (dns_name_compare(&a->name, &b->name)); -} - -static isc_result_t -uniqify_name_list(dns_diff_t *list) { - isc_result_t result; - dns_difftuple_t *p, *q; - - CHECK(dns_diff_sort(list, name_order)); - - p = ISC_LIST_HEAD(list->tuples); - while (p != NULL) { - do { - q = ISC_LIST_NEXT(p, link); - if (q == NULL || ! dns_name_equal(&p->name, &q->name)) - break; - ISC_LIST_UNLINK(list->tuples, q, link); - dns_difftuple_free(&q); - } while (1); - p = ISC_LIST_NEXT(p, link); - } - failure: - return (result); -} - -static isc_result_t -is_active(dns_db_t *db, dns_dbversion_t *ver, dns_name_t *name, - isc_boolean_t *flag, isc_boolean_t *cut, isc_boolean_t *unsecure) -{ - isc_result_t result; - dns_fixedname_t foundname; - dns_fixedname_init(&foundname); - result = dns_db_find(db, name, ver, dns_rdatatype_any, - DNS_DBFIND_GLUEOK | DNS_DBFIND_NOWILD, - (isc_stdtime_t) 0, NULL, - dns_fixedname_name(&foundname), - NULL, NULL); - if (result == ISC_R_SUCCESS || result == DNS_R_EMPTYNAME) { - *flag = ISC_TRUE; - *cut = ISC_FALSE; - if (unsecure != NULL) - *unsecure = ISC_FALSE; - return (ISC_R_SUCCESS); - } else if (result == DNS_R_ZONECUT) { - *flag = ISC_TRUE; - *cut = ISC_TRUE; - if (unsecure != NULL) { - /* - * We are at the zonecut. Check to see if there - * is a DS RRset. - */ - if (dns_db_find(db, name, ver, dns_rdatatype_ds, 0, - (isc_stdtime_t) 0, NULL, - dns_fixedname_name(&foundname), - NULL, NULL) == DNS_R_NXRRSET) - *unsecure = ISC_TRUE; - else - *unsecure = ISC_FALSE; - } - return (ISC_R_SUCCESS); - } else if (result == DNS_R_GLUE || result == DNS_R_DNAME || - result == DNS_R_DELEGATION || result == DNS_R_NXDOMAIN) { - *flag = ISC_FALSE; - *cut = ISC_FALSE; - if (unsecure != NULL) - *unsecure = ISC_FALSE; - return (ISC_R_SUCCESS); - } else { - /* - * Silence compiler. - */ - *flag = ISC_FALSE; - *cut = ISC_FALSE; - if (unsecure != NULL) - *unsecure = ISC_FALSE; - return (result); - } -} - -/*% - * Find the next/previous name that has a NSEC record. - * In other words, skip empty database nodes and names that - * have had their NSECs removed because they are obscured by - * a zone cut. - */ -static isc_result_t -next_active(ns_client_t *client, dns_zone_t *zone, dns_db_t *db, - dns_dbversion_t *ver, dns_name_t *oldname, dns_name_t *newname, - isc_boolean_t forward) -{ - isc_result_t result; - dns_dbiterator_t *dbit = NULL; - isc_boolean_t has_nsec = ISC_FALSE; - unsigned int wraps = 0; - isc_boolean_t secure = dns_db_issecure(db); - - CHECK(dns_db_createiterator(db, 0, &dbit)); - - CHECK(dns_dbiterator_seek(dbit, oldname)); - do { - dns_dbnode_t *node = NULL; - - if (forward) - result = dns_dbiterator_next(dbit); - else - result = dns_dbiterator_prev(dbit); - if (result == ISC_R_NOMORE) { - /* - * Wrap around. - */ - if (forward) - CHECK(dns_dbiterator_first(dbit)); - else - CHECK(dns_dbiterator_last(dbit)); - wraps++; - if (wraps == 2) { - update_log(client, zone, ISC_LOG_ERROR, - "secure zone with no NSECs"); - result = DNS_R_BADZONE; - goto failure; - } - } - CHECK(dns_dbiterator_current(dbit, &node, newname)); - dns_db_detachnode(db, &node); - - /* - * The iterator may hold the tree lock, and - * rrset_exists() calls dns_db_findnode() which - * may try to reacquire it. To avoid deadlock - * we must pause the iterator first. - */ - CHECK(dns_dbiterator_pause(dbit)); - if (secure) { - CHECK(rrset_exists(db, ver, newname, - dns_rdatatype_nsec, 0, &has_nsec)); - } else { - dns_fixedname_t ffound; - dns_name_t *found; - dns_fixedname_init(&ffound); - found = dns_fixedname_name(&ffound); - result = dns_db_find(db, newname, ver, - dns_rdatatype_soa, - DNS_DBFIND_NOWILD, 0, NULL, found, - NULL, NULL); - if (result == ISC_R_SUCCESS || - result == DNS_R_EMPTYNAME || - result == DNS_R_NXRRSET || - result == DNS_R_CNAME || - (result == DNS_R_DELEGATION && - dns_name_equal(newname, found))) { - has_nsec = ISC_TRUE; - result = ISC_R_SUCCESS; - } else if (result != DNS_R_NXDOMAIN) - break; - } - } while (! has_nsec); - failure: - if (dbit != NULL) - dns_dbiterator_destroy(&dbit); - - return (result); -} - -/*% - * Add a NSEC record for "name", recording the change in "diff". - * The existing NSEC is removed. - */ -static isc_result_t -add_nsec(ns_client_t *client, dns_zone_t *zone, dns_db_t *db, - dns_dbversion_t *ver, dns_name_t *name, dns_ttl_t nsecttl, - dns_diff_t *diff) -{ - isc_result_t result; - dns_dbnode_t *node = NULL; - unsigned char buffer[DNS_NSEC_BUFFERSIZE]; - dns_rdata_t rdata = DNS_RDATA_INIT; - dns_difftuple_t *tuple = NULL; - dns_fixedname_t fixedname; - dns_name_t *target; - - dns_fixedname_init(&fixedname); - target = dns_fixedname_name(&fixedname); - - /* - * Find the successor name, aka NSEC target. - */ - CHECK(next_active(client, zone, db, ver, name, target, ISC_TRUE)); - - /* - * Create the NSEC RDATA. - */ - CHECK(dns_db_findnode(db, name, ISC_FALSE, &node)); - dns_rdata_init(&rdata); - CHECK(dns_nsec_buildrdata(db, ver, node, target, buffer, &rdata)); - dns_db_detachnode(db, &node); - - /* - * Delete the old NSEC and record the change. - */ - CHECK(delete_if(true_p, db, ver, name, dns_rdatatype_nsec, 0, - NULL, diff)); - /* - * Add the new NSEC and record the change. - */ - CHECK(dns_difftuple_create(diff->mctx, DNS_DIFFOP_ADD, name, - nsecttl, &rdata, &tuple)); - CHECK(do_one_tuple(&tuple, db, ver, diff)); - INSIST(tuple == NULL); - - failure: - if (node != NULL) - dns_db_detachnode(db, &node); - return (result); -} - -/*% - * Add a placeholder NSEC record for "name", recording the change in "diff". - */ -static isc_result_t -add_placeholder_nsec(dns_db_t *db, dns_dbversion_t *ver, dns_name_t *name, - dns_diff_t *diff) -{ - isc_result_t result; - dns_difftuple_t *tuple = NULL; - isc_region_t r; - unsigned char data[1] = { 0 }; /* The root domain, no bits. */ - dns_rdata_t rdata = DNS_RDATA_INIT; - - r.base = data; - r.length = sizeof(data); - dns_rdata_fromregion(&rdata, dns_db_class(db), dns_rdatatype_nsec, &r); - CHECK(dns_difftuple_create(diff->mctx, DNS_DIFFOP_ADD, name, 0, - &rdata, &tuple)); - CHECK(do_one_tuple(&tuple, db, ver, diff)); - failure: - return (result); -} - -static isc_result_t -find_zone_keys(dns_zone_t *zone, dns_db_t *db, dns_dbversion_t *ver, - isc_mem_t *mctx, unsigned int maxkeys, - dst_key_t **keys, unsigned int *nkeys) -{ - isc_result_t result; - dns_dbnode_t *node = NULL; - const char *directory = dns_zone_getkeydirectory(zone); - CHECK(dns_db_findnode(db, dns_db_origin(db), ISC_FALSE, &node)); - CHECK(dns_dnssec_findzonekeys2(db, ver, node, dns_db_origin(db), - directory, mctx, maxkeys, keys, nkeys)); - failure: - if (node != NULL) - dns_db_detachnode(db, &node); - return (result); -} - -/*% - * Add RRSIG records for an RRset, recording the change in "diff". - */ -static isc_result_t -add_sigs(ns_client_t *client, dns_zone_t *zone, dns_db_t *db, - dns_dbversion_t *ver, dns_name_t *name, dns_rdatatype_t type, - dns_diff_t *diff, dst_key_t **keys, unsigned int nkeys, - isc_stdtime_t inception, isc_stdtime_t expire, - isc_boolean_t check_ksk, isc_boolean_t keyset_kskonly) -{ - isc_result_t result; - dns_dbnode_t *node = NULL; - dns_rdataset_t rdataset; - dns_rdata_t sig_rdata = DNS_RDATA_INIT; - isc_buffer_t buffer; - unsigned char data[1024]; /* XXX */ - unsigned int i, j; - isc_boolean_t added_sig = ISC_FALSE; - isc_mem_t *mctx = client->mctx; - - dns_rdataset_init(&rdataset); - isc_buffer_init(&buffer, data, sizeof(data)); - - /* Get the rdataset to sign. */ - if (type == dns_rdatatype_nsec3) - CHECK(dns_db_findnsec3node(db, name, ISC_FALSE, &node)); - else - CHECK(dns_db_findnode(db, name, ISC_FALSE, &node)); - CHECK(dns_db_findrdataset(db, node, ver, type, 0, - (isc_stdtime_t) 0, &rdataset, NULL)); - dns_db_detachnode(db, &node); - -#define REVOKE(x) ((dst_key_flags(x) & DNS_KEYFLAG_REVOKE) != 0) -#define KSK(x) ((dst_key_flags(x) & DNS_KEYFLAG_KSK) != 0) -#define ALG(x) dst_key_alg(x) - - /* - * If we are honoring KSK flags then we need to check that we - * have both KSK and non-KSK keys that are not revoked per - * algorithm. - */ - for (i = 0; i < nkeys; i++) { - isc_boolean_t both = ISC_FALSE; - - if (!dst_key_isprivate(keys[i])) - continue; - - if (check_ksk && !REVOKE(keys[i])) { - isc_boolean_t have_ksk, have_nonksk; - if (KSK(keys[i])) { - have_ksk = ISC_TRUE; - have_nonksk = ISC_FALSE; - } else { - have_ksk = ISC_FALSE; - have_nonksk = ISC_TRUE; - } - for (j = 0; j < nkeys; j++) { - if (j == i || ALG(keys[i]) != ALG(keys[j])) - continue; - if (REVOKE(keys[j])) - continue; - if (KSK(keys[j])) - have_ksk = ISC_TRUE; - else - have_nonksk = ISC_TRUE; - both = have_ksk && have_nonksk; - if (both) - break; - } - } - - if (both) { - if (type == dns_rdatatype_dnskey) { - if (!KSK(keys[i]) && keyset_kskonly) - continue; - } else if (KSK(keys[i])) - continue; - } else if (REVOKE(keys[i]) && type != dns_rdatatype_dnskey) - continue; - - /* Calculate the signature, creating a RRSIG RDATA. */ - CHECK(dns_dnssec_sign(name, &rdataset, keys[i], - &inception, &expire, - mctx, &buffer, &sig_rdata)); - - /* Update the database and journal with the RRSIG. */ - /* XXX inefficient - will cause dataset merging */ - CHECK(update_one_rr(db, ver, diff, DNS_DIFFOP_ADDRESIGN, name, - rdataset.ttl, &sig_rdata)); - dns_rdata_reset(&sig_rdata); - isc_buffer_init(&buffer, data, sizeof(data)); - added_sig = ISC_TRUE; - } - if (!added_sig) { - update_log(client, zone, ISC_LOG_ERROR, - "found no active private keys, " - "unable to generate any signatures"); - result = ISC_R_NOTFOUND; - } - - failure: - if (dns_rdataset_isassociated(&rdataset)) - dns_rdataset_disassociate(&rdataset); - if (node != NULL) - dns_db_detachnode(db, &node); - return (result); -} - -/* - * Delete expired RRsigs and any RRsigs we are about to re-sign. - * See also zone.c:del_sigs(). - */ -static isc_result_t -del_keysigs(dns_db_t *db, dns_dbversion_t *ver, dns_name_t *name, - dns_diff_t *diff, dst_key_t **keys, unsigned int nkeys) -{ - isc_result_t result; - dns_dbnode_t *node = NULL; - dns_rdataset_t rdataset; - dns_rdata_t rdata = DNS_RDATA_INIT; - unsigned int i; - dns_rdata_rrsig_t rrsig; - isc_boolean_t found; - - dns_rdataset_init(&rdataset); - - result = dns_db_findnode(db, name, ISC_FALSE, &node); - if (result == ISC_R_NOTFOUND) - return (ISC_R_SUCCESS); - if (result != ISC_R_SUCCESS) - goto failure; - result = dns_db_findrdataset(db, node, ver, dns_rdatatype_rrsig, - dns_rdatatype_dnskey, (isc_stdtime_t) 0, - &rdataset, NULL); - dns_db_detachnode(db, &node); - - if (result == ISC_R_NOTFOUND) - return (ISC_R_SUCCESS); - if (result != ISC_R_SUCCESS) - goto failure; - - for (result = dns_rdataset_first(&rdataset); - result == ISC_R_SUCCESS; - result = dns_rdataset_next(&rdataset)) { - dns_rdataset_current(&rdataset, &rdata); - result = dns_rdata_tostruct(&rdata, &rrsig, NULL); - RUNTIME_CHECK(result == ISC_R_SUCCESS); - found = ISC_FALSE; - for (i = 0; i < nkeys; i++) { - if (rrsig.keyid == dst_key_id(keys[i])) { - found = ISC_TRUE; - if (!dst_key_isprivate(keys[i])) { - /* - * The re-signing code in zone.c - * will mark this as offline. - * Just skip the record for now. - */ - break; - } - result = update_one_rr(db, ver, diff, - DNS_DIFFOP_DEL, name, - rdataset.ttl, &rdata); - break; - } - } - /* - * If there is not a matching DNSKEY then delete the RRSIG. - */ - if (!found) - result = update_one_rr(db, ver, diff, DNS_DIFFOP_DEL, - name, rdataset.ttl, &rdata); - dns_rdata_reset(&rdata); - if (result != ISC_R_SUCCESS) - break; - } - dns_rdataset_disassociate(&rdataset); - if (result == ISC_R_NOMORE) - result = ISC_R_SUCCESS; -failure: - if (node != NULL) - dns_db_detachnode(db, &node); - return (result); -} - -static isc_result_t -add_exposed_sigs(ns_client_t *client, dns_zone_t *zone, dns_db_t *db, - dns_dbversion_t *ver, dns_name_t *name, isc_boolean_t cut, - dns_diff_t *diff, dst_key_t **keys, unsigned int nkeys, - isc_stdtime_t inception, isc_stdtime_t expire, - isc_boolean_t check_ksk, isc_boolean_t keyset_kskonly) -{ - isc_result_t result; - dns_dbnode_t *node; - dns_rdatasetiter_t *iter; - - node = NULL; - result = dns_db_findnode(db, name, ISC_FALSE, &node); - if (result == ISC_R_NOTFOUND) - return (ISC_R_SUCCESS); - if (result != ISC_R_SUCCESS) - return (result); - - iter = NULL; - result = dns_db_allrdatasets(db, node, ver, - (isc_stdtime_t) 0, &iter); - if (result != ISC_R_SUCCESS) - goto cleanup_node; - - for (result = dns_rdatasetiter_first(iter); - result == ISC_R_SUCCESS; - result = dns_rdatasetiter_next(iter)) - { - dns_rdataset_t rdataset; - dns_rdatatype_t type; - isc_boolean_t flag; - - dns_rdataset_init(&rdataset); - dns_rdatasetiter_current(iter, &rdataset); - type = rdataset.type; - dns_rdataset_disassociate(&rdataset); - - /* - * We don't need to sign unsigned NSEC records at the cut - * as they are handled elsewhere. - */ - if ((type == dns_rdatatype_rrsig) || - (cut && type != dns_rdatatype_ds)) - continue; - result = rrset_exists(db, ver, name, dns_rdatatype_rrsig, - type, &flag); - if (result != ISC_R_SUCCESS) - goto cleanup_iterator; - if (flag) - continue;; - result = add_sigs(client, zone, db, ver, name, type, diff, - keys, nkeys, inception, expire, - check_ksk, keyset_kskonly); - if (result != ISC_R_SUCCESS) - goto cleanup_iterator; - } - if (result == ISC_R_NOMORE) - result = ISC_R_SUCCESS; - - cleanup_iterator: - dns_rdatasetiter_destroy(&iter); - - cleanup_node: - dns_db_detachnode(db, &node); - - return (result); -} - -/*% - * Update RRSIG, NSEC and NSEC3 records affected by an update. The original - * update, including the SOA serial update but excluding the RRSIG & NSEC - * changes, is in "diff" and has already been applied to "newver" of "db". - * The database version prior to the update is "oldver". - * - * The necessary RRSIG, NSEC and NSEC3 changes will be applied to "newver" - * and added (as a minimal diff) to "diff". - * - * The RRSIGs generated will be valid for 'sigvalidityinterval' seconds. - */ -static isc_result_t -update_signatures(ns_client_t *client, dns_zone_t *zone, dns_db_t *db, - dns_dbversion_t *oldver, dns_dbversion_t *newver, - dns_diff_t *diff, isc_uint32_t sigvalidityinterval) -{ - isc_result_t result; - dns_difftuple_t *t; - dns_diff_t diffnames; - dns_diff_t affected; - dns_diff_t sig_diff; - dns_diff_t nsec_diff; - dns_diff_t nsec_mindiff; - isc_boolean_t flag, build_nsec, build_nsec3; - dst_key_t *zone_keys[DNS_MAXZONEKEYS]; - unsigned int nkeys = 0; - unsigned int i; - isc_stdtime_t now, inception, expire; - dns_ttl_t nsecttl; - dns_rdata_soa_t soa; - dns_rdata_t rdata = DNS_RDATA_INIT; - dns_rdataset_t rdataset; - dns_dbnode_t *node = NULL; - isc_boolean_t check_ksk, keyset_kskonly; - isc_boolean_t unsecure; - isc_boolean_t cut; - dns_rdatatype_t privatetype = dns_zone_getprivatetype(zone); - - dns_diff_init(client->mctx, &diffnames); - dns_diff_init(client->mctx, &affected); - - dns_diff_init(client->mctx, &sig_diff); - sig_diff.resign = dns_zone_getsigresigninginterval(zone); - dns_diff_init(client->mctx, &nsec_diff); - dns_diff_init(client->mctx, &nsec_mindiff); - - result = find_zone_keys(zone, db, newver, client->mctx, - DNS_MAXZONEKEYS, zone_keys, &nkeys); - if (result != ISC_R_SUCCESS) { - update_log(client, zone, ISC_LOG_ERROR, - "could not get zone keys for secure dynamic update"); - goto failure; - } - - isc_stdtime_get(&now); - inception = now - 3600; /* Allow for some clock skew. */ - expire = now + sigvalidityinterval; - - /* - * Do we look at the KSK flag on the DNSKEY to determining which - * keys sign which RRsets? First check the zone option then - * check the keys flags to make sure at least one has a ksk set - * and one doesn't. - */ - check_ksk = ISC_TF((dns_zone_getoptions(zone) & - DNS_ZONEOPT_UPDATECHECKKSK) != 0); - keyset_kskonly = ISC_TF((dns_zone_getoptions(zone) & - DNS_ZONEOPT_DNSKEYKSKONLY) != 0); - - /* - * Get the NSEC/NSEC3 TTL from the SOA MINIMUM field. - */ - CHECK(dns_db_findnode(db, dns_db_origin(db), ISC_FALSE, &node)); - dns_rdataset_init(&rdataset); - CHECK(dns_db_findrdataset(db, node, newver, dns_rdatatype_soa, 0, - (isc_stdtime_t) 0, &rdataset, NULL)); - CHECK(dns_rdataset_first(&rdataset)); - dns_rdataset_current(&rdataset, &rdata); - CHECK(dns_rdata_tostruct(&rdata, &soa, NULL)); - nsecttl = soa.minimum; - dns_rdataset_disassociate(&rdataset); - dns_db_detachnode(db, &node); - - /* - * Find all RRsets directly affected by the update, and - * update their RRSIGs. Also build a list of names affected - * by the update in "diffnames". - */ - CHECK(dns_diff_sort(diff, temp_order)); - - t = ISC_LIST_HEAD(diff->tuples); - while (t != NULL) { - dns_name_t *name = &t->name; - /* Now "name" is a new, unique name affected by the update. */ - - CHECK(namelist_append_name(&diffnames, name)); - - while (t != NULL && dns_name_equal(&t->name, name)) { - dns_rdatatype_t type; - type = t->rdata.type; - - /* - * Now "name" and "type" denote a new unique RRset - * affected by the update. - */ - - /* Don't sign RRSIGs. */ - if (type == dns_rdatatype_rrsig) - goto skip; - - /* - * Delete all old RRSIGs covering this type, since they - * are all invalid when the signed RRset has changed. - * We may not be able to recreate all of them - tough. - * Special case changes to the zone's DNSKEY records - * to support offline KSKs. - */ - if (type == dns_rdatatype_dnskey) - del_keysigs(db, newver, name, &sig_diff, - zone_keys, nkeys); - else - CHECK(delete_if(true_p, db, newver, name, - dns_rdatatype_rrsig, type, - NULL, &sig_diff)); - - /* - * If this RRset is still visible after the update, - * add a new signature for it. - */ - CHECK(rrset_visible(db, newver, name, type, &flag)); - if (flag) { - CHECK(add_sigs(client, zone, db, newver, name, - type, &sig_diff, zone_keys, - nkeys, inception, expire, - check_ksk, keyset_kskonly)); - } - skip: - /* Skip any other updates to the same RRset. */ - while (t != NULL && - dns_name_equal(&t->name, name) && - t->rdata.type == type) - { - t = ISC_LIST_NEXT(t, link); - } - } - } - update_log(client, zone, ISC_LOG_DEBUG(3), "updated data signatures"); - - /* Remove orphaned NSECs and RRSIG NSECs. */ - for (t = ISC_LIST_HEAD(diffnames.tuples); - t != NULL; - t = ISC_LIST_NEXT(t, link)) - { - CHECK(non_nsec_rrset_exists(db, newver, &t->name, &flag)); - if (! flag) { - CHECK(delete_if(true_p, db, newver, &t->name, - dns_rdatatype_any, 0, - NULL, &sig_diff)); - } - } - update_log(client, zone, ISC_LOG_DEBUG(3), - "removed any orphaned NSEC records"); - - /* - * See if we need to build NSEC or NSEC3 chains. - */ - CHECK(dns_private_chains(db, newver, privatetype, &build_nsec, - &build_nsec3)); - if (!build_nsec) - goto update_nsec3; - - update_log(client, zone, ISC_LOG_DEBUG(3), "rebuilding NSEC chain"); - - /* - * When a name is created or deleted, its predecessor needs to - * have its NSEC updated. - */ - for (t = ISC_LIST_HEAD(diffnames.tuples); - t != NULL; - t = ISC_LIST_NEXT(t, link)) - { - isc_boolean_t existed, exists; - dns_fixedname_t fixedname; - dns_name_t *prevname; - - dns_fixedname_init(&fixedname); - prevname = dns_fixedname_name(&fixedname); - - CHECK(name_exists(db, oldver, &t->name, &existed)); - CHECK(name_exists(db, newver, &t->name, &exists)); - if (exists == existed) - continue; - - /* - * Find the predecessor. - * When names become obscured or unobscured in this update - * transaction, we may find the wrong predecessor because - * the NSECs have not yet been updated to reflect the delegation - * change. This should not matter because in this case, - * the correct predecessor is either the delegation node or - * a newly unobscured node, and those nodes are on the - * "affected" list in any case. - */ - CHECK(next_active(client, zone, db, newver, - &t->name, prevname, ISC_FALSE)); - CHECK(namelist_append_name(&affected, prevname)); - } - - /* - * Find names potentially affected by delegation changes - * (obscured by adding an NS or DNAME, or unobscured by - * removing one). - */ - for (t = ISC_LIST_HEAD(diffnames.tuples); - t != NULL; - t = ISC_LIST_NEXT(t, link)) - { - isc_boolean_t ns_existed, dname_existed; - isc_boolean_t ns_exists, dname_exists; - - CHECK(rrset_exists(db, oldver, &t->name, dns_rdatatype_ns, 0, - &ns_existed)); - CHECK(rrset_exists(db, oldver, &t->name, dns_rdatatype_dname, 0, - &dname_existed)); - CHECK(rrset_exists(db, newver, &t->name, dns_rdatatype_ns, 0, - &ns_exists)); - CHECK(rrset_exists(db, newver, &t->name, dns_rdatatype_dname, 0, - &dname_exists)); - if ((ns_exists || dname_exists) == (ns_existed || dname_existed)) - continue; - /* - * There was a delegation change. Mark all subdomains - * of t->name as potentially needing a NSEC update. - */ - CHECK(namelist_append_subdomain(db, &t->name, &affected)); - } - - ISC_LIST_APPENDLIST(affected.tuples, diffnames.tuples, link); - INSIST(ISC_LIST_EMPTY(diffnames.tuples)); - - CHECK(uniqify_name_list(&affected)); - - /* - * Determine which names should have NSECs, and delete/create - * NSECs to make it so. We don't know the final NSEC targets yet, - * so we just create placeholder NSECs with arbitrary contents - * to indicate that their respective owner names should be part of - * the NSEC chain. - */ - for (t = ISC_LIST_HEAD(affected.tuples); - t != NULL; - t = ISC_LIST_NEXT(t, link)) - { - isc_boolean_t exists; - dns_name_t *name = &t->name; - - CHECK(name_exists(db, newver, name, &exists)); - if (! exists) - continue; - CHECK(is_active(db, newver, name, &flag, &cut, NULL)); - if (!flag) { - /* - * This name is obscured. Delete any - * existing NSEC record. - */ - CHECK(delete_if(true_p, db, newver, name, - dns_rdatatype_nsec, 0, - NULL, &nsec_diff)); - CHECK(delete_if(rrsig_p, db, newver, name, - dns_rdatatype_any, 0, NULL, diff)); - } else { - /* - * This name is not obscured. It needs to have a - * NSEC unless it is the at the origin, in which - * case it should already exist if there is a complete - * NSEC chain and if there isn't a complete NSEC chain - * we don't want to add one as that would signal that - * there is a complete NSEC chain. - */ - if (!dns_name_equal(name, dns_db_origin(db))) { - CHECK(rrset_exists(db, newver, name, - dns_rdatatype_nsec, 0, - &flag)); - if (!flag) - CHECK(add_placeholder_nsec(db, newver, - name, diff)); - } - CHECK(add_exposed_sigs(client, zone, db, newver, name, - cut, &sig_diff, zone_keys, nkeys, - inception, expire, check_ksk, - keyset_kskonly)); - } - } - - /* - * Now we know which names are part of the NSEC chain. - * Make them all point at their correct targets. - */ - for (t = ISC_LIST_HEAD(affected.tuples); - t != NULL; - t = ISC_LIST_NEXT(t, link)) - { - CHECK(rrset_exists(db, newver, &t->name, - dns_rdatatype_nsec, 0, &flag)); - if (flag) { - /* - * There is a NSEC, but we don't know if it is correct. - * Delete it and create a correct one to be sure. - * If the update was unnecessary, the diff minimization - * will take care of eliminating it from the journal, - * IXFRs, etc. - * - * The RRSIG bit should always be set in the NSECs - * we generate, because they will all get RRSIG NSECs. - * (XXX what if the zone keys are missing?). - * Because the RRSIG NSECs have not necessarily been - * created yet, the correctness of the bit mask relies - * on the assumption that NSECs are only created if - * there is other data, and if there is other data, - * there are other RRSIGs. - */ - CHECK(add_nsec(client, zone, db, newver, &t->name, - nsecttl, &nsec_diff)); - } - } - - /* - * Minimize the set of NSEC updates so that we don't - * have to regenerate the RRSIG NSECs for NSECs that were - * replaced with identical ones. - */ - while ((t = ISC_LIST_HEAD(nsec_diff.tuples)) != NULL) { - ISC_LIST_UNLINK(nsec_diff.tuples, t, link); - dns_diff_appendminimal(&nsec_mindiff, &t); - } - - update_log(client, zone, ISC_LOG_DEBUG(3), - "signing rebuilt NSEC chain"); - - /* Update RRSIG NSECs. */ - for (t = ISC_LIST_HEAD(nsec_mindiff.tuples); - t != NULL; - t = ISC_LIST_NEXT(t, link)) - { - if (t->op == DNS_DIFFOP_DEL) { - CHECK(delete_if(true_p, db, newver, &t->name, - dns_rdatatype_rrsig, dns_rdatatype_nsec, - NULL, &sig_diff)); - } else if (t->op == DNS_DIFFOP_ADD) { - CHECK(add_sigs(client, zone, db, newver, &t->name, - dns_rdatatype_nsec, &sig_diff, - zone_keys, nkeys, inception, expire, - check_ksk, keyset_kskonly)); - } else { - INSIST(0); - } - } - - update_nsec3: - - /* Record our changes for the journal. */ - while ((t = ISC_LIST_HEAD(sig_diff.tuples)) != NULL) { - ISC_LIST_UNLINK(sig_diff.tuples, t, link); - dns_diff_appendminimal(diff, &t); - } - while ((t = ISC_LIST_HEAD(nsec_mindiff.tuples)) != NULL) { - ISC_LIST_UNLINK(nsec_mindiff.tuples, t, link); - dns_diff_appendminimal(diff, &t); - } - - INSIST(ISC_LIST_EMPTY(sig_diff.tuples)); - INSIST(ISC_LIST_EMPTY(nsec_diff.tuples)); - INSIST(ISC_LIST_EMPTY(nsec_mindiff.tuples)); - - if (!build_nsec3) { - update_log(client, zone, ISC_LOG_DEBUG(3), - "no NSEC3 chains to rebuild"); - goto failure; - } - - update_log(client, zone, ISC_LOG_DEBUG(3), "rebuilding NSEC3 chains"); - - dns_diff_clear(&diffnames); - dns_diff_clear(&affected); - - CHECK(dns_diff_sort(diff, temp_order)); - - /* - * Find names potentially affected by delegation changes - * (obscured by adding an NS or DNAME, or unobscured by - * removing one). - */ - t = ISC_LIST_HEAD(diff->tuples); - while (t != NULL) { - dns_name_t *name = &t->name; - - isc_boolean_t ns_existed, dname_existed; - isc_boolean_t ns_exists, dname_exists; - isc_boolean_t exists, existed; - - if (t->rdata.type == dns_rdatatype_nsec || - t->rdata.type == dns_rdatatype_rrsig) { - t = ISC_LIST_NEXT(t, link); - continue; - } - - CHECK(namelist_append_name(&affected, name)); - - CHECK(rrset_exists(db, oldver, name, dns_rdatatype_ns, 0, - &ns_existed)); - CHECK(rrset_exists(db, oldver, name, dns_rdatatype_dname, 0, - &dname_existed)); - CHECK(rrset_exists(db, newver, name, dns_rdatatype_ns, 0, - &ns_exists)); - CHECK(rrset_exists(db, newver, name, dns_rdatatype_dname, 0, - &dname_exists)); - - exists = ns_exists || dname_exists; - existed = ns_existed || dname_existed; - if (exists == existed) - goto nextname; - /* - * There was a delegation change. Mark all subdomains - * of t->name as potentially needing a NSEC3 update. - */ - CHECK(namelist_append_subdomain(db, name, &affected)); - - nextname: - while (t != NULL && dns_name_equal(&t->name, name)) - t = ISC_LIST_NEXT(t, link); - } - - for (t = ISC_LIST_HEAD(affected.tuples); - t != NULL; - t = ISC_LIST_NEXT(t, link)) { - dns_name_t *name = &t->name; - - unsecure = ISC_FALSE; /* Silence compiler warning. */ - CHECK(is_active(db, newver, name, &flag, &cut, &unsecure)); - - if (!flag) { - CHECK(delete_if(rrsig_p, db, newver, name, - dns_rdatatype_any, 0, NULL, diff)); - CHECK(dns_nsec3_delnsec3sx(db, newver, name, - privatetype, &nsec_diff)); - } else { - CHECK(add_exposed_sigs(client, zone, db, newver, name, - cut, &sig_diff, zone_keys, nkeys, - inception, expire, check_ksk, - keyset_kskonly)); - CHECK(dns_nsec3_addnsec3sx(db, newver, name, nsecttl, - unsecure, privatetype, - &nsec_diff)); - } - } - - /* - * Minimize the set of NSEC3 updates so that we don't - * have to regenerate the RRSIG NSEC3s for NSEC3s that were - * replaced with identical ones. - */ - while ((t = ISC_LIST_HEAD(nsec_diff.tuples)) != NULL) { - ISC_LIST_UNLINK(nsec_diff.tuples, t, link); - dns_diff_appendminimal(&nsec_mindiff, &t); - } - - update_log(client, zone, ISC_LOG_DEBUG(3), - "signing rebuilt NSEC3 chain"); - - /* Update RRSIG NSEC3s. */ - for (t = ISC_LIST_HEAD(nsec_mindiff.tuples); - t != NULL; - t = ISC_LIST_NEXT(t, link)) - { - if (t->op == DNS_DIFFOP_DEL) { - CHECK(delete_if(true_p, db, newver, &t->name, - dns_rdatatype_rrsig, - dns_rdatatype_nsec3, - NULL, &sig_diff)); - } else if (t->op == DNS_DIFFOP_ADD) { - CHECK(add_sigs(client, zone, db, newver, &t->name, - dns_rdatatype_nsec3, - &sig_diff, zone_keys, nkeys, - inception, expire, check_ksk, - keyset_kskonly)); - } else { - INSIST(0); - } - } - - /* Record our changes for the journal. */ - while ((t = ISC_LIST_HEAD(sig_diff.tuples)) != NULL) { - ISC_LIST_UNLINK(sig_diff.tuples, t, link); - dns_diff_appendminimal(diff, &t); - } - while ((t = ISC_LIST_HEAD(nsec_mindiff.tuples)) != NULL) { - ISC_LIST_UNLINK(nsec_mindiff.tuples, t, link); - dns_diff_appendminimal(diff, &t); - } - - INSIST(ISC_LIST_EMPTY(sig_diff.tuples)); - INSIST(ISC_LIST_EMPTY(nsec_diff.tuples)); - INSIST(ISC_LIST_EMPTY(nsec_mindiff.tuples)); - - failure: - dns_diff_clear(&sig_diff); - dns_diff_clear(&nsec_diff); - dns_diff_clear(&nsec_mindiff); - - dns_diff_clear(&affected); - dns_diff_clear(&diffnames); - - for (i = 0; i < nkeys; i++) - dst_key_free(&zone_keys[i]); - - return (result); -} - - -/**************************************************************************/ /*% * The actual update code in all its glory. We try to follow * the RFC2136 pseudocode as closely as possible. @@ -2686,7 +1515,7 @@ ns_update_start(ns_client_t *client, isc_result_t sigresult) { isc_result_t result; dns_name_t *zonename; dns_rdataset_t *zone_rdataset; - dns_zone_t *zone = NULL; + dns_zone_t *zone = NULL, *raw = NULL; /* * Interpret the zone section. @@ -2720,6 +1549,17 @@ ns_update_start(ns_client_t *client, isc_result_t sigresult) { if (result != ISC_R_SUCCESS) FAILC(DNS_R_NOTAUTH, "not authoritative for update zone"); + /* + * If there is a raw (unsigned) zone associated with this + * zone then it processes the UPDATE request. + */ + dns_zone_getraw(zone, &raw); + if (raw != NULL) { + dns_zone_detach(&zone); + dns_zone_attach(raw, &zone); + dns_zone_detach(&raw); + } + switch(dns_zone_gettype(zone)) { case dns_zone_master: case dns_zone_dlz: @@ -3066,8 +1906,19 @@ check_dnssec(ns_client_t *client, dns_zone_t *zone, dns_db_t *db, } /* Check existing DB for NSEC-only DNSKEY */ - if (!nseconly) - CHECK(dns_nsec_nseconly(db, ver, &nseconly)); + if (!nseconly) { + result = dns_nsec_nseconly(db, ver, &nseconly); + + /* + * An NSEC3PARAM update can proceed without a DNSKEY (it + * will trigger a delayed change), so we can ignore + * ISC_R_NOTFOUND here. + */ + if (result == ISC_R_NOTFOUND) + result = ISC_R_SUCCESS; + + CHECK(result); + } /* Check existing DB for NSEC3 */ if (!nsec3) @@ -3238,9 +2089,11 @@ add_nsec3param_records(ns_client_t *client, dns_zone_t *zone, dns_db_t *db, ttl_good = ISC_TRUE; } if (tuple->op == DNS_DIFFOP_ADD) { + isc_boolean_t nseconly = ISC_FALSE; + /* * Look for any deletes which match this ADD ignoring - * OPTOUT. We don't need to explictly remove them as + * flags. We don't need to explictly remove them as * they will be removed a side effect of processing * the add. */ @@ -3262,12 +2115,28 @@ add_nsec3param_records(ns_client_t *client, dns_zone_t *zone, dns_db_t *db, ISC_LIST_APPEND(diff->tuples, next, link); next = ISC_LIST_HEAD(temp_diff.tuples); } + /* - * See if we already have a CREATE request in progress. + * Create a private-type record to signal that + * we want a delayed NSEC3 chain add/delete */ dns_nsec3param_toprivate(&tuple->rdata, &rdata, privatetype, buf, sizeof(buf)); buf[2] |= DNS_NSEC3FLAG_CREATE; + + /* + * If the zone is not currently capable of + * supporting an NSEC3 chain, then we set the + * INITIAL flag to indicate that these parameters + * are to be used later. + */ + result = dns_nsec_nseconly(db, ver, &nseconly); + if (result == ISC_R_NOTFOUND || nseconly) + buf[2] |= DNS_NSEC3FLAG_INITIAL; + + /* + * See if this CREATE request already exists. + */ CHECK(rr_exists(db, ver, name, &rdata, &flag)); if (!flag) { @@ -3379,7 +2248,7 @@ rollback_private(dns_db_t *db, dns_rdatatype_t privatetype, /* * Allow records which indicate that a zone has been - * signed with a DNSKEY to be be removed. + * signed with a DNSKEY to be removed. */ if (tuple->op == DNS_DIFFOP_DEL && tuple->rdata.length == 5 && @@ -4157,7 +3026,8 @@ update_action(isc_task_t *task, isc_event_t *event) { * changed as a result of an update operation. */ if (! soa_serial_changed) { - CHECK(increment_soa_serial(db, ver, &diff, mctx)); + CHECK(update_soa_serial(db, ver, &diff, mctx, + dns_zone_getserialupdatemethod(zone))); } CHECK(check_mx(client, zone, db, ver, &diff)); @@ -4191,7 +3061,7 @@ update_action(isc_task_t *task, isc_event_t *event) { CHECK(add_nsec3param_records(client, zone, db, ver, &diff)); - if (!has_dnskey) { + if (had_dnskey && !has_dnskey) { /* * We are transitioning from secure to insecure. * Cause all NSEC3 chains to be deleted. When the @@ -4199,12 +3069,17 @@ update_action(isc_task_t *task, isc_event_t *event) { * remove any NSEC chain present will also be removed. */ CHECK(dns_nsec3param_deletechains(db, ver, zone, - &diff)); + ISC_TRUE, &diff)); } else if (has_dnskey && isdnssec(db, ver, privatetype)) { isc_uint32_t interval; + dns_update_log_t log; + interval = dns_zone_getsigvalidityinterval(zone); - result = update_signatures(client, zone, db, oldver, - ver, &diff, interval); + log.func = update_log_cb; + log.arg = client; + result = dns_update_signatures(&log, zone, db, oldver, + ver, &diff, interval); + if (result != ISC_R_SUCCESS) { update_log(client, zone, ISC_LOG_ERROR, @@ -4221,7 +3096,7 @@ update_action(isc_task_t *task, isc_event_t *event) { journal = NULL; result = dns_journal_open(mctx, journalfile, - ISC_TRUE, &journal); + DNS_JOURNAL_CREATE, &journal); if (result != ISC_R_SUCCESS) FAILS(result, "journal open failed"); diff --git a/contrib/bind9/bin/named/xfrout.c b/contrib/bind9/bin/named/xfrout.c index 036350009da6..a0a617d14c12 100644 --- a/contrib/bind9/bin/named/xfrout.c +++ b/contrib/bind9/bin/named/xfrout.c @@ -1,5 +1,5 @@ /* - * Copyright (C) 2004-2011, 2013 Internet Systems Consortium, Inc. ("ISC") + * Copyright (C) 2004-2013 Internet Systems Consortium, Inc. ("ISC") * Copyright (C) 1999-2003 Internet Software Consortium. * * Permission to use, copy, modify, and/or distribute this software for any @@ -15,7 +15,7 @@ * PERFORMANCE OF THIS SOFTWARE. */ -/* $Id: xfrout.c,v 1.139.16.4 2011/12/01 01:00:50 marka Exp $ */ +/* $Id$ */ #include <config.h> @@ -247,12 +247,13 @@ ixfr_rrstream_create(isc_mem_t *mctx, s = isc_mem_get(mctx, sizeof(*s)); if (s == NULL) return (ISC_R_NOMEMORY); - s->common.mctx = mctx; + s->common.mctx = NULL; + isc_mem_attach(mctx, &s->common.mctx); s->common.methods = &ixfr_rrstream_methods; s->journal = NULL; CHECK(dns_journal_open(mctx, journal_filename, - ISC_FALSE, &s->journal)); + DNS_JOURNAL_READ, &s->journal)); CHECK(dns_journal_iter_init(s->journal, begin_serial, end_serial)); *sp = (rrstream_t *) s; @@ -289,7 +290,7 @@ ixfr_rrstream_destroy(rrstream_t **rsp) { ixfr_rrstream_t *s = (ixfr_rrstream_t *) *rsp; if (s->journal != 0) dns_journal_destroy(&s->journal); - isc_mem_put(s->common.mctx, s, sizeof(*s)); + isc_mem_putanddetach(&s->common.mctx, s, sizeof(*s)); } static rrstream_methods_t ixfr_rrstream_methods = { @@ -335,7 +336,8 @@ axfr_rrstream_create(isc_mem_t *mctx, dns_db_t *db, dns_dbversion_t *ver, s = isc_mem_get(mctx, sizeof(*s)); if (s == NULL) return (ISC_R_NOMEMORY); - s->common.mctx = mctx; + s->common.mctx = NULL; + isc_mem_attach(mctx, &s->common.mctx); s->common.methods = &axfr_rrstream_methods; s->it_valid = ISC_FALSE; @@ -413,7 +415,7 @@ axfr_rrstream_destroy(rrstream_t **rsp) { axfr_rrstream_t *s = (axfr_rrstream_t *) *rsp; if (s->it_valid) dns_rriterator_destroy(&s->it); - isc_mem_put(s->common.mctx, s, sizeof(*s)); + isc_mem_putanddetach(&s->common.mctx, s, sizeof(*s)); } static rrstream_methods_t axfr_rrstream_methods = { @@ -455,7 +457,8 @@ soa_rrstream_create(isc_mem_t *mctx, dns_db_t *db, dns_dbversion_t *ver, s = isc_mem_get(mctx, sizeof(*s)); if (s == NULL) return (ISC_R_NOMEMORY); - s->common.mctx = mctx; + s->common.mctx = NULL; + isc_mem_attach(mctx, &s->common.mctx); s->common.methods = &soa_rrstream_methods; s->soa_tuple = NULL; @@ -497,7 +500,7 @@ soa_rrstream_destroy(rrstream_t **rsp) { soa_rrstream_t *s = (soa_rrstream_t *) *rsp; if (s->soa_tuple != NULL) dns_difftuple_free(&s->soa_tuple); - isc_mem_put(s->common.mctx, s, sizeof(*s)); + isc_mem_putanddetach(&s->common.mctx, s, sizeof(*s)); } static rrstream_methods_t soa_rrstream_methods = { @@ -561,7 +564,8 @@ compound_rrstream_create(isc_mem_t *mctx, rrstream_t **soa_stream, s = isc_mem_get(mctx, sizeof(*s)); if (s == NULL) return (ISC_R_NOMEMORY); - s->common.mctx = mctx; + s->common.mctx = NULL; + isc_mem_attach(mctx, &s->common.mctx); s->common.methods = &compound_rrstream_methods; s->components[0] = *soa_stream; s->components[1] = *data_stream; @@ -634,7 +638,7 @@ compound_rrstream_destroy(rrstream_t **rsp) { s->components[0]->methods->destroy(&s->components[0]); s->components[1]->methods->destroy(&s->components[1]); s->components[2] = NULL; /* Copy of components[0]. */ - isc_mem_put(s->common.mctx, s, sizeof(*s)); + isc_mem_putanddetach(&s->common.mctx, s, sizeof(*s)); } static rrstream_methods_t compound_rrstream_methods = { diff --git a/contrib/bind9/bin/named/zoneconf.c b/contrib/bind9/bin/named/zoneconf.c index 404c238f02a4..7f36b143d4e5 100644 --- a/contrib/bind9/bin/named/zoneconf.c +++ b/contrib/bind9/bin/named/zoneconf.c @@ -15,7 +15,7 @@ * PERFORMANCE OF THIS SOFTWARE. */ -/* $Id: zoneconf.c,v 1.170.14.7 2012/01/31 23:46:39 tbox Exp $ */ +/* $Id$ */ /*% */ @@ -792,7 +792,7 @@ checknames(dns_zonetype_t ztype, const cfg_obj_t **maps, isc_result_t ns_zone_configure(const cfg_obj_t *config, const cfg_obj_t *vconfig, const cfg_obj_t *zconfig, cfg_aclconfctx_t *ac, - dns_zone_t *zone) + dns_zone_t *zone, dns_zone_t *raw) { isc_result_t result; const char *zname; @@ -824,8 +824,12 @@ ns_zone_configure(const cfg_obj_t *config, const cfg_obj_t *vconfig, isc_boolean_t ixfrdiff; dns_masterformat_t masterformat; isc_stats_t *zoneqrystats; - isc_boolean_t zonestats_on; +#ifdef NEWSTATS + dns_stats_t *rcvquerystats; +#endif + dns_zonestat_level_t statlevel; int seconds; + dns_zone_t *mayberaw = (raw != NULL) ? raw : zone; i = 0; if (zconfig != NULL) { @@ -857,9 +861,16 @@ ns_zone_configure(const cfg_obj_t *config, const cfg_obj_t *vconfig, RETERR(ns_config_getclass(cfg_tuple_get(zconfig, "class"), vclass, &zclass)); dns_zone_setclass(zone, zclass); + if (raw != NULL) + dns_zone_setclass(raw, zclass); ztype = zonetype_fromconfig(zoptions); - dns_zone_settype(zone, ztype); + if (raw != NULL) { + dns_zone_settype(raw, ztype); + dns_zone_settype(zone, dns_zone_master); + } else + dns_zone_settype(zone, ztype); + obj = NULL; result = cfg_map_get(zoptions, "database", &obj); @@ -907,7 +918,10 @@ ns_zone_configure(const cfg_obj_t *config, const cfg_obj_t *vconfig, return (ISC_R_FAILURE); } - masterformat = dns_masterformat_text; + if (ztype == dns_zone_slave) + masterformat = dns_masterformat_raw; + else + masterformat = dns_masterformat_text; obj = NULL; result= ns_config_get(maps, "masterfile-format", &obj); if (result == ISC_R_SUCCESS) { @@ -920,18 +934,40 @@ ns_zone_configure(const cfg_obj_t *config, const cfg_obj_t *vconfig, else INSIST(0); } - RETERR(dns_zone_setfile2(zone, filename, masterformat)); + + if (raw != NULL && filename != NULL) { +#define SIGNED ".signed" + size_t signedlen = strlen(filename) + sizeof(SIGNED); + char *signedname; + + RETERR(dns_zone_setfile2(raw, filename, masterformat)); + signedname = isc_mem_get(mctx, signedlen); + if (signedname == NULL) + return (ISC_R_NOMEMORY); + + (void)snprintf(signedname, signedlen, "%s" SIGNED, filename); + result = dns_zone_setfile2(zone, signedname, + dns_masterformat_raw); + isc_mem_put(mctx, signedname, signedlen); + if (result != ISC_R_SUCCESS) + return (result); + } else + RETERR(dns_zone_setfile2(zone, filename, masterformat)); obj = NULL; result = cfg_map_get(zoptions, "journal", &obj); if (result == ISC_R_SUCCESS) - RETERR(dns_zone_setjournal(zone, cfg_obj_asstring(obj))); + RETERR(dns_zone_setjournal(mayberaw, cfg_obj_asstring(obj))); + /* + * Notify messages are processed by the raw zone if it exists. + */ if (ztype == dns_zone_slave) RETERR(configure_zone_acl(zconfig, vconfig, config, - allow_notify, ac, zone, + allow_notify, ac, mayberaw, dns_zone_setnotifyacl, dns_zone_clearnotifyacl)); + /* * XXXAG This probably does not make sense for stubs. */ @@ -966,27 +1002,63 @@ ns_zone_configure(const cfg_obj_t *config, const cfg_obj_t *vconfig, else INSIST(0); } + if (raw != NULL) + dns_zone_setdialup(raw, dialup); dns_zone_setdialup(zone, dialup); obj = NULL; result = ns_config_get(maps, "zone-statistics", &obj); INSIST(result == ISC_R_SUCCESS && obj != NULL); - zonestats_on = cfg_obj_asboolean(obj); - zoneqrystats = NULL; - if (zonestats_on) { + if (cfg_obj_isboolean(obj)) { + if (cfg_obj_asboolean(obj)) + statlevel = dns_zonestat_full; + else + statlevel = dns_zonestat_terse; /* XXX */ + } else { + const char *levelstr = cfg_obj_asstring(obj); + if (strcasecmp(levelstr, "full") == 0) + statlevel = dns_zonestat_full; + else if (strcasecmp(levelstr, "terse") == 0) + statlevel = dns_zonestat_terse; + else if (strcasecmp(levelstr, "none") == 0) + statlevel = dns_zonestat_none; + else + INSIST(0); + } + dns_zone_setstatlevel(zone, statlevel); + + zoneqrystats = NULL; +#ifdef NEWSTATS + rcvquerystats = NULL; +#endif + if (statlevel == dns_zonestat_full) { RETERR(isc_stats_create(mctx, &zoneqrystats, dns_nsstatscounter_max)); +#ifdef NEWSTATS + RETERR(dns_rdatatypestats_create(mctx, + &rcvquerystats)); +#endif } - dns_zone_setrequeststats(zone, zoneqrystats); + dns_zone_setrequeststats(zone, zoneqrystats ); +#ifdef NEWSTATS + dns_zone_setrcvquerystats(zone, rcvquerystats); +#endif + if (zoneqrystats != NULL) isc_stats_detach(&zoneqrystats); +#ifdef NEWSTATS + if(rcvquerystats != NULL) + dns_stats_detach(&rcvquerystats); +#endif + /* * Configure master functionality. This applies * to primary masters (type "master") and slaves * acting as masters (type "slave"), but not to stubs. */ - if (ztype != dns_zone_stub && ztype != dns_zone_staticstub) { + if (ztype != dns_zone_stub && ztype != dns_zone_staticstub && + ztype != dns_zone_redirect) { obj = NULL; result = ns_config_get(maps, "notify", &obj); INSIST(result == ISC_R_SUCCESS && obj != NULL); @@ -1004,22 +1076,28 @@ ns_zone_configure(const cfg_obj_t *config, const cfg_obj_t *vconfig, else INSIST(0); } + if (raw != NULL) + dns_zone_setnotifytype(raw, dns_notifytype_no); dns_zone_setnotifytype(zone, notifytype); obj = NULL; result = ns_config_get(maps, "also-notify", &obj); if (result == ISC_R_SUCCESS) { - isc_sockaddr_t *addrs = NULL; isc_uint32_t addrcount; - result = ns_config_getiplist(config, obj, 0, mctx, - &addrs, &addrcount); - if (result != ISC_R_SUCCESS) - return (result); - result = dns_zone_setalsonotify(zone, addrs, - addrcount); - ns_config_putiplist(mctx, &addrs, addrcount); - if (result != ISC_R_SUCCESS) - return (result); + addrs = NULL; + keynames = NULL; + RETERR(ns_config_getipandkeylist(config, obj, mctx, + &addrs, &keynames, + &addrcount)); + result = dns_zone_setalsonotifywithkeys(zone, addrs, + keynames, + addrcount); + if (addrcount != 0) + ns_config_putipandkeylist(mctx, &addrs, + &keynames, addrcount); + else + INSIST(addrs == NULL && keynames == NULL); + RETERR(result); } else RETERR(dns_zone_setalsonotify(zone, NULL, 0)); @@ -1059,8 +1137,10 @@ ns_zone_configure(const cfg_obj_t *config, const cfg_obj_t *vconfig, dns_zone_setidleout(zone, cfg_obj_asuint32(obj) * 60); obj = NULL; - result = ns_config_get(maps, "max-journal-size", &obj); + result = ns_config_get(maps, "max-journal-size", &obj); INSIST(result == ISC_R_SUCCESS && obj != NULL); + if (raw != NULL) + dns_zone_setjournalsize(raw, -1); dns_zone_setjournalsize(zone, -1); if (cfg_obj_isstring(obj)) { const char *str = cfg_obj_asstring(obj); @@ -1080,6 +1160,8 @@ ns_zone_configure(const cfg_obj_t *config, const cfg_obj_t *vconfig, } journal_size = (isc_uint32_t)value; } + if (raw != NULL) + dns_zone_setjournalsize(raw, journal_size); dns_zone_setjournalsize(zone, journal_size); obj = NULL; @@ -1095,7 +1177,19 @@ ns_zone_configure(const cfg_obj_t *config, const cfg_obj_t *vconfig, ixfrdiff = ISC_TRUE; else ixfrdiff = ISC_FALSE; - dns_zone_setoption(zone, DNS_ZONEOPT_IXFRFROMDIFFS, ixfrdiff); + if (raw != NULL) { + dns_zone_setoption(raw, DNS_ZONEOPT_IXFRFROMDIFFS, + ISC_TRUE); + dns_zone_setoption(zone, DNS_ZONEOPT_IXFRFROMDIFFS, + ISC_TRUE); + } else + dns_zone_setoption(zone, DNS_ZONEOPT_IXFRFROMDIFFS, + ixfrdiff); + + obj = NULL; + result = ns_config_get(maps, "request-ixfr", &obj); + INSIST(result == ISC_R_SUCCESS); + dns_zone_setrequestixfr(zone, cfg_obj_asboolean(obj)); checknames(ztype, maps, &obj); INSIST(obj != NULL); @@ -1108,8 +1202,21 @@ ns_zone_configure(const cfg_obj_t *config, const cfg_obj_t *vconfig, fail = check = ISC_FALSE; } else INSIST(0); - dns_zone_setoption(zone, DNS_ZONEOPT_CHECKNAMES, check); - dns_zone_setoption(zone, DNS_ZONEOPT_CHECKNAMESFAIL, fail); + if (raw != NULL) { + dns_zone_setoption(raw, DNS_ZONEOPT_CHECKNAMES, + check); + dns_zone_setoption(raw, DNS_ZONEOPT_CHECKNAMESFAIL, + fail); + dns_zone_setoption(zone, DNS_ZONEOPT_CHECKNAMES, + ISC_FALSE); + dns_zone_setoption(zone, DNS_ZONEOPT_CHECKNAMESFAIL, + ISC_FALSE); + } else { + dns_zone_setoption(zone, DNS_ZONEOPT_CHECKNAMES, + check); + dns_zone_setoption(zone, DNS_ZONEOPT_CHECKNAMESFAIL, + fail); + } obj = NULL; result = ns_config_get(maps, "notify-delay", &obj); @@ -1143,6 +1250,32 @@ ns_zone_configure(const cfg_obj_t *config, const cfg_obj_t *vconfig, INSIST(result == ISC_R_SUCCESS && obj != NULL); dns_zone_setoption(zone, DNS_ZONEOPT_NSEC3TESTZONE, cfg_obj_asboolean(obj)); + } else if (ztype == dns_zone_redirect) { + dns_zone_setnotifytype(zone, dns_notifytype_no); + + obj = NULL; + result = ns_config_get(maps, "max-journal-size", &obj); + INSIST(result == ISC_R_SUCCESS && obj != NULL); + dns_zone_setjournalsize(zone, -1); + if (cfg_obj_isstring(obj)) { + const char *str = cfg_obj_asstring(obj); + INSIST(strcasecmp(str, "unlimited") == 0); + journal_size = ISC_UINT32_MAX / 2; + } else { + isc_resourcevalue_t value; + value = cfg_obj_asuint64(obj); + if (value > ISC_UINT32_MAX / 2) { + cfg_obj_log(obj, ns_g_lctx, + ISC_LOG_ERROR, + "'max-journal-size " + "%" ISC_PRINT_QUADFORMAT "d' " + "is too large", + value); + RETERR(ISC_R_RANGE); + } + journal_size = (isc_uint32_t)value; + } + dns_zone_setjournalsize(zone, journal_size); } /* @@ -1153,11 +1286,11 @@ ns_zone_configure(const cfg_obj_t *config, const cfg_obj_t *vconfig, dns_acl_t *updateacl; RETERR(configure_zone_acl(zconfig, vconfig, config, - allow_update, ac, zone, + allow_update, ac, mayberaw, dns_zone_setupdateacl, dns_zone_clearupdateacl)); - updateacl = dns_zone_getupdateacl(zone); + updateacl = dns_zone_getupdateacl(mayberaw); if (updateacl != NULL && dns_acl_isinsecure(updateacl)) isc_log_write(ns_g_lctx, DNS_LOGCATEGORY_SECURITY, NS_LOGMODULE_SERVER, ISC_LOG_WARNING, @@ -1165,7 +1298,11 @@ ns_zone_configure(const cfg_obj_t *config, const cfg_obj_t *vconfig, "address, which is insecure", zname); - RETERR(configure_zone_ssutable(zoptions, zone, zname)); + RETERR(configure_zone_ssutable(zoptions, mayberaw, zname)); + } + + if (ztype == dns_zone_master || raw != NULL) { + isc_boolean_t allow = ISC_FALSE, maint = ISC_FALSE; obj = NULL; result = ns_config_get(maps, "sig-validity-interval", &obj); @@ -1224,10 +1361,34 @@ ns_zone_configure(const cfg_obj_t *config, const cfg_obj_t *vconfig, INSIST(result == ISC_R_SUCCESS && obj != NULL); dns_zone_setoption(zone, DNS_ZONEOPT_DNSKEYKSKONLY, cfg_obj_asboolean(obj)); - } else if (ztype == dns_zone_slave) { + + obj = NULL; + result = ns_config_get(maps, "dnssec-loadkeys-interval", &obj); + INSIST(result == ISC_R_SUCCESS && obj != NULL); + RETERR(dns_zone_setrefreshkeyinterval(zone, + cfg_obj_asuint32(obj))); + + obj = NULL; + result = cfg_map_get(zoptions, "auto-dnssec", &obj); + if (result == ISC_R_SUCCESS) { + const char *arg = cfg_obj_asstring(obj); + if (strcasecmp(arg, "allow") == 0) + allow = ISC_TRUE; + else if (strcasecmp(arg, "maintain") == 0) + allow = maint = ISC_TRUE; + else if (strcasecmp(arg, "off") == 0) + ; + else + INSIST(0); + dns_zone_setkeyopt(zone, DNS_ZONEKEY_ALLOW, allow); + dns_zone_setkeyopt(zone, DNS_ZONEKEY_MAINTAIN, maint); + } + } + + if (ztype == dns_zone_slave) { RETERR(configure_zone_acl(zconfig, vconfig, config, - allow_update_forwarding, ac, zone, - dns_zone_setforwardacl, + allow_update_forwarding, ac, + mayberaw, dns_zone_setforwardacl, dns_zone_clearforwardacl)); } @@ -1235,15 +1396,13 @@ ns_zone_configure(const cfg_obj_t *config, const cfg_obj_t *vconfig, * Primary master functionality. */ if (ztype == dns_zone_master) { - isc_boolean_t allow = ISC_FALSE, maint = ISC_FALSE; - obj = NULL; result = ns_config_get(maps, "check-wildcard", &obj); if (result == ISC_R_SUCCESS) check = cfg_obj_asboolean(obj); else check = ISC_FALSE; - dns_zone_setoption(zone, DNS_ZONEOPT_CHECKWILDCARD, check); + dns_zone_setoption(mayberaw, DNS_ZONEOPT_CHECKWILDCARD, check); obj = NULL; result = ns_config_get(maps, "check-dup-records", &obj); @@ -1257,8 +1416,8 @@ ns_zone_configure(const cfg_obj_t *config, const cfg_obj_t *vconfig, fail = check = ISC_FALSE; } else INSIST(0); - dns_zone_setoption(zone, DNS_ZONEOPT_CHECKDUPRR, check); - dns_zone_setoption(zone, DNS_ZONEOPT_CHECKDUPRRFAIL, fail); + dns_zone_setoption(mayberaw, DNS_ZONEOPT_CHECKDUPRR, check); + dns_zone_setoption(mayberaw, DNS_ZONEOPT_CHECKDUPRRFAIL, fail); obj = NULL; result = ns_config_get(maps, "check-mx", &obj); @@ -1272,13 +1431,13 @@ ns_zone_configure(const cfg_obj_t *config, const cfg_obj_t *vconfig, fail = check = ISC_FALSE; } else INSIST(0); - dns_zone_setoption(zone, DNS_ZONEOPT_CHECKMX, check); - dns_zone_setoption(zone, DNS_ZONEOPT_CHECKMXFAIL, fail); + dns_zone_setoption(mayberaw, DNS_ZONEOPT_CHECKMX, check); + dns_zone_setoption(mayberaw, DNS_ZONEOPT_CHECKMXFAIL, fail); obj = NULL; result = ns_config_get(maps, "check-integrity", &obj); INSIST(result == ISC_R_SUCCESS && obj != NULL); - dns_zone_setoption(zone, DNS_ZONEOPT_CHECKINTEGRITY, + dns_zone_setoption(mayberaw, DNS_ZONEOPT_CHECKINTEGRITY, cfg_obj_asboolean(obj)); obj = NULL; @@ -1293,8 +1452,8 @@ ns_zone_configure(const cfg_obj_t *config, const cfg_obj_t *vconfig, warn = ignore = ISC_TRUE; } else INSIST(0); - dns_zone_setoption(zone, DNS_ZONEOPT_WARNMXCNAME, warn); - dns_zone_setoption(zone, DNS_ZONEOPT_IGNOREMXCNAME, ignore); + dns_zone_setoption(mayberaw, DNS_ZONEOPT_WARNMXCNAME, warn); + dns_zone_setoption(mayberaw, DNS_ZONEOPT_IGNOREMXCNAME, ignore); obj = NULL; result = ns_config_get(maps, "check-srv-cname", &obj); @@ -1308,30 +1467,38 @@ ns_zone_configure(const cfg_obj_t *config, const cfg_obj_t *vconfig, warn = ignore = ISC_TRUE; } else INSIST(0); - dns_zone_setoption(zone, DNS_ZONEOPT_WARNSRVCNAME, warn); - dns_zone_setoption(zone, DNS_ZONEOPT_IGNORESRVCNAME, ignore); + dns_zone_setoption(mayberaw, DNS_ZONEOPT_WARNSRVCNAME, warn); + dns_zone_setoption(mayberaw, DNS_ZONEOPT_IGNORESRVCNAME, + ignore); obj = NULL; result = ns_config_get(maps, "dnssec-secure-to-insecure", &obj); INSIST(result == ISC_R_SUCCESS && obj != NULL); - dns_zone_setoption(zone, DNS_ZONEOPT_SECURETOINSECURE, + dns_zone_setoption(mayberaw, DNS_ZONEOPT_SECURETOINSECURE, cfg_obj_asboolean(obj)); obj = NULL; - result = cfg_map_get(zoptions, "auto-dnssec", &obj); + result = cfg_map_get(zoptions, "dnssec-update-mode", &obj); if (result == ISC_R_SUCCESS) { const char *arg = cfg_obj_asstring(obj); - if (strcasecmp(arg, "allow") == 0) - allow = ISC_TRUE; + if (strcasecmp(arg, "no-resign") == 0) + dns_zone_setkeyopt(zone, DNS_ZONEKEY_NORESIGN, + ISC_TRUE); else if (strcasecmp(arg, "maintain") == 0) - allow = maint = ISC_TRUE; - else if (strcasecmp(arg, "off") == 0) ; else INSIST(0); - dns_zone_setkeyopt(zone, DNS_ZONEKEY_ALLOW, allow); - dns_zone_setkeyopt(zone, DNS_ZONEKEY_MAINTAIN, maint); } + + obj = NULL; + result = ns_config_get(maps, "serial-update-method", &obj); + INSIST(result == ISC_R_SUCCESS && obj != NULL); + if (strcasecmp(cfg_obj_asstring(obj), "unixtime") == 0) + dns_zone_setserialupdatemethod(zone, + dns_updatemethod_unixtime); + else + dns_zone_setserialupdatemethod(zone, + dns_updatemethod_increment); } /* @@ -1340,6 +1507,7 @@ ns_zone_configure(const cfg_obj_t *config, const cfg_obj_t *vconfig, switch (ztype) { case dns_zone_slave: case dns_zone_stub: + case dns_zone_redirect: count = 0; obj = NULL; (void)cfg_map_get(zoptions, "masters", &obj); @@ -1349,7 +1517,7 @@ ns_zone_configure(const cfg_obj_t *config, const cfg_obj_t *vconfig, RETERR(ns_config_getipandkeylist(config, obj, mctx, &addrs, &keynames, &count)); - result = dns_zone_setmasterswithkeys(zone, addrs, + result = dns_zone_setmasterswithkeys(mayberaw, addrs, keynames, count); if (count != 0) ns_config_putipandkeylist(mctx, &addrs, @@ -1357,7 +1525,7 @@ ns_zone_configure(const cfg_obj_t *config, const cfg_obj_t *vconfig, else INSIST(addrs == NULL && keynames == NULL); } else - result = dns_zone_setmasters(zone, NULL, 0); + result = dns_zone_setmasters(mayberaw, NULL, 0); RETERR(result); multi = ISC_FALSE; @@ -1367,59 +1535,63 @@ ns_zone_configure(const cfg_obj_t *config, const cfg_obj_t *vconfig, INSIST(result == ISC_R_SUCCESS && obj != NULL); multi = cfg_obj_asboolean(obj); } - dns_zone_setoption(zone, DNS_ZONEOPT_MULTIMASTER, multi); + dns_zone_setoption(mayberaw, DNS_ZONEOPT_MULTIMASTER, multi); obj = NULL; result = ns_config_get(maps, "max-transfer-time-in", &obj); INSIST(result == ISC_R_SUCCESS && obj != NULL); - dns_zone_setmaxxfrin(zone, cfg_obj_asuint32(obj) * 60); + dns_zone_setmaxxfrin(mayberaw, cfg_obj_asuint32(obj) * 60); obj = NULL; result = ns_config_get(maps, "max-transfer-idle-in", &obj); INSIST(result == ISC_R_SUCCESS && obj != NULL); - dns_zone_setidlein(zone, cfg_obj_asuint32(obj) * 60); + dns_zone_setidlein(mayberaw, cfg_obj_asuint32(obj) * 60); obj = NULL; result = ns_config_get(maps, "max-refresh-time", &obj); INSIST(result == ISC_R_SUCCESS && obj != NULL); - dns_zone_setmaxrefreshtime(zone, cfg_obj_asuint32(obj)); + dns_zone_setmaxrefreshtime(mayberaw, cfg_obj_asuint32(obj)); obj = NULL; result = ns_config_get(maps, "min-refresh-time", &obj); INSIST(result == ISC_R_SUCCESS && obj != NULL); - dns_zone_setminrefreshtime(zone, cfg_obj_asuint32(obj)); + dns_zone_setminrefreshtime(mayberaw, cfg_obj_asuint32(obj)); obj = NULL; result = ns_config_get(maps, "max-retry-time", &obj); INSIST(result == ISC_R_SUCCESS && obj != NULL); - dns_zone_setmaxretrytime(zone, cfg_obj_asuint32(obj)); + dns_zone_setmaxretrytime(mayberaw, cfg_obj_asuint32(obj)); obj = NULL; result = ns_config_get(maps, "min-retry-time", &obj); INSIST(result == ISC_R_SUCCESS && obj != NULL); - dns_zone_setminretrytime(zone, cfg_obj_asuint32(obj)); + dns_zone_setminretrytime(mayberaw, cfg_obj_asuint32(obj)); obj = NULL; result = ns_config_get(maps, "transfer-source", &obj); INSIST(result == ISC_R_SUCCESS && obj != NULL); - RETERR(dns_zone_setxfrsource4(zone, cfg_obj_assockaddr(obj))); + RETERR(dns_zone_setxfrsource4(mayberaw, + cfg_obj_assockaddr(obj))); ns_add_reserved_dispatch(ns_g_server, cfg_obj_assockaddr(obj)); obj = NULL; result = ns_config_get(maps, "transfer-source-v6", &obj); INSIST(result == ISC_R_SUCCESS && obj != NULL); - RETERR(dns_zone_setxfrsource6(zone, cfg_obj_assockaddr(obj))); + RETERR(dns_zone_setxfrsource6(mayberaw, + cfg_obj_assockaddr(obj))); ns_add_reserved_dispatch(ns_g_server, cfg_obj_assockaddr(obj)); obj = NULL; result = ns_config_get(maps, "alt-transfer-source", &obj); INSIST(result == ISC_R_SUCCESS && obj != NULL); - RETERR(dns_zone_setaltxfrsource4(zone, cfg_obj_assockaddr(obj))); + RETERR(dns_zone_setaltxfrsource4(mayberaw, + cfg_obj_assockaddr(obj))); obj = NULL; result = ns_config_get(maps, "alt-transfer-source-v6", &obj); INSIST(result == ISC_R_SUCCESS && obj != NULL); - RETERR(dns_zone_setaltxfrsource6(zone, cfg_obj_assockaddr(obj))); + RETERR(dns_zone_setaltxfrsource6(mayberaw, + cfg_obj_assockaddr(obj))); obj = NULL; (void)ns_config_get(maps, "use-alt-transfer-source", &obj); @@ -1435,11 +1607,11 @@ ns_zone_configure(const cfg_obj_t *config, const cfg_obj_t *vconfig, alt = ISC_FALSE; } else alt = cfg_obj_asboolean(obj); - dns_zone_setoption(zone, DNS_ZONEOPT_USEALTXFRSRC, alt); + dns_zone_setoption(mayberaw, DNS_ZONEOPT_USEALTXFRSRC, alt); obj = NULL; (void)ns_config_get(maps, "try-tcp-refresh", &obj); - dns_zone_setoption(zone, DNS_ZONEOPT_TRYTCPREFRESH, + dns_zone_setoption(mayberaw, DNS_ZONEOPT_TRYTCPREFRESH, cfg_obj_asboolean(obj)); break; @@ -1472,10 +1644,10 @@ ns_zone_configure_writeable_dlz(dns_dlzdb_t *dlzdatabase, dns_zone_t *zone, dns_zone_settype(zone, dns_zone_dlz); result = dns_sdlz_setdb(dlzdatabase, rdclass, name, &db); if (result != ISC_R_SUCCESS) - return result; + return (result); result = dns_zone_dlzpostload(zone, db); dns_db_detach(&db); - return result; + return (result); } isc_boolean_t @@ -1484,15 +1656,12 @@ ns_zone_reusable(dns_zone_t *zone, const cfg_obj_t *zconfig) { const cfg_obj_t *obj = NULL; const char *cfilename; const char *zfilename; + dns_zone_t *raw = NULL; + isc_boolean_t has_raw; + dns_zonetype_t ztype; zoptions = cfg_tuple_get(zconfig, "options"); - if (zonetype_fromconfig(zoptions) != dns_zone_gettype(zone)) { - dns_zone_log(zone, ISC_LOG_DEBUG(1), - "not reusable: type mismatch"); - return (ISC_FALSE); - } - /* * We always reconfigure a static-stub zone for simplicity, assuming * the amount of data to be loaded is small. @@ -1503,18 +1672,49 @@ ns_zone_reusable(dns_zone_t *zone, const cfg_obj_t *zconfig) { return (ISC_FALSE); } + /* If there's a raw zone, use that for filename and type comparison */ + dns_zone_getraw(zone, &raw); + if (raw != NULL) { + zfilename = dns_zone_getfile(raw); + ztype = dns_zone_gettype(raw); + dns_zone_detach(&raw); + has_raw = ISC_TRUE; + } else { + zfilename = dns_zone_getfile(zone); + ztype = dns_zone_gettype(zone); + has_raw = ISC_FALSE; + } + + obj = NULL; + (void)cfg_map_get(zoptions, "inline-signing", &obj); + if ((obj == NULL || !cfg_obj_asboolean(obj)) && has_raw) { + dns_zone_log(zone, ISC_LOG_DEBUG(1), + "not reusable: old zone was inline-signing"); + return (ISC_FALSE); + } else if ((obj != NULL && cfg_obj_asboolean(obj)) && !has_raw) { + dns_zone_log(zone, ISC_LOG_DEBUG(1), + "not reusable: old zone was not inline-signing"); + return (ISC_FALSE); + } + + if (zonetype_fromconfig(zoptions) != ztype) { + dns_zone_log(zone, ISC_LOG_DEBUG(1), + "not reusable: type mismatch"); + return (ISC_FALSE); + } + obj = NULL; (void)cfg_map_get(zoptions, "file", &obj); if (obj != NULL) cfilename = cfg_obj_asstring(obj); else cfilename = NULL; - zfilename = dns_zone_getfile(zone); if (!((cfilename == NULL && zfilename == NULL) || (cfilename != NULL && zfilename != NULL && - strcmp(cfilename, zfilename) == 0))) { + strcmp(cfilename, zfilename) == 0))) + { dns_zone_log(zone, ISC_LOG_DEBUG(1), - "not reusable: filename mismatch"); + "not reusable: filename mismatch"); return (ISC_FALSE); } |