diff options
Diffstat (limited to 'contrib/bind9/bin/named')
37 files changed, 4379 insertions, 2146 deletions
diff --git a/contrib/bind9/bin/named/Makefile.in b/contrib/bind9/bin/named/Makefile.in index ea919ae5e2da..689413570378 100644 --- a/contrib/bind9/bin/named/Makefile.in +++ b/contrib/bind9/bin/named/Makefile.in @@ -1,4 +1,4 @@ -# Copyright (C) 2004-2012 Internet Systems Consortium, Inc. ("ISC") +# Copyright (C) 2004-2013 Internet Systems Consortium, Inc. ("ISC") # Copyright (C) 1998-2002 Internet Software Consortium. # # Permission to use, copy, modify, and/or distribute this software for any @@ -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@ @@ -21,6 +21,12 @@ top_srcdir = @top_srcdir@ @BIND9_VERSION@ +@BIND9_PRODUCT@ + +@BIND9_DESCRIPTION@ + +@BIND9_SRCID@ + @BIND9_CONFIGARGS@ @BIND9_MAKE_INCLUDES@ @@ -114,6 +120,9 @@ MANOBJS = ${MANPAGES} ${HTMLPAGES} main.@O@: main.c ${LIBTOOL_MODE_COMPILE} ${CC} ${ALL_CFLAGS} \ -DVERSION=\"${VERSION}\" \ + -DPRODUCT=\"${PRODUCT}\" \ + -DDESCRIPTION=\"${DESCRIPTION}\" \ + -DSRCID=\"${SRCID}\" \ -DCONFIGARGS="\"${CONFIGARGS}\"" \ -DNS_LOCALSTATEDIR=\"${localstatedir}\" \ -DNS_SYSCONFDIR=\"${sysconfdir}\" -c ${srcdir}/main.c @@ -124,6 +133,7 @@ bind.keys.h: ${top_srcdir}/bind.keys ${srcdir}/bindkeys.pl config.@O@: config.c bind.keys.h ${LIBTOOL_MODE_COMPILE} ${CC} ${ALL_CFLAGS} \ -DVERSION=\"${VERSION}\" \ + -DSRCID=\"${SRCID}\" \ -DNS_LOCALSTATEDIR=\"${localstatedir}\" \ -DNS_SYSCONFDIR=\"${sysconfdir}\" \ -c ${srcdir}/config.c @@ -151,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} @@ -167,3 +180,6 @@ install:: named@EXEEXT@ lwresd@EXEEXT@ installdirs ${INSTALL_DATA} ${srcdir}/named.conf.5 ${DESTDIR}${mandir}/man5 @DLZ_DRIVER_RULES@ + +named-symtbl.@O@: named-symtbl.c + ${LIBTOOL_MODE_COMPILE} ${CC} ${ALL_CFLAGS} -c named-symtbl.c 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 606cc2d4dad4..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. + */ + 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. */ - ns_client_checkactive(client); + 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); } @@ -1394,10 +1395,9 @@ client_request(isc_task_t *task, isc_event_t *event) { INSIST(client->recursionquota == NULL); - INSIST(client->state == - TCP_CLIENT(client) ? - NS_CLIENTSTATE_READING : - NS_CLIENTSTATE_READY); + INSIST(client->state == (TCP_CLIENT(client) ? + NS_CLIENTSTATE_READING : + NS_CLIENTSTATE_READY)); ns_client_requests++; @@ -1975,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. @@ -1986,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 @@ -2119,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); @@ -2130,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, @@ -2145,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; @@ -2408,10 +2416,11 @@ ns_client_replace(ns_client_t *client) { CTRACE("replace"); - result = ns_clientmgr_createclients(client->manager, - 1, client->interface, - (TCP_CLIENT(client) ? - ISC_TRUE : ISC_FALSE)); + REQUIRE(client != NULL); + REQUIRE(client->manager != NULL); + + result = get_client(client->manager, client->interface, + client->dispatch, TCP_CLIENT(client)); if (result != ISC_R_SUCCESS) return (result); @@ -2435,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"); @@ -2448,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)); } @@ -2471,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++) @@ -2491,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)); @@ -2499,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; @@ -2509,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); @@ -2541,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); } @@ -2700,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 @@ -2794,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 && @@ -2807,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) { @@ -2829,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. @@ -2851,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 9e453ade3bc6..fa349eeade2f 100644 --- a/contrib/bind9/bin/named/config.c +++ b/contrib/bind9/bin/named/config.c @@ -1,5 +1,5 @@ /* - * Copyright (C) 2004-2012 Internet Systems Consortium, Inc. ("ISC") + * Copyright (C) 2004-2013 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: 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\ @@ -150,6 +151,7 @@ options {\n\ check-names response ignore;\n\ check-dup-records warn;\n\ check-mx warn;\n\ + check-spf warn;\n\ acache-enable no;\n\ acache-cleaning-interval 60;\n\ max-acache-size 16M;\n\ @@ -199,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\ @@ -209,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\ " @@ -291,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. */ @@ -304,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); } @@ -377,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); @@ -639,17 +649,16 @@ ns_config_getipandkeylist(const cfg_obj_t *config, const cfg_obj_t *list, if (isc_sockaddr_getport(&addrs[i]) == 0) isc_sockaddr_setport(&addrs[i], port); keys[i] = NULL; - if (!cfg_obj_isstring(key)) { - i++; + i++; /* Increment here so that cleanup on error works. */ + if (!cfg_obj_isstring(key)) continue; - } - keys[i] = isc_mem_get(mctx, sizeof(dns_name_t)); - if (keys[i] == NULL) + keys[i - 1] = isc_mem_get(mctx, sizeof(dns_name_t)); + if (keys[i - 1] == NULL) goto cleanup; - dns_name_init(keys[i], NULL); + dns_name_init(keys[i - 1], NULL); keystr = cfg_obj_asstring(key); - isc_buffer_init(&b, keystr, strlen(keystr)); + isc_buffer_constinit(&b, keystr, strlen(keystr)); isc_buffer_add(&b, strlen(keystr)); dns_fixedname_init(&fname); result = dns_name_fromtext(dns_fixedname_name(&fname), &b, @@ -657,10 +666,9 @@ ns_config_getipandkeylist(const cfg_obj_t *config, const cfg_obj_t *list, if (result != ISC_R_SUCCESS) goto cleanup; result = dns_name_dup(dns_fixedname_name(&fname), mctx, - keys[i]); + keys[i - 1]); if (result != ISC_R_SUCCESS) goto cleanup; - i++; } if (pushed != 0) { pushed--; @@ -716,7 +724,7 @@ ns_config_getipandkeylist(const cfg_obj_t *config, const cfg_obj_t *list, if (addrs != NULL) isc_mem_put(mctx, addrs, addrcount * sizeof(isc_sockaddr_t)); if (keys != NULL) { - for (j = 0; j <= i; j++) { + for (j = 0; j < i; j++) { if (keys[j] == NULL) continue; if (dns_name_dynamic(keys[j])) diff --git a/contrib/bind9/bin/named/control.c b/contrib/bind9/bin/named/control.c index ff084fc7d5a9..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 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 */ @@ -61,7 +61,7 @@ command_compare(const char *text, const char *command) { isc_result_t ns_control_docommand(isccc_sexpr_t *message, isc_buffer_t *text) { isccc_sexpr_t *data; - char *command; + char *command = NULL; isc_result_t result; int log_level; #ifdef HAVE_LIBSCF @@ -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 daf00d04ed65..c46a6e15f467 100644 --- a/contrib/bind9/bin/named/controlconf.c +++ b/contrib/bind9/bin/named/controlconf.c @@ -1,5 +1,5 @@ /* - * Copyright (C) 2004-2008, 2011, 2012 Internet Systems Consortium, Inc. ("ISC") + * Copyright (C) 2004-2008, 2011-2013 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: 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 */ @@ -149,7 +149,7 @@ free_listener(controllistener_t *listener) { if (listener->acl != NULL) dns_acl_detach(&listener->acl); - isc_mem_put(listener->mctx, listener, sizeof(*listener)); + isc_mem_putanddetach(&listener->mctx, listener, sizeof(*listener)); } static void @@ -1066,8 +1066,9 @@ add_listener(ns_controls_t *cp, controllistener_t **listenerp, result = ISC_R_NOMEMORY; if (result == ISC_R_SUCCESS) { + listener->mctx = NULL; + isc_mem_attach(mctx, &listener->mctx); listener->controls = cp; - listener->mctx = mctx; listener->task = cp->server->task; listener->address = *addr; listener->sock = NULL; 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 109d160b456b..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,26 +155,29 @@ 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) -#define NS_CLIENTATTR_TCP 0x01 -#define NS_CLIENTATTR_RA 0x02 /*%< Client gets recursive service */ -#define NS_CLIENTATTR_PKTINFO 0x04 /*%< pktinfo is valid */ -#define NS_CLIENTATTR_MULTICAST 0x08 /*%< recv'd from multicast */ -#define NS_CLIENTATTR_WANTDNSSEC 0x10 /*%< include dnssec records */ -#define NS_CLIENTATTR_WANTNSID 0x20 /*%< include nameserver ID */ +#define NS_CLIENTATTR_TCP 0x001 +#define NS_CLIENTATTR_RA 0x002 /*%< Client gets recursive service */ +#define NS_CLIENTATTR_PKTINFO 0x004 /*%< pktinfo is valid */ +#define NS_CLIENTATTR_MULTICAST 0x008 /*%< recv'd from multicast */ +#define NS_CLIENTATTR_WANTDNSSEC 0x010 /*%< include dnssec records */ +#define NS_CLIENTATTR_WANTNSID 0x020 /*%< include nameserver ID */ #ifdef ALLOW_FILTER_AAAA_ON_V4 -#define NS_CLIENTATTR_FILTER_AAAA 0x40 /*%< suppress AAAAs */ -#define NS_CLIENTATTR_FILTER_AAAA_RC 0x80 /*%< recursing for A against AAAA */ +#define NS_CLIENTATTR_FILTER_AAAA 0x040 /*%< suppress AAAAs */ +#define NS_CLIENTATTR_FILTER_AAAA_RC 0x080 /*%< recursing for A against AAAA */ #endif +#define NS_CLIENTATTR_WANTAD 0x100 /*%< want AD in response if possible */ extern unsigned int ns_client_requests; @@ -378,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 842931677b55..cbc14d8b72d9 100644 --- a/contrib/bind9/bin/named/include/named/globals.h +++ b/contrib/bind9/bin/named/include/named/globals.h @@ -1,5 +1,5 @@ /* - * Copyright (C) 2004-2011 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: 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); @@ -66,6 +67,9 @@ EXTERN isc_timermgr_t * ns_g_timermgr INIT(NULL); EXTERN isc_socketmgr_t * ns_g_socketmgr INIT(NULL); EXTERN cfg_parser_t * ns_g_parser INIT(NULL); EXTERN const char * ns_g_version INIT(VERSION); +EXTERN const char * ns_g_product INIT(PRODUCT); +EXTERN const char * ns_g_description INIT(DESCRIPTION); +EXTERN const char * ns_g_srcid INIT(SRCID); EXTERN const char * ns_g_configargs INIT(CONFIGARGS); EXTERN in_port_t ns_g_port INIT(0); EXTERN in_port_t lwresd_g_listenport INIT(0); @@ -120,6 +124,7 @@ EXTERN isc_boolean_t ns_g_coreok INIT(ISC_TRUE); EXTERN const char * ns_g_chrootdir INIT(NULL); EXTERN isc_boolean_t ns_g_foreground INIT(ISC_FALSE); EXTERN isc_boolean_t ns_g_logstderr INIT(ISC_FALSE); +EXTERN isc_boolean_t ns_g_nosyslog INIT(ISC_FALSE); EXTERN const char * ns_g_defaultsessionkeyfile INIT(NS_LOCALSTATEDIR "/run/named/" @@ -153,6 +158,7 @@ EXTERN isc_boolean_t ns_g_memstatistics INIT(ISC_FALSE); EXTERN isc_boolean_t ns_g_clienttest INIT(ISC_FALSE); EXTERN isc_boolean_t ns_g_nosoa INIT(ISC_FALSE); EXTERN isc_boolean_t ns_g_noaa INIT(ISC_FALSE); +EXTERN isc_boolean_t ns_g_nonearest INIT(ISC_FALSE); #undef EXTERN #undef INIT 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 25aa641ad37e..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 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 @@ -165,7 +165,9 @@ enum { dns_nsstatscounter_updatefail = 34, dns_nsstatscounter_updatebadprereq = 35, - dns_nsstatscounter_max = 36 + dns_nsstatscounter_rpz_rewrites = 36, + + dns_nsstatscounter_max = 37 }; void @@ -228,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.) */ /*% @@ -264,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. @@ -295,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", @@ -334,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 d194d2b877cf..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 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> @@ -79,11 +80,13 @@ ns_interfacemgr_create(isc_mem_t *mctx, isc_taskmgr_t *taskmgr, if (mgr == NULL) return (ISC_R_NOMEMORY); + mgr->mctx = NULL; + isc_mem_attach(mctx, &mgr->mctx); + result = isc_mutex_init(&mgr->lock); if (result != ISC_R_SUCCESS) goto cleanup_mem; - mgr->mctx = mctx; mgr->taskmgr = taskmgr; mgr->socketmgr = socketmgr; mgr->dispatchmgr = dispatchmgr; @@ -115,7 +118,7 @@ ns_interfacemgr_create(isc_mem_t *mctx, isc_taskmgr_t *taskmgr, ns_listenlist_detach(&mgr->listenon4); ns_listenlist_detach(&mgr->listenon6); cleanup_mem: - isc_mem_put(mctx, mgr, sizeof(*mgr)); + isc_mem_putanddetach(&mgr->mctx, mgr, sizeof(*mgr)); return (result); } @@ -128,7 +131,7 @@ ns_interfacemgr_destroy(ns_interfacemgr_t *mgr) { clearlistenon(mgr); DESTROYLOCK(&mgr->lock); mgr->magic = 0; - isc_mem_put(mgr->mctx, mgr, sizeof(*mgr)); + isc_mem_putanddetach(&mgr->mctx, mgr, sizeof(*mgr)); } dns_aclenv_t * @@ -183,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; @@ -210,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 @@ -221,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); @@ -235,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)); @@ -247,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; @@ -258,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__, @@ -277,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); } @@ -396,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/log.c b/contrib/bind9/bin/named/log.c index 5d19dcb205c6..a34dea47ecb7 100644 --- a/contrib/bind9/bin/named/log.c +++ b/contrib/bind9/bin/named/log.c @@ -1,5 +1,5 @@ /* - * Copyright (C) 2004-2007, 2009 Internet Systems Consortium, Inc. ("ISC") + * Copyright (C) 2004-2007, 2009, 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 @@ -201,7 +201,7 @@ isc_result_t ns_log_setdefaultcategory(isc_logconfig_t *lcfg) { isc_result_t result; - if (! ns_g_logstderr) { + if (! ns_g_logstderr && ! ns_g_nosyslog) { result = isc_log_usechannel(lcfg, "default_syslog", ISC_LOGCATEGORY_DEFAULT, NULL); if (result != ISC_R_SUCCESS) diff --git a/contrib/bind9/bin/named/logconf.c b/contrib/bind9/bin/named/logconf.c index 5d17ab0e6016..b99a167d12f1 100644 --- a/contrib/bind9/bin/named/logconf.c +++ b/contrib/bind9/bin/named/logconf.c @@ -1,5 +1,5 @@ /* - * Copyright (C) 2004-2007, 2011 Internet Systems Consortium, Inc. ("ISC") + * Copyright (C) 2004-2007, 2011, 2013 Internet Systems Consortium, Inc. ("ISC") * Copyright (C) 1999-2001 Internet Software Consortium. * * Permission to use, copy, modify, and/or distribute this software for any @@ -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 */ @@ -246,14 +246,16 @@ channel_fromconf(const cfg_obj_t *channel, isc_logconfig_t *lctx) { isc_result_totext(result)); } else (void)isc_stdio_close(fp); - } else { - syslog(LOG_ERR, "isc_file_isplainfile '%s' failed: %s", - dest.file.name, isc_result_totext(result)); - fprintf(stderr, "isc_file_isplainfile '%s' failed: %s", - dest.file.name, isc_result_totext(result)); + goto done; } + if (!ns_g_nosyslog) + syslog(LOG_ERR, "isc_file_isplainfile '%s' failed: %s", + dest.file.name, isc_result_totext(result)); + fprintf(stderr, "isc_file_isplainfile '%s' failed: %s", + dest.file.name, isc_result_totext(result)); } + done: return (result); } diff --git a/contrib/bind9/bin/named/lwresd.c b/contrib/bind9/bin/named/lwresd.c index 11198a4324f2..7ee2196364e9 100644 --- a/contrib/bind9/bin/named/lwresd.c +++ b/contrib/bind9/bin/named/lwresd.c @@ -1,5 +1,5 @@ /* - * Copyright (C) 2004-2009 Internet Systems Consortium, Inc. ("ISC") + * Copyright (C) 2004-2009, 2012 Internet Systems Consortium, Inc. ("ISC") * Copyright (C) 2000-2003 Internet Software Consortium. * * Permission to use, copy, modify, and/or distribute this software for any @@ -368,7 +368,7 @@ ns_lwdmanager_create(isc_mem_t *mctx, const cfg_obj_t *lwres, dns_fixedname_init(&fname); name = dns_fixedname_name(&fname); - isc_buffer_init(&namebuf, searchstr, + isc_buffer_constinit(&namebuf, searchstr, strlen(searchstr)); isc_buffer_add(&namebuf, strlen(searchstr)); result = dns_name_fromtext(name, &namebuf, diff --git a/contrib/bind9/bin/named/main.c b/contrib/bind9/bin/named/main.c index 30c6ef9cac56..a5467249082a 100644 --- a/contrib/bind9/bin/named/main.c +++ b/contrib/bind9/bin/named/main.c @@ -1,5 +1,5 @@ /* - * Copyright (C) 2004-2011 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: 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) @@ -523,18 +523,33 @@ parse_command_line(int argc, char *argv[]) { maxudp = 512; else if (!strcmp(isc_commandline_argument, "maxudp1460")) maxudp = 1460; + else if (!strcmp(isc_commandline_argument, "nosyslog")) + ns_g_nosyslog = ISC_TRUE; + else if (!strcmp(isc_commandline_argument, "nonearest")) + ns_g_nonearest = ISC_TRUE; else 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; case 'v': - printf("BIND %s\n", ns_g_version); + printf("%s %s", ns_g_product, ns_g_version); + if (*ns_g_description != 0) + printf(" %s", ns_g_description); + printf("\n"); exit(0); case 'V': - printf("BIND %s built with %s\n", ns_g_version, + printf("%s %s", ns_g_product, ns_g_version); + if (*ns_g_description != 0) + printf(" %s", ns_g_description); + printf(" <id:%s> built with %s\n", ns_g_srcid, ns_g_configargs); #ifdef OPENSSL printf("using OpenSSL version: %s\n", @@ -585,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__, @@ -787,8 +814,8 @@ setup(void) { isc_result_totext(result)); isc_log_write(ns_g_lctx, NS_LOGCATEGORY_GENERAL, NS_LOGMODULE_MAIN, - ISC_LOG_NOTICE, "starting BIND %s%s", ns_g_version, - saved_command_line); + ISC_LOG_NOTICE, "starting %s %s%s", ns_g_product, + ns_g_version, saved_command_line); isc_log_write(ns_g_lctx, NS_LOGCATEGORY_GENERAL, NS_LOGMODULE_MAIN, ISC_LOG_NOTICE, "built with %s", ns_g_configargs); @@ -1029,9 +1056,9 @@ main(int argc, char *argv[]) { */ strlcat(version, #if defined(NO_VERSION_DATE) || !defined(__DATE__) - "named version: BIND " VERSION, + "named version: BIND " VERSION " <" SRCID ">", #else - "named version: BIND " VERSION " (" __DATE__ ")", + "named version: BIND " VERSION " <" SRCID "> (" __DATE__ ")", #endif sizeof(version)); result = isc_file_progname(*argv, program_name, sizeof(program_name)); 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 4356c192e6b6..8d0122280b8a 100644 --- a/contrib/bind9/bin/named/named.conf.5 +++ b/contrib/bind9/bin/named/named.conf.5 @@ -1,4 +1,4 @@ -.\" Copyright (C) 2004-2011 Internet Systems Consortium, Inc. ("ISC") +.\" Copyright (C) 2004-2011, 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 @@ -187,7 +187,7 @@ options { random\-device \fIquoted_string\fR; recursive\-clients \fIinteger\fR; serial\-query\-rate \fIinteger\fR; - server\-id ( \fIquoted_string\fR | none |; + server\-id ( \fIquoted_string\fR | none ); stacksize \fIsize\fR; statistics\-file \fIquoted_string\fR; statistics\-interval \fIinteger\fR; // not yet implemented @@ -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 | * ) ]; @@ -592,5 +596,5 @@ zone \fIstring\fR \fIoptional_class\fR { \fBrndc\fR(8), BIND 9 Administrator Reference Manual. .SH "COPYRIGHT" -Copyright \(co 2004\-2011 Internet Systems Consortium, Inc. ("ISC") +Copyright \(co 2004\-2011, 2013 Internet Systems Consortium, Inc. ("ISC") .br diff --git a/contrib/bind9/bin/named/named.conf.docbook b/contrib/bind9/bin/named/named.conf.docbook index c6ee1db1ca49..d778706930e0 100644 --- a/contrib/bind9/bin/named/named.conf.docbook +++ b/contrib/bind9/bin/named/named.conf.docbook @@ -2,7 +2,7 @@ "http://www.oasis-open.org/docbook/xml/4.2/docbookx.dtd" [<!ENTITY mdash "—">]> <!-- - - Copyright (C) 2004-2011 Internet Systems Consortium, Inc. ("ISC") + - Copyright (C) 2004-2011, 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 @@ -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> @@ -44,6 +44,7 @@ <year>2009</year> <year>2010</year> <year>2011</year> + <year>2013</year> <holder>Internet Systems Consortium, Inc. ("ISC")</holder> </copyright> </docinfo> @@ -218,7 +219,7 @@ options { random-device <replaceable>quoted_string</replaceable>; recursive-clients <replaceable>integer</replaceable>; serial-query-rate <replaceable>integer</replaceable>; - server-id ( <replaceable>quoted_string</replaceable> | none |; + server-id ( <replaceable>quoted_string</replaceable> | none ); stacksize <replaceable>size</replaceable>; statistics-file <replaceable>quoted_string</replaceable>; statistics-interval <replaceable>integer</replaceable>; // not yet implemented @@ -325,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 ); @@ -512,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 ); @@ -562,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>; @@ -608,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 ); @@ -626,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 71bd94669503..23d9391af3d0 100644 --- a/contrib/bind9/bin/named/named.conf.html +++ b/contrib/bind9/bin/named/named.conf.html @@ -1,5 +1,5 @@ <!-- - - Copyright (C) 2004-2011 Internet Systems Consortium, Inc. ("ISC") + - Copyright (C) 2004-2011, 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 @@ -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="id2543353"></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="id2543381"></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="id2543397"></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="id2543416"></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="id2543462"></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="id2543530"></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="id2543556"></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="id2543585"></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="id2543620"></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="id2543658"></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="id2543700"></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> @@ -184,7 +184,7 @@ options {<br> random-device <em class="replaceable"><code>quoted_string</code></em>;<br> recursive-clients <em class="replaceable"><code>integer</code></em>;<br> serial-query-rate <em class="replaceable"><code>integer</code></em>;<br> - server-id ( <em class="replaceable"><code>quoted_string</code></em> | none |;<br> + server-id ( <em class="replaceable"><code>quoted_string</code></em> | none );<br> stacksize <em class="replaceable"><code>size</code></em>;<br> statistics-file <em class="replaceable"><code>quoted_string</code></em>;<br> statistics-interval <em class="replaceable"><code>integer</code></em>; // not yet implemented<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="id2544574"></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="id2545284"></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="id2545664"></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="id2545675"></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 9e67f2d2187f..5093cb243da4 100644 --- a/contrib/bind9/bin/named/query.c +++ b/contrib/bind9/bin/named/query.c @@ -1,5 +1,5 @@ /* - * Copyright (C) 2004-2012 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: query.c,v 1.353.8.24 2012/02/07 01:14:39 marka Exp $ */ +/* $Id$ */ /*! \file */ @@ -94,6 +94,10 @@ /*% Want DNSSEC? */ #define WANTDNSSEC(c) (((c)->attributes & \ NS_CLIENTATTR_WANTDNSSEC) != 0) +/*% Want WANTAD? */ +#define WANTAD(c) (((c)->attributes & \ + NS_CLIENTATTR_WANTAD) != 0) + /*% No authority? */ #define NOAUTHORITY(c) (((c)->query.attributes & \ NS_QUERYATTR_NOAUTHORITY) != 0) @@ -168,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); } @@ -651,7 +682,7 @@ query_validatezonedb(ns_client_t *client, dns_name_t *name, dns_dbversion_t **versionp) { isc_result_t result; - dns_acl_t *queryacl; + dns_acl_t *queryacl, *queryonacl; ns_dbversion_t *dbversion; REQUIRE(zone != NULL); @@ -763,6 +794,21 @@ query_validatezonedb(ns_client_t *client, dns_name_t *name, client->query.attributes |= NS_QUERYATTR_QUERYOKVALID; } + /* If and only if we've gotten this far, check allow-query-on too */ + if (result == ISC_R_SUCCESS) { + queryonacl = dns_zone_getqueryonacl(zone); + if (queryonacl == NULL) + queryonacl = client->view->queryonacl; + + result = ns_client_checkaclsilent(client, NULL, + queryonacl, ISC_TRUE); + if ((options & DNS_GETDB_NOLOG) == 0 && + result != ISC_R_SUCCESS) + ns_client_log(client, DNS_LOGCATEGORY_SECURITY, + NS_LOGMODULE_QUERY, ISC_LOG_INFO, + "query-on denied"); + } + dbversion->acl_checked = ISC_TRUE; if (result != ISC_R_SUCCESS) { dbversion->queryok = ISC_FALSE; @@ -831,12 +877,29 @@ query_getzonedb(ns_client_t *client, dns_name_t *name, dns_rdatatype_t qtype, } static void -rpz_log_rewrite(ns_client_t *client, const char *disabled, +rpz_log_rewrite(ns_client_t *client, isc_boolean_t disabled, dns_rpz_policy_t policy, dns_rpz_type_t type, - dns_name_t *rpz_qname) { + dns_zone_t *zone, dns_name_t *rpz_qname) +{ + isc_stats_t *zonestats; char qname_buf[DNS_NAME_FORMATSIZE]; char rpz_qname_buf[DNS_NAME_FORMATSIZE]; + /* + * Count enabled rewrites in the global counter. + * Count both enabled and disabled rewrites for each zone. + */ + if (!disabled && policy != DNS_RPZ_POLICY_PASSTHRU) { + isc_stats_increment(ns_g_server->nsstats, + dns_nsstatscounter_rpz_rewrites); + } + if (zone != NULL) { + zonestats = dns_zone_getrequeststats(zone); + if (zonestats != NULL) + isc_stats_increment(zonestats, + dns_nsstatscounter_rpz_rewrites); + } + if (!isc_log_wouldlog(ns_g_lctx, DNS_RPZ_INFO_LEVEL)) return; @@ -845,7 +908,7 @@ rpz_log_rewrite(ns_client_t *client, const char *disabled, ns_client_log(client, DNS_LOGCATEGORY_RPZ, NS_LOGMODULE_QUERY, DNS_RPZ_INFO_LEVEL, "%srpz %s %s rewrite %s via %s", - disabled, + disabled ? "disabled " : "", dns_rpz_type2str(type), dns_rpz_policy2str(policy), qname_buf, rpz_qname_buf); } @@ -861,6 +924,9 @@ rpz_log_fail(ns_client_t *client, int level, if (!isc_log_wouldlog(ns_g_lctx, level)) return; + /* + * bin/tests/system/rpz/tests.sh looks for "rpz.*failed". + */ dns_name_format(client->query.qname, namebuf1, sizeof(namebuf1)); dns_name_format(name, namebuf2, sizeof(namebuf2)); ns_client_log(client, NS_LOGCATEGORY_QUERY_EERRORS, @@ -1141,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); @@ -1165,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. @@ -1209,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)) @@ -1247,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; @@ -1294,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)) @@ -1371,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) { @@ -1422,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) { @@ -1597,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. @@ -1635,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"); @@ -1737,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; @@ -1765,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; @@ -1837,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)) { @@ -2489,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"); /* @@ -2499,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". */ @@ -2532,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; @@ -2542,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) { /* @@ -2609,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"); /* @@ -2620,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. @@ -2652,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) { @@ -2781,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; @@ -2817,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); @@ -2862,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; @@ -2871,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; } @@ -2916,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, @@ -2944,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; @@ -2960,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. */ @@ -2993,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)) { @@ -3075,6 +3178,14 @@ query_addbestns(ns_client_t *client) { goto cleanup; /* + * If the answer is secure only add NS records if they are secure * when the client may be looking for AD in the response. + */ + if (SECURE(client) && (WANTDNSSEC(client) || WANTAD(client)) && + ((rdataset->trust != dns_trust_secure) || + (sigrdataset != NULL && sigrdataset->trust != dns_trust_secure))) + goto cleanup; + + /* * If the client doesn't want DNSSEC we can discard the sigrdataset * now. */ @@ -3265,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; @@ -3272,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. @@ -3331,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); @@ -3354,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. @@ -3857,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) { @@ -3912,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 @@ -3922,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) { @@ -4028,6 +4151,8 @@ rpz_rewrite_rrset(ns_client_t *client, dns_rpz_type_t rpz_type, rdatasetp, resuming); switch (result) { case ISC_R_SUCCESS: + case DNS_R_GLUE: + case DNS_R_ZONECUT: result = rpz_rewrite_ip(client, *rdatasetp, rpz_type); break; case DNS_R_EMPTYNAME: @@ -4120,6 +4245,13 @@ 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) { @@ -4140,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; @@ -4185,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) { @@ -4204,26 +4337,32 @@ rpz_find(ns_client_t *client, dns_rdatatype_t qtype, dns_name_t *qnamef, result = DNS_R_CNAME; } break; + case DNS_R_NXRRSET: + policy = DNS_RPZ_POLICY_NODATA; + break; case DNS_R_DNAME: /* * DNAME policy RRs have very few if any uses that are not * better served with simple wildcards. Making the work would * require complications to get the number of labels matched * in the name or the found name to the main DNS_R_DNAME case - * in query_find(). So fall through to treat them as NODATA. + * in query_find(). + */ + dns_rdataset_disassociate(*rdatasetp); + dns_db_detachnode(*dbp, nodep); + /* + * Fall through to treat it as a miss. */ - case DNS_R_NXRRSET: - policy = DNS_RPZ_POLICY_NODATA; - break; case DNS_R_NXDOMAIN: case DNS_R_EMPTYNAME: /* * If we don't get a qname hit, * see if it is worth looking for other types. */ - dns_db_rpz_enabled(*dbp, client->query.rpz_st); + (void)dns_db_rpz_enabled(*dbp, client->query.rpz_st); dns_db_detach(dbp); dns_zone_detach(zonep); + result = DNS_R_NXDOMAIN; policy = DNS_RPZ_POLICY_MISS; break; default: @@ -4231,9 +4370,7 @@ rpz_find(ns_client_t *client, dns_rdatatype_t qtype, dns_name_t *qnamef, dns_zone_detach(zonep); rpz_log_fail(client, DNS_RPZ_ERROR_LEVEL, rpz_type, qnamef, "", result); - policy = DNS_RPZ_POLICY_ERROR; - result = DNS_R_SERVFAIL; - break; + return (DNS_R_SERVFAIL); } *policyp = policy; @@ -4299,6 +4436,9 @@ rpz_rewrite_name(ns_client_t *client, dns_rdatatype_t qtype, dns_name_t *qname, if (result == ISC_R_SUCCESS) break; INSIST(result == DNS_R_NAMETOOLONG); + /* + * Trim the name until it is not too long. + */ labels = dns_name_countlabels(prefix); if (labels < 2) { rpz_log_fail(client, DNS_RPZ_ERROR_LEVEL, @@ -4322,7 +4462,6 @@ rpz_rewrite_name(ns_client_t *client, dns_rdatatype_t qtype, dns_name_t *qname, rdatasetp, &policy); switch (result) { case DNS_R_NXDOMAIN: - case DNS_R_EMPTYNAME: break; case DNS_R_SERVFAIL: rpz_clean(&zone, &db, &node, rdatasetp); @@ -4345,13 +4484,45 @@ rpz_rewrite_name(ns_client_t *client, dns_rdatatype_t qtype, dns_name_t *qname, (st->m.type == rpz_type && 0 >= dns_name_compare(rpz_qname, st->qname)))) continue; - +#if 0 + /* + * This code would block a customer reported information + * leak of rpz rules by rewriting requests in the + * rpz-ip, rpz-nsip, rpz-nsdname,and rpz-passthru TLDs. + * Without this code, a bad guy could request + * 24.0.3.2.10.rpz-ip. to find the policy rule for + * 10.2.3.0/14. It is an insignificant leak and this + * code is not worth its cost, because the bad guy + * could publish "evil.com A 10.2.3.4" and request + * evil.com to get the same information. + * Keep code with "#if 0" in case customer demand + * is irresistible. + * + * We have the less frequent case of a triggered + * policy. Check that we have not trigger on one + * of the pretend RPZ TLDs. + * This test would make it impossible to rewrite + * names in TLDs that start with "rpz-" should + * ICANN ever allow such TLDs. + */ + labels = dns_name_countlabels(qname); + if (labels >= 2) { + dns_label_t label; + + dns_name_getlabel(qname, labels-2, &label); + if (label.length >= sizeof(DNS_RPZ_PREFIX)-1 && + strncasecmp((const char *)label.base+1, + DNS_RPZ_PREFIX, + sizeof(DNS_RPZ_PREFIX)-1) == 0) + continue; + } +#endif /* * Merely log DNS_RPZ_POLICY_DISABLED hits. */ if (rpz->policy == DNS_RPZ_POLICY_DISABLED) { - rpz_log_rewrite(client, "disabled ", - policy, rpz_type, rpz_qname); + rpz_log_rewrite(client, ISC_TRUE, policy, + rpz_type, zone, rpz_qname); continue; } @@ -4482,7 +4653,7 @@ rpz_rewrite(ns_client_t *client, dns_rdatatype_t qtype, isc_result_t qresult, rdataset = NULL; if ((st->state & DNS_RPZ_DONE_QNAME) == 0) { /* - * Check rules for the query name if this it the first time + * Check rules for the query name if this is the first time * for the current qname, i.e. we've not been recursing. * There is a first time for each name in a CNAME chain. */ @@ -4524,7 +4695,7 @@ rpz_rewrite(ns_client_t *client, dns_rdatatype_t qtype, isc_result_t qresult, dns_fixedname_init(&nsnamef); dns_name_clone(client->query.qname, dns_fixedname_name(&nsnamef)); - while (st->r.label > 1) { + while (st->r.label > client->view->rpz_min_ns_labels) { /* * Get NS rrset for each domain in the current qname. */ @@ -4655,8 +4826,8 @@ cleanup: st->m.policy == DNS_RPZ_POLICY_ERROR) { if (st->m.policy == DNS_RPZ_POLICY_PASSTHRU && result != DNS_R_DELEGATION) - rpz_log_rewrite(client, "", st->m.policy, st->m.type, - st->qname); + rpz_log_rewrite(client, ISC_FALSE, st->m.policy, + st->m.type, st->m.zone, st->qname); rpz_match_clear(st); } if (st->m.policy == DNS_RPZ_POLICY_ERROR) { @@ -4671,7 +4842,7 @@ cleanup: } /* - * See if response policy zone rewriting is allowed a lack of interest + * See if response policy zone rewriting is allowed by a lack of interest * by the client in DNSSEC or a lack of signatures. */ static isc_boolean_t @@ -4766,7 +4937,8 @@ rpz_add_cname(ns_client_t *client, dns_rpz_st_t *st, fname, dns_trust_authanswer, st->m.ttl); if (result != ISC_R_SUCCESS) return (result); - rpz_log_rewrite(client, "", st->m.policy, st->m.type, st->qname); + rpz_log_rewrite(client, ISC_FALSE, st->m.policy, + st->m.type, st->m.zone, st->qname); ns_client_qnamereplace(client, fname); /* * Turn off DNSSEC because the results of a @@ -5093,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, @@ -5102,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. @@ -5118,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)) { @@ -5260,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. @@ -5297,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"); @@ -5328,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 @@ -5562,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"); @@ -5703,9 +5999,10 @@ query_find(ns_client_t *client, dns_fetchevent_t *event, dns_rdatatype_t qtype) client->attributes &= ~(NS_CLIENTATTR_WANTDNSSEC | DNS_MESSAGEFLAG_AD); query_putrdataset(client, &sigrdataset); + rpz_st->q.is_zone = is_zone; is_zone = ISC_TRUE; - rpz_log_rewrite(client, "", rpz_st->m.policy, - rpz_st->m.type, rpz_st->qname); + rpz_log_rewrite(client, ISC_FALSE, rpz_st->m.policy, + rpz_st->m.type, zone, rpz_st->qname); } } @@ -5737,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) { /* @@ -6080,6 +6378,15 @@ query_find(ns_client_t *client, dns_fetchevent_t *event, dns_rdatatype_t qtype) rdataset = NULL; sigrdataset = NULL; type = qtype = dns_rdatatype_a; + rpz_st = client->query.rpz_st; + if (rpz_st != NULL) { + /* + * Arrange for RPZ rewriting of any A records. + */ + if ((rpz_st->state & DNS_RPZ_REWRITTEN) != 0) + is_zone = rpz_st->q.is_zone; + rpz_st_clear(client); + } dns64 = ISC_TRUE; goto db_find; } @@ -6108,7 +6415,10 @@ query_find(ns_client_t *client, dns_fetchevent_t *event, dns_rdatatype_t qtype) * closest provable encloser. */ if (dns_rdataset_isassociated(rdataset) && - !dns_name_equal(qname, found)) { + !dns_name_equal(qname, found) && + !(ns_g_nonearest && + qtype != dns_rdatatype_ds)) + { unsigned int count; unsigned int skip; @@ -6198,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 @@ -6257,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); @@ -6338,6 +6655,15 @@ query_find(ns_client_t *client, dns_fetchevent_t *event, dns_rdatatype_t qtype) sigrdataset = NULL; fname = NULL; type = qtype = dns_rdatatype_a; + rpz_st = client->query.rpz_st; + if (rpz_st != NULL) { + /* + * Arrange for RPZ rewriting of any A records. + */ + if ((rpz_st->state & DNS_RPZ_REWRITTEN) != 0) + is_zone = rpz_st->q.is_zone; + rpz_st_clear(client); + } dns64 = ISC_TRUE; goto db_find; } @@ -6750,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); @@ -6838,6 +7164,15 @@ query_find(ns_client_t *client, dns_fetchevent_t *event, dns_rdatatype_t qtype) rdataset = NULL; sigrdataset = NULL; type = qtype = dns_rdatatype_a; + rpz_st = client->query.rpz_st; + if (rpz_st != NULL) { + /* + * Arrange for RPZ rewriting of any A records. + */ + if ((rpz_st->state & DNS_RPZ_REWRITTEN) != 0) + is_zone = rpz_st->q.is_zone; + rpz_st_clear(client); + } dns64_exclude = dns64 = ISC_TRUE; goto db_find; } @@ -7124,7 +7459,6 @@ ns_query_start(ns_client_t *client) { dns_rdatatype_t qtype; unsigned int saved_extflags = client->extflags; unsigned int saved_flags = client->message->flags; - isc_boolean_t want_ad; CTRACE("ns_query_start"); @@ -7220,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: @@ -7286,13 +7621,11 @@ ns_query_start(ns_client_t *client) { client->query.attributes &= ~NS_QUERYATTR_SECURE; /* - * Set 'want_ad' if the client has set AD in the query. + * Set NS_CLIENTATTR_WANTDNSSEC if the client has set AD in the query. * This allows AD to be returned on queries without DO set. */ if ((message->flags & DNS_MESSAGEFLAG_AD) != 0) - want_ad = ISC_TRUE; - else - want_ad = ISC_FALSE; + client->attributes |= NS_CLIENTATTR_WANTAD; /* * This is an ordinary query. @@ -7317,7 +7650,7 @@ ns_query_start(ns_client_t *client) { * Set AD. We must clear it if we add non-validated data to a * response. */ - if (WANTDNSSEC(client) || want_ad) + if (WANTDNSSEC(client) || WANTAD(client)) message->flags |= DNS_MESSAGEFLAG_AD; qclient = NULL; diff --git a/contrib/bind9/bin/named/server.c b/contrib/bind9/bin/named/server.c index c3eb1ea0ae67..aef922bb73bc 100644 --- a/contrib/bind9/bin/named/server.c +++ b/contrib/bind9/bin/named/server.c @@ -1,5 +1,5 @@ /* - * Copyright (C) 2004-2012 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.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. @@ -159,7 +166,7 @@ * a cache. Only effective when a finite max-cache-size is specified. * This is currently defined to be 8MB. */ -#define MAX_ADB_SIZE_FOR_CACHESHARE 8388608 +#define MAX_ADB_SIZE_FOR_CACHESHARE 8388608U struct ns_dispatch { isc_sockaddr_t addr; @@ -215,56 +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", + "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 @@ -447,7 +527,7 @@ configure_view_nametable(const cfg_obj_t *vconfig, const cfg_obj_t *config, element = cfg_list_next(element)) { nameobj = cfg_listelt_value(element); str = cfg_obj_asstring(nameobj); - isc_buffer_init(&b, str, strlen(str)); + isc_buffer_constinit(&b, str, strlen(str)); isc_buffer_add(&b, strlen(str)); CHECK(dns_name_fromtext(name, &b, dns_rootname, 0, NULL)); /* @@ -564,7 +644,7 @@ dstkey_fromconfig(const cfg_obj_t *vconfig, const cfg_obj_t *key, keystruct.common.rdtype, &keystruct, &rrdatabuf)); dns_fixedname_init(&fkeyname); - isc_buffer_init(&namebuf, keynamestr, strlen(keynamestr)); + isc_buffer_constinit(&namebuf, keynamestr, strlen(keynamestr)); isc_buffer_add(&namebuf, strlen(keynamestr)); CHECK(dns_name_fromtext(keyname, &namebuf, dns_rootname, 0, NULL)); CHECK(dst_key_fromdns(keyname, viewclass, &rrdatabuf, @@ -798,7 +878,17 @@ configure_view_dnsseckeys(dns_view_t *view, const cfg_obj_t *vconfig, */ obj = NULL; (void)ns_config_get(maps, "managed-keys-directory", &obj); - directory = obj != NULL ? cfg_obj_asstring(obj) : NULL; + directory = (obj != NULL ? cfg_obj_asstring(obj) : NULL); + if (directory != NULL) + result = isc_file_isdirectory(directory); + if (result != ISC_R_SUCCESS) { + isc_log_write(ns_g_lctx, DNS_LOGCATEGORY_SECURITY, + NS_LOGMODULE_SERVER, ISC_LOG_ERROR, + "invalid managed-keys-directory %s: %s", + directory, isc_result_totext(result)); + goto cleanup; + + } CHECK(add_keydata_zone(view, directory, ns_g_mctx)); cleanup: @@ -824,7 +914,7 @@ mustbesecure(const cfg_obj_t *mbs, dns_resolver_t *resolver) { { obj = cfg_listelt_value(element); str = cfg_obj_asstring(cfg_tuple_get(obj, "name")); - isc_buffer_init(&b, str, strlen(str)); + isc_buffer_constinit(&b, str, strlen(str)); isc_buffer_add(&b, strlen(str)); CHECK(dns_name_fromtext(name, &b, dns_rootname, 0, NULL)); value = cfg_obj_asboolean(cfg_tuple_get(obj, "value")); @@ -977,7 +1067,7 @@ configure_order(dns_order_t *order, const cfg_obj_t *ent) { else str = "*"; addroot = ISC_TF(strcmp(str, "*") == 0); - isc_buffer_init(&b, str, strlen(str)); + isc_buffer_constinit(&b, str, strlen(str)); isc_buffer_add(&b, strlen(str)); dns_fixedname_init(&fixed); result = dns_name_fromtext(dns_fixedname_name(&fixed), &b, @@ -1163,7 +1253,7 @@ disable_algorithms(const cfg_obj_t *disabled, dns_resolver_t *resolver) { dns_fixedname_init(&fixed); name = dns_fixedname_name(&fixed); str = cfg_obj_asstring(cfg_tuple_get(disabled, "name")); - isc_buffer_init(&b, str, strlen(str)); + isc_buffer_constinit(&b, str, strlen(str)); isc_buffer_add(&b, strlen(str)); CHECK(dns_name_fromtext(name, &b, dns_rootname, 0, NULL)); @@ -1215,7 +1305,7 @@ on_disable_list(const cfg_obj_t *disablelist, dns_name_t *zonename) { { value = cfg_listelt_value(element); str = cfg_obj_asstring(value); - isc_buffer_init(&b, str, strlen(str)); + isc_buffer_constinit(&b, str, strlen(str)); isc_buffer_add(&b, strlen(str)); result = dns_name_fromtext(name, &b, dns_rootname, 0, NULL); @@ -1258,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) @@ -1311,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 @@ -1344,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 @@ -1399,7 +1491,7 @@ dns64_reverse(dns_view_t *view, isc_mem_t *mctx, isc_netaddr_t *na, dns64_dbtype[3] = contact; dns_fixedname_init(&fixed); name = dns_fixedname_name(&fixed); - isc_buffer_init(&b, reverse, strlen(reverse)); + isc_buffer_constinit(&b, reverse, strlen(reverse)); isc_buffer_add(&b, strlen(reverse)); CHECK(dns_name_fromtext(name, &b, dns_rootname, 0, NULL)); CHECK(dns_zone_create(&zone, mctx)); @@ -1417,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, @@ -1430,39 +1522,57 @@ cleanup: } static isc_result_t +configure_rpz_name(dns_view_t *view, const cfg_obj_t *obj, dns_name_t *name, + const char *str, const char *msg) +{ + isc_result_t result; + + result = dns_name_fromstring(name, str, DNS_NAME_DOWNCASE, view->mctx); + if (result != ISC_R_SUCCESS) + cfg_obj_log(obj, ns_g_lctx, DNS_RPZ_ERROR_LEVEL, + "invalid %s '%s'", msg, str); + return (result); +} + +static isc_result_t +configure_rpz_name2(dns_view_t *view, const cfg_obj_t *obj, dns_name_t *name, + const char *str, const dns_name_t *origin) +{ + isc_result_t result; + + result = dns_name_fromstring2(name, str, origin, DNS_NAME_DOWNCASE, + view->mctx); + if (result != ISC_R_SUCCESS) + cfg_obj_log(obj, ns_g_lctx, DNS_RPZ_ERROR_LEVEL, + "invalid zone '%s'", str); + return (result); +} + +static isc_result_t configure_rpz(dns_view_t *view, const cfg_listelt_t *element, isc_boolean_t recursive_only_def, dns_ttl_t ttl_def) { - const cfg_obj_t *rpz_obj, *policy_obj, *obj; + const cfg_obj_t *rpz_obj, *obj; const char *str; dns_rpz_zone_t *old, *new; - dns_zone_t *zone = NULL; isc_result_t result; + rpz_obj = cfg_listelt_value(element); + new = isc_mem_get(view->mctx, sizeof(*new)); if (new == NULL) { - result = ISC_R_NOMEMORY; - goto cleanup; + cfg_obj_log(rpz_obj, ns_g_lctx, DNS_RPZ_ERROR_LEVEL, + "no memory for response policy zones"); + return (ISC_R_NOMEMORY); } memset(new, 0, sizeof(*new)); dns_name_init(&new->origin, NULL); dns_name_init(&new->nsdname, NULL); - dns_name_init(&new->cname, NULL); dns_name_init(&new->passthru, NULL); + dns_name_init(&new->cname, NULL); ISC_LIST_INITANDAPPEND(view->rpz_zones, new, link); - rpz_obj = cfg_listelt_value(element); - policy_obj = cfg_tuple_get(rpz_obj, "policy"); - if (cfg_obj_isvoid(policy_obj)) { - new->policy = DNS_RPZ_POLICY_GIVEN; - } else { - str = cfg_obj_asstring(cfg_tuple_get(policy_obj, - "policy name")); - new->policy = dns_rpz_str2policy(str); - INSIST(new->policy != DNS_RPZ_POLICY_ERROR); - } - obj = cfg_tuple_get(rpz_obj, "recursive-only"); if (cfg_obj_isvoid(obj)) { new->recursive_only = recursive_only_def; @@ -1480,47 +1590,14 @@ configure_rpz(dns_view_t *view, const cfg_listelt_t *element, } str = cfg_obj_asstring(cfg_tuple_get(rpz_obj, "zone name")); - result = dns_name_fromstring(&new->origin, str, DNS_NAME_DOWNCASE, - view->mctx); - if (result != ISC_R_SUCCESS) { - cfg_obj_log(rpz_obj, ns_g_lctx, DNS_RPZ_ERROR_LEVEL, - "invalid zone '%s'", str); - goto cleanup; - } - - result = dns_name_fromstring2(&new->nsdname, DNS_RPZ_NSDNAME_ZONE, - &new->origin, DNS_NAME_DOWNCASE, - view->mctx); - if (result != ISC_R_SUCCESS) { - cfg_obj_log(rpz_obj, ns_g_lctx, DNS_RPZ_ERROR_LEVEL, - "invalid zone '%s'", str); - goto cleanup; - } - - result = dns_name_fromstring(&new->passthru, DNS_RPZ_PASSTHRU_ZONE, - DNS_NAME_DOWNCASE, view->mctx); - if (result != ISC_R_SUCCESS) { - cfg_obj_log(rpz_obj, ns_g_lctx, DNS_RPZ_ERROR_LEVEL, - "invalid zone '%s'", str); - goto cleanup; - } - - result = dns_view_findzone(view, &new->origin, &zone); - if (result != ISC_R_SUCCESS) { - cfg_obj_log(rpz_obj, ns_g_lctx, DNS_RPZ_ERROR_LEVEL, - "unknown zone '%s'", str); - goto cleanup; - } - if (dns_zone_gettype(zone) != dns_zone_master && - dns_zone_gettype(zone) != dns_zone_slave) { + result = configure_rpz_name(view, rpz_obj, &new->origin, str, "zone"); + if (result != ISC_R_SUCCESS) + return (result); + if (dns_name_equal(&new->origin, dns_rootname)) { cfg_obj_log(rpz_obj, ns_g_lctx, DNS_RPZ_ERROR_LEVEL, - "zone '%s' is neither master nor slave", str); - dns_zone_detach(&zone); - result = DNS_R_NOTMASTER; - goto cleanup; + "invalid zone name '%s'", str); + return (DNS_R_EMPTYLABEL); } - dns_zone_detach(&zone); - for (old = ISC_LIST_HEAD(view->rpz_zones); old != new; old = ISC_LIST_NEXT(old, link)) { @@ -1529,26 +1606,37 @@ configure_rpz(dns_view_t *view, const cfg_listelt_t *element, cfg_obj_log(rpz_obj, ns_g_lctx, DNS_RPZ_ERROR_LEVEL, "duplicate '%s'", str); result = DNS_R_DUPLICATE; - goto cleanup; + return (result); } } - if (new->policy == DNS_RPZ_POLICY_CNAME) { - str = cfg_obj_asstring(cfg_tuple_get(policy_obj, "cname")); - result = dns_name_fromstring(&new->cname, str, - DNS_NAME_DOWNCASE, view->mctx); - if (result != ISC_R_SUCCESS) { - cfg_obj_log(rpz_obj, ns_g_lctx, DNS_RPZ_ERROR_LEVEL, - "invalid cname '%s'", str); - goto cleanup; + result = configure_rpz_name2(view, rpz_obj, &new->nsdname, + DNS_RPZ_NSDNAME_ZONE, &new->origin); + if (result != ISC_R_SUCCESS) + return (result); + + result = configure_rpz_name(view, rpz_obj, &new->passthru, + DNS_RPZ_PASSTHRU_ZONE, "zone"); + if (result != ISC_R_SUCCESS) + return (result); + + obj = cfg_tuple_get(rpz_obj, "policy"); + if (cfg_obj_isvoid(obj)) { + new->policy = DNS_RPZ_POLICY_GIVEN; + } else { + str = cfg_obj_asstring(cfg_tuple_get(obj, "policy name")); + new->policy = dns_rpz_str2policy(str); + INSIST(new->policy != DNS_RPZ_POLICY_ERROR); + if (new->policy == DNS_RPZ_POLICY_CNAME) { + str = cfg_obj_asstring(cfg_tuple_get(obj, "cname")); + result = configure_rpz_name(view, rpz_obj, &new->cname, + str, "cname"); + if (result != ISC_R_SUCCESS) + return (result); } } return (ISC_R_SUCCESS); - - cleanup: - dns_rpz_view_destroy(view); - return (result); } /* @@ -1582,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 */ @@ -1599,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; @@ -1615,8 +1703,9 @@ 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; REQUIRE(DNS_VIEW_VALID(view)); @@ -1690,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); } @@ -1715,6 +1804,53 @@ configure_view(dns_view_t *view, cfg_obj_t *config, cfg_obj_t *vconfig, } /* + * Make the list of response policy zone names for a view that + * is used for real lookups and so cares about hints. + */ + obj = NULL; + if (view->rdclass == dns_rdataclass_in && need_hints && + ns_config_get(maps, "response-policy", &obj) == ISC_R_SUCCESS) { + const cfg_obj_t *rpz_obj; + isc_boolean_t recursive_only_def; + dns_ttl_t ttl_def; + + rpz_obj = cfg_tuple_get(obj, "recursive-only"); + if (!cfg_obj_isvoid(rpz_obj) && + !cfg_obj_asboolean(rpz_obj)) + recursive_only_def = ISC_FALSE; + else + recursive_only_def = ISC_TRUE; + + rpz_obj = cfg_tuple_get(obj, "break-dnssec"); + if (!cfg_obj_isvoid(rpz_obj) && + cfg_obj_asboolean(rpz_obj)) + view->rpz_break_dnssec = ISC_TRUE; + else + view->rpz_break_dnssec = ISC_FALSE; + + rpz_obj = cfg_tuple_get(obj, "max-policy-ttl"); + if (cfg_obj_isuint32(rpz_obj)) + ttl_def = cfg_obj_asuint32(rpz_obj); + else + ttl_def = DNS_RPZ_MAX_TTL_DEFAULT; + + rpz_obj = cfg_tuple_get(obj, "min-ns-dots"); + if (cfg_obj_isuint32(rpz_obj)) + view->rpz_min_ns_labels = cfg_obj_asuint32(rpz_obj) + 1; + else + view->rpz_min_ns_labels = 2; + + element = cfg_list_first(cfg_tuple_get(obj, "zone list")); + while (element != NULL) { + result = configure_rpz(view, element, + recursive_only_def, ttl_def); + if (result != ISC_R_SUCCESS) + goto cleanup; + element = cfg_list_next(element); + } + } + + /* * Configure the zones. */ zonelist = NULL; @@ -1735,6 +1871,22 @@ configure_view(dns_view_t *view, cfg_obj_t *config, cfg_obj_t *vconfig, actx, ISC_FALSE)); } + for (rpz = ISC_LIST_HEAD(view->rpz_zones); + rpz != NULL; + rpz = ISC_LIST_NEXT(rpz, link)) + { + if (!rpz->defined) { + char namebuf[DNS_NAME_FORMATSIZE]; + + dns_name_format(&rpz->origin, namebuf, sizeof(namebuf)); + cfg_obj_log(obj, ns_g_lctx, DNS_RPZ_ERROR_LEVEL, + "'%s' is not a master or slave zone", + namebuf); + result = ISC_R_NOTFOUND; + goto cleanup; + } + } + /* * If we're allowing added zones, then load zone configuration * from the newzone file for zones that were added during previous @@ -1825,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. */ @@ -2142,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)); @@ -2161,9 +2317,9 @@ configure_view(dns_view_t *view, cfg_obj_t *config, cfg_obj_t *vconfig, * MAX_ADB_SIZE_FOR_CACHESHARE when the cache is shared. */ max_adb_size = 0; - if (max_cache_size != 0) { + if (max_cache_size != 0U) { max_adb_size = max_cache_size / 8; - if (max_adb_size == 0) + if (max_adb_size == 0U) max_adb_size = 1; /* Force minimum. */ if (view != nsc->primaryview && max_adb_size > MAX_ADB_SIZE_FOR_CACHESHARE) { @@ -2227,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); @@ -2554,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); @@ -2638,7 +2802,7 @@ configure_view(dns_view_t *view, cfg_obj_t *config, cfg_obj_t *vconfig, obj = cfg_listelt_value(element); str = cfg_obj_asstring(cfg_tuple_get(obj, "trust-anchor")); - isc_buffer_init(&b, str, strlen(str)); + isc_buffer_constinit(&b, str, strlen(str)); isc_buffer_add(&b, strlen(str)); dlv = dns_fixedname_name(&view->dlv_fixed); CHECK(dns_name_fromtext(dlv, &b, dns_rootname, @@ -2691,7 +2855,7 @@ configure_view(dns_view_t *view, cfg_obj_t *config, cfg_obj_t *vconfig, element = cfg_list_next(element)) { exclude = cfg_listelt_value(element); str = cfg_obj_asstring(exclude); - isc_buffer_init(&b, str, strlen(str)); + isc_buffer_constinit(&b, str, strlen(str)); isc_buffer_add(&b, strlen(str)); CHECK(dns_name_fromtext(name, &b, dns_rootname, 0, NULL)); @@ -2711,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) { @@ -2732,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); @@ -2745,7 +2905,7 @@ configure_view(dns_view_t *view, cfg_obj_t *config, cfg_obj_t *vconfig, result = ns_config_get(maps, "empty-server", &obj); if (result == ISC_R_SUCCESS) { str = cfg_obj_asstring(obj); - isc_buffer_init(&buffer, str, strlen(str)); + isc_buffer_constinit(&buffer, str, strlen(str)); isc_buffer_add(&buffer, strlen(str)); CHECK(dns_name_fromtext(name, &buffer, dns_rootname, 0, NULL)); @@ -2760,7 +2920,7 @@ configure_view(dns_view_t *view, cfg_obj_t *config, cfg_obj_t *vconfig, result = ns_config_get(maps, "empty-contact", &obj); if (result == ISC_R_SUCCESS) { str = cfg_obj_asstring(obj); - isc_buffer_init(&buffer, str, strlen(str)); + isc_buffer_constinit(&buffer, str, strlen(str)); isc_buffer_add(&buffer, strlen(str)); CHECK(dns_name_fromtext(name, &buffer, dns_rootname, 0, NULL)); @@ -2774,17 +2934,31 @@ 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; - isc_buffer_init(&buffer, empty, strlen(empty)); + isc_buffer_constinit(&buffer, empty, strlen(empty)); isc_buffer_add(&buffer, strlen(empty)); /* * Look for zone on drop list. @@ -2800,7 +2974,6 @@ configure_view(dns_view_t *view, cfg_obj_t *config, cfg_obj_t *vconfig, */ (void)dns_view_findzone(view, name, &zone); if (zone != NULL) { - CHECK(setquerystats(zone, mctx, zonestats_on)); dns_zone_detach(&zone); continue; } @@ -2815,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. */ @@ -2852,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, @@ -2876,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, @@ -2886,49 +3043,6 @@ configure_view(dns_view_t *view, cfg_obj_t *config, cfg_obj_t *vconfig, } } - /* - * Make the list of response policy zone names for views that - * are used for real lookups and so care about hints. - */ - obj = NULL; - if (view->rdclass == dns_rdataclass_in && need_hints && - ns_config_get(maps, "response-policy", &obj) == ISC_R_SUCCESS) { - const cfg_obj_t *recursive_only_obj; - const cfg_obj_t *break_dnssec_obj, *ttl_obj; - isc_boolean_t recursive_only_def; - dns_ttl_t ttl_def; - - recursive_only_obj = cfg_tuple_get(obj, "recursive-only"); - if (!cfg_obj_isvoid(recursive_only_obj) && - !cfg_obj_asboolean(recursive_only_obj)) - recursive_only_def = ISC_FALSE; - else - recursive_only_def = ISC_TRUE; - - break_dnssec_obj = cfg_tuple_get(obj, "break-dnssec"); - if (!cfg_obj_isvoid(break_dnssec_obj) && - cfg_obj_asboolean(break_dnssec_obj)) - view->rpz_break_dnssec = ISC_TRUE; - else - view->rpz_break_dnssec = ISC_FALSE; - - ttl_obj = cfg_tuple_get(obj, "max-policy-ttl"); - if (cfg_obj_isuint32(ttl_obj)) - ttl_def = cfg_obj_asuint32(ttl_obj); - else - ttl_def = DNS_RPZ_MAX_TTL_DEFAULT; - - for (element = cfg_list_first(cfg_tuple_get(obj, "zone list")); - element != NULL; - element = cfg_list_next(element)) { - result = configure_rpz(view, element, - recursive_only_def, ttl_def); - if (result != ISC_R_SUCCESS) - goto cleanup; - dns_rpz_set_need(ISC_TRUE); - } - } - result = ISC_R_SUCCESS; cleanup: @@ -3028,7 +3142,7 @@ configure_alternates(const cfg_obj_t *config, dns_view_t *view, isc_buffer_t buffer; in_port_t myport = port; - isc_buffer_init(&buffer, str, strlen(str)); + isc_buffer_constinit(&buffer, str, strlen(str)); isc_buffer_add(&buffer, strlen(str)); dns_fixedname_init(&fixed); name = dns_fixedname_name(&fixed); @@ -3265,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; @@ -3272,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; @@ -3280,6 +3396,8 @@ configure_zone(const cfg_obj_t *config, const cfg_obj_t *zconfig, const char *zname; dns_rdataclass_t zclass; const char *ztypestr; + isc_boolean_t is_rpz; + dns_rpz_zone_t *rpz; options = NULL; (void)cfg_map_get(config, "options", &options); @@ -3290,7 +3408,7 @@ configure_zone(const cfg_obj_t *config, const cfg_obj_t *zconfig, * Get the zone origin as a dns_name_t. */ zname = cfg_obj_asstring(cfg_tuple_get(zconfig, "name")); - isc_buffer_init(&buffer, zname, strlen(zname)); + isc_buffer_constinit(&buffer, zname, strlen(zname)); isc_buffer_add(&buffer, strlen(zname)); dns_fixedname_init(&fixorigin); CHECK(dns_name_fromtext(dns_fixedname_name(&fixorigin), @@ -3393,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); @@ -3409,6 +3559,21 @@ configure_zone(const cfg_obj_t *config, const cfg_obj_t *zconfig, INSIST(dupzone == NULL); /* + * Note whether this is a response policy zone. + */ + is_rpz = ISC_FALSE; + for (rpz = ISC_LIST_HEAD(view->rpz_zones); + rpz != NULL; + rpz = ISC_LIST_NEXT(rpz, link)) + { + if (dns_name_equal(&rpz->origin, origin)) { + is_rpz = ISC_TRUE; + rpz->defined = ISC_TRUE; + break; + } + } + + /* * See if we can reuse an existing zone. This is * only possible if all of these are true: * - The zone's view exists @@ -3416,19 +3581,23 @@ configure_zone(const cfg_obj_t *config, const cfg_obj_t *zconfig, * - The zone is compatible with the config * options (e.g., an existing master zone cannot * 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); + if (zone != NULL && is_rpz != dns_zone_get_rpz(zone)) + dns_zone_detach(&zone); + if (zone != NULL) { /* * We found a reusable zone. Make it use the @@ -3442,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) @@ -3451,6 +3620,19 @@ configure_zone(const cfg_obj_t *config, const cfg_obj_t *zconfig, dns_zone_setstats(zone, ns_g_server->zonestats); } + if (is_rpz) { + result = dns_zone_rpz_enable(zone); + if (result != ISC_R_SUCCESS) { + isc_log_write(ns_g_lctx, NS_LOGCATEGORY_GENERAL, + NS_LOGMODULE_SERVER, ISC_LOG_ERROR, + "zone '%s': incompatible" + " masterfile-format or database" + " for a response policy zone", + zname); + goto cleanup; + } + } + /* * If the zone contains a 'forwarders' statement, configure * selective forwarding. @@ -3479,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. @@ -3498,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); @@ -3540,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); @@ -3574,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); @@ -3982,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; @@ -4126,7 +4331,7 @@ configure_session_key(const cfg_obj_t **maps, ns_server_t *server, INSIST(result == ISC_R_SUCCESS); keynamestr = cfg_obj_asstring(obj); dns_fixedname_init(&fname); - isc_buffer_init(&buffer, keynamestr, strlen(keynamestr)); + isc_buffer_constinit(&buffer, keynamestr, strlen(keynamestr)); isc_buffer_add(&buffer, strlen(keynamestr)); keyname = dns_fixedname_name(&fname); result = dns_name_fromtext(keyname, &buffer, dns_rootname, 0, NULL); @@ -5211,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); } @@ -5261,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)); } /* @@ -5322,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 @@ -5763,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, @@ -5844,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; @@ -5858,19 +6130,23 @@ zone_from_args(ns_server_t *server, char *args, dns_zone_t **zonep, dns_rdataclass_t rdclass; REQUIRE(zonep != NULL && *zonep == NULL); + REQUIRE(zonename == NULL || *zonename == NULL); 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) + if (zonename != NULL) *zonename = zonetxt; /* Look for the optional class name. */ @@ -5880,7 +6156,7 @@ zone_from_args(ns_server_t *server, char *args, dns_zone_t **zonep, viewtxt = next_token(&input, " \t"); } - isc_buffer_init(&buf, zonetxt, strlen(zonetxt)); + isc_buffer_constinit(&buf, zonetxt, strlen(zonetxt)); isc_buffer_add(&buf, strlen(zonetxt)); dns_fixedname_init(&name); result = dns_name_fromtext(dns_fixedname_name(&name), @@ -5930,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); @@ -5956,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) { @@ -6016,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) @@ -6041,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) @@ -6063,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, @@ -6471,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), @@ -6768,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; @@ -6788,7 +7093,7 @@ ns_server_flushname(ns_server_t *server, char *args) { if (target == NULL) return (ISC_R_UNEXPECTEDEND); - isc_buffer_init(&b, target, strlen(target)); + isc_buffer_constinit(&b, target, strlen(target)); isc_buffer_add(&b, strlen(target)); dns_fixedname_init(&fixed); name = dns_fixedname_name(&fixed); @@ -6815,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)); } } @@ -6829,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); @@ -6878,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" @@ -6890,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", @@ -7142,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) @@ -7169,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 @@ -7176,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) { @@ -7209,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); @@ -7231,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 { @@ -7342,7 +7766,7 @@ ns_server_add_zone(ns_server_t *server, char *args) { CHECK(cfg_map_get(config, "addzone", &parms)); zonename = cfg_obj_asstring(cfg_tuple_get(parms, "name")); - isc_buffer_init(&buf, zonename, strlen(zonename)); + isc_buffer_constinit(&buf, zonename, strlen(zonename)); isc_buffer_add(&buf, strlen(zonename)); dns_name_init(&dnsname, NULL); isc_buffer_allocate(server->mctx, &nbuf, 256); @@ -7406,7 +7830,8 @@ ns_server_add_zone(ns_server_t *server, char *args) { CHECK(isc_stdio_open(view->new_zone_file, "a", &fp)); /* Mark view unfrozen so that zone can be added */ - isc_task_beginexclusive(server->task); + result = isc_task_beginexclusive(server->task); + RUNTIME_CHECK(result == ISC_R_SUCCESS); dns_view_thaw(view); result = configure_zone(cfg->config, parms, vconfig, server->mctx, view, cfg->actx, ISC_FALSE); @@ -7514,9 +7939,8 @@ 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)); - if (result != ISC_R_SUCCESS) - return (result); + CHECK(zone_from_args(server, args, NULL, &zone, &zonename, ISC_TRUE)); + if (zone == NULL) { result = ISC_R_UNEXPECTEDEND; goto cleanup; @@ -7531,8 +7955,8 @@ ns_server_del_zone(ns_server_t *server, char *args) { goto cleanup; } - if (zonename != NULL) - znamelen = strlen(zonename); + INSIST(zonename != NULL); + znamelen = strlen(zonename); /* Dig out configuration for this zone */ view = dns_zone_getview(zone); @@ -7682,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 6ea0be505191..bb642cc374bf 100644 --- a/contrib/bind9/bin/named/statschannel.c +++ b/contrib/bind9/bin/named/statschannel.c @@ -1,5 +1,5 @@ /* - * Copyright (C) 2008-2012 Internet Systems Consortium, Inc. ("ISC") + * Copyright (C) 2008-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 @@ -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"); @@ -202,6 +206,8 @@ init_desc(void) { SET_NSSTATDESC(updatebadprereq, "updates rejected due to prerequisite failure", "UpdateBadPrereq"); + SET_NSSTATDESC(rpz_rewrites, "response policy zone rewrites", + "RPZRewrites"); INSIST(i == dns_nsstatscounter_max); /* Initialize resolver statistics */ @@ -302,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); @@ -425,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) @@ -517,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) { @@ -546,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]; @@ -608,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) { @@ -666,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; @@ -719,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 */ @@ -774,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"]; @@ -877,11 +1347,11 @@ generatexml(ns_server_t *server, int *buflen, xmlChar **buf) { TRY0(xmlTextWriterEndElement(writer)); /* views */ TRY0(xmlTextWriterStartElement(writer, ISC_XMLCHAR "socketmgr")); - isc_socketmgr_renderxml(ns_g_socketmgr, writer); + TRY0(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(isc_taskmgr_renderxml(ns_g_taskmgr, writer)); TRY0(xmlTextWriterEndElement(writer)); /* taskmgr */ TRY0(xmlTextWriterStartElement(writer, ISC_XMLCHAR "server")); @@ -944,7 +1414,7 @@ generatexml(ns_server_t *server, int *buflen, xmlChar **buf) { TRY0(xmlTextWriterEndElement(writer)); /* server */ TRY0(xmlTextWriterStartElement(writer, ISC_XMLCHAR "memory")); - isc_mem_renderxml(writer); + TRY0(isc_mem_renderxml(writer)); TRY0(xmlTextWriterEndElement(writer)); /* memory */ TRY0(xmlTextWriterEndElement(writer)); /* statistics */ @@ -966,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) { @@ -998,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); } @@ -1030,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); @@ -1148,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, @@ -1283,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/tkeyconf.c b/contrib/bind9/bin/named/tkeyconf.c index 6d852a0871c0..e9520592dc5f 100644 --- a/contrib/bind9/bin/named/tkeyconf.c +++ b/contrib/bind9/bin/named/tkeyconf.c @@ -1,5 +1,5 @@ /* - * Copyright (C) 2004-2007, 2009, 2010 Internet Systems Consortium, Inc. ("ISC") + * Copyright (C) 2004-2007, 2009, 2010, 2012 Internet Systems Consortium, Inc. ("ISC") * Copyright (C) 1999-2001 Internet Software Consortium. * * Permission to use, copy, modify, and/or distribute this software for any @@ -73,7 +73,7 @@ ns_tkeyctx_fromconfig(const cfg_obj_t *options, isc_mem_t *mctx, if (result == ISC_R_SUCCESS) { s = cfg_obj_asstring(cfg_tuple_get(obj, "name")); n = cfg_obj_asuint32(cfg_tuple_get(obj, "keyid")); - isc_buffer_init(&b, s, strlen(s)); + isc_buffer_constinit(&b, s, strlen(s)); isc_buffer_add(&b, strlen(s)); dns_fixedname_init(&fname); name = dns_fixedname_name(&fname); @@ -87,7 +87,7 @@ ns_tkeyctx_fromconfig(const cfg_obj_t *options, isc_mem_t *mctx, result = cfg_map_get(options, "tkey-domain", &obj); if (result == ISC_R_SUCCESS) { s = cfg_obj_asstring(obj); - isc_buffer_init(&b, s, strlen(s)); + isc_buffer_constinit(&b, s, strlen(s)); isc_buffer_add(&b, strlen(s)); dns_fixedname_init(&fname); name = dns_fixedname_name(&fname); @@ -106,7 +106,7 @@ ns_tkeyctx_fromconfig(const cfg_obj_t *options, isc_mem_t *mctx, if (result == ISC_R_SUCCESS) { s = cfg_obj_asstring(obj); - isc_buffer_init(&b, s, strlen(s)); + isc_buffer_constinit(&b, s, strlen(s)); isc_buffer_add(&b, strlen(s)); dns_fixedname_init(&fname); name = dns_fixedname_name(&fname); diff --git a/contrib/bind9/bin/named/tsigconf.c b/contrib/bind9/bin/named/tsigconf.c index 776b1b9f837d..eef87e930438 100644 --- a/contrib/bind9/bin/named/tsigconf.c +++ b/contrib/bind9/bin/named/tsigconf.c @@ -1,5 +1,5 @@ /* - * Copyright (C) 2004-2007, 2009, 2011 Internet Systems Consortium, Inc. ("ISC") + * Copyright (C) 2004-2007, 2009, 2011, 2012 Internet Systems Consortium, Inc. ("ISC") * Copyright (C) 1999-2001 Internet Software Consortium. * * Permission to use, copy, modify, and/or distribute this software for any @@ -78,7 +78,7 @@ add_initial_keys(const cfg_obj_t *list, dns_tsig_keyring_t *ring, * Create the key name. */ dns_name_init(&keyname, NULL); - isc_buffer_init(&keynamesrc, keyid, strlen(keyid)); + isc_buffer_constinit(&keynamesrc, keyid, strlen(keyid)); isc_buffer_add(&keynamesrc, strlen(keyid)); isc_buffer_init(&keynamebuf, keynamedata, sizeof(keynamedata)); ret = dns_name_fromtext(&keyname, &keynamesrc, dns_rootname, 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 edd394656d28..2ba8a028a37a 100644 --- a/contrib/bind9/bin/named/unix/dlz_dlopen_driver.c +++ b/contrib/bind9/bin/named/unix/dlz_dlopen_driver.c @@ -1,5 +1,5 @@ /* - * Copyright (C) 2011, 2012 Internet Systems Consortium, Inc. ("ISC") + * Copyright (C) 2011-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 @@ -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); } @@ -225,7 +228,9 @@ dlopen_dlz_create(const char *dlzname, unsigned int argc, char *argv[], return (ISC_R_FAILURE); } - isc_mem_create(0, 0, &mctx); + result = isc_mem_create(0, 0, &mctx); + if (result != ISC_R_SUCCESS) + return (result); cd = isc_mem_get(mctx, sizeof(*cd)); if (cd == NULL) { @@ -247,7 +252,9 @@ dlopen_dlz_create(const char *dlzname, unsigned int argc, char *argv[], } /* Initialize the lock */ - isc_mutex_init(&cd->lock); + result = isc_mutex_init(&cd->lock); + if (result != ISC_R_SUCCESS) + goto failed; /* Open the library */ dlopen_flags = RTLD_NOW|RTLD_GLOBAL; @@ -351,11 +358,11 @@ dlopen_dlz_create(const char *dlzname, unsigned int argc, char *argv[], failed: dlopen_log(ISC_LOG_ERROR, "dlz_dlopen of '%s' failed", dlzname); - if (cd->dl_path) + if (cd->dl_path != NULL) isc_mem_free(mctx, cd->dl_path); - if (cd->dlzname) + if (cd->dlzname != NULL) isc_mem_free(mctx, cd->dlzname); - if (dlopen_flags) + if (dlopen_flags != 0) (void) isc_mutex_destroy(&cd->lock); #ifdef HAVE_DLCLOSE if (cd->dl_handle) 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 6fb6a8536721..0df00c083c55 100644 --- a/contrib/bind9/bin/named/update.c +++ b/contrib/bind9/bin/named/update.c @@ -1,5 +1,5 @@ /* - * Copyright (C) 2004-2011 Internet Systems Consortium, Inc. ("ISC") + * Copyright (C) 2004-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: 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 && @@ -3500,7 +2369,8 @@ add_signing_records(dns_db_t *db, dns_rdatatype_t privatetype, ISC_LIST_UNLINK(temp_diff.tuples, tuple, link); ISC_LIST_APPEND(diff->tuples, tuple, link); - dns_rdata_tostruct(&tuple->rdata, &dnskey, NULL); + result = dns_rdata_tostruct(&tuple->rdata, &dnskey, NULL); + RUNTIME_CHECK(result == ISC_R_SUCCESS); if ((dnskey.flags & (DNS_KEYFLAG_OWNERMASK|DNS_KEYTYPE_NOAUTH)) != DNS_KEYOWNER_ZONE) @@ -4156,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)); @@ -4190,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 @@ -4198,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, @@ -4220,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 6cda6589e1c9..a0a617d14c12 100644 --- a/contrib/bind9/bin/named/xfrout.c +++ b/contrib/bind9/bin/named/xfrout.c @@ -1,5 +1,5 @@ /* - * Copyright (C) 2004-2011 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 = { @@ -833,14 +837,6 @@ ns_xfr_start(ns_client_t *client, dns_rdatatype_t reqtype) { FAILQ(DNS_R_NOTAUTH, "non-authoritative zone", question_name, question_class); is_dlz = ISC_TRUE; - /* - * DLZ only support full zone transfer, not incremental - */ - if (reqtype != dns_rdatatype_axfr) { - mnemonic = "AXFR-style IXFR"; - reqtype = dns_rdatatype_axfr; - } - } else { /* * not DLZ and not in normal zone table, we are @@ -852,12 +848,14 @@ ns_xfr_start(ns_client_t *client, dns_rdatatype_t reqtype) { } else { /* zone table has a match */ switch(dns_zone_gettype(zone)) { + /* Master and slave zones are OK for transfer. */ case dns_zone_master: case dns_zone_slave: case dns_zone_dlz: - break; /* Master and slave zones are OK for transfer. */ + break; default: - FAILQ(DNS_R_NOTAUTH, "non-authoritative zone", question_name, question_class); + FAILQ(DNS_R_NOTAUTH, "non-authoritative zone", + question_name, question_class); } CHECK(dns_zone_getdb(zone, &db)); dns_db_currentversion(db, &ver); @@ -992,7 +990,7 @@ ns_xfr_start(ns_client_t *client, dns_rdatatype_t reqtype) { is_poll = ISC_TRUE; goto have_stream; } - journalfile = dns_zone_getjournal(zone); + journalfile = is_dlz ? NULL : dns_zone_getjournal(zone); if (journalfile != NULL) result = ixfr_rrstream_create(mctx, journalfile, diff --git a/contrib/bind9/bin/named/zoneconf.c b/contrib/bind9/bin/named/zoneconf.c index 6eef28ae131f..7f36b143d4e5 100644 --- a/contrib/bind9/bin/named/zoneconf.c +++ b/contrib/bind9/bin/named/zoneconf.c @@ -1,5 +1,5 @@ /* - * Copyright (C) 2004-2012 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: zoneconf.c,v 1.170.14.7 2012/01/31 23:46:39 tbox Exp $ */ +/* $Id$ */ /*% */ @@ -56,6 +56,7 @@ typedef enum { allow_notify, allow_query, + allow_query_on, allow_transfer, allow_update, allow_update_forwarding @@ -104,6 +105,11 @@ configure_zone_acl(const cfg_obj_t *zconfig, const cfg_obj_t *vconfig, aclp = &view->queryacl; aclname = "allow-query"; break; + case allow_query_on: + if (view != NULL) + aclp = &view->queryonacl; + aclname = "allow-query-on"; + break; case allow_transfer: if (view != NULL) aclp = &view->transferacl; @@ -269,7 +275,7 @@ configure_zone_ssutable(const cfg_obj_t *zconfig, dns_zone_t *zone, dns_fixedname_init(&fident); str = cfg_obj_asstring(identity); - isc_buffer_init(&b, str, strlen(str)); + isc_buffer_constinit(&b, str, strlen(str)); isc_buffer_add(&b, strlen(str)); result = dns_name_fromtext(dns_fixedname_name(&fident), &b, dns_rootname, 0, NULL); @@ -292,7 +298,7 @@ configure_zone_ssutable(const cfg_obj_t *zconfig, dns_zone_t *zone, } } else { str = cfg_obj_asstring(dname); - isc_buffer_init(&b, str, strlen(str)); + isc_buffer_constinit(&b, str, strlen(str)); isc_buffer_add(&b, strlen(str)); result = dns_name_fromtext(dns_fixedname_name(&fname), &b, dns_rootname, 0, NULL); @@ -525,7 +531,7 @@ configure_staticstub_servernames(const cfg_obj_t *zconfig, dns_zone_t *zone, dns_fixedname_init(&fixed_name); nsname = dns_fixedname_name(&fixed_name); - isc_buffer_init(&b, str, strlen(str)); + isc_buffer_constinit(&b, str, strlen(str)); isc_buffer_add(&b, strlen(str)); result = dns_name_fromtext(nsname, &b, dns_rootname, 0, NULL); if (result != ISC_R_SUCCESS) { @@ -786,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; @@ -818,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) { @@ -851,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); @@ -901,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) { @@ -914,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. */ @@ -934,6 +976,11 @@ ns_zone_configure(const cfg_obj_t *config, const cfg_obj_t *vconfig, dns_zone_setqueryacl, dns_zone_clearqueryacl)); + RETERR(configure_zone_acl(zconfig, vconfig, config, + allow_query_on, ac, zone, + dns_zone_setqueryonacl, + dns_zone_clearqueryonacl)); + obj = NULL; result = ns_config_get(maps, "dialup", &obj); INSIST(result == ISC_R_SUCCESS && obj != NULL); @@ -955,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); @@ -993,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)); @@ -1048,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); @@ -1069,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; @@ -1084,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); @@ -1097,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); @@ -1112,6 +1230,17 @@ ns_zone_configure(const cfg_obj_t *config, const cfg_obj_t *vconfig, cfg_obj_asboolean(obj)); obj = NULL; + result = ns_config_get(maps, "check-spf", &obj); + INSIST(result == ISC_R_SUCCESS && obj != NULL); + if (strcasecmp(cfg_obj_asstring(obj), "warn") == 0) { + check = ISC_TRUE; + } else if (strcasecmp(cfg_obj_asstring(obj), "ignore") == 0) { + check = ISC_FALSE; + } else + INSIST(0); + dns_zone_setoption(zone, DNS_ZONEOPT_CHECKSPF, check); + + obj = NULL; result = ns_config_get(maps, "zero-no-soa-ttl", &obj); INSIST(result == ISC_R_SUCCESS && obj != NULL); dns_zone_setzeronosoattl(zone, cfg_obj_asboolean(obj)); @@ -1121,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); } /* @@ -1131,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, @@ -1143,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); @@ -1202,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)); } @@ -1213,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); @@ -1235,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); @@ -1250,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; @@ -1271,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); @@ -1286,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); } /* @@ -1318,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); @@ -1327,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, @@ -1335,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; @@ -1345,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); @@ -1413,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; @@ -1450,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 @@ -1462,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. @@ -1481,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); } |