]> granicus.if.org Git - pdns/commitdiff
Add rst-based dnsdist documentation.
authorPieter Lexis <pieter.lexis@powerdns.com>
Thu, 9 Feb 2017 17:06:19 +0000 (18:06 +0100)
committerPieter Lexis <pieter.lexis@powerdns.com>
Mon, 17 Jul 2017 17:10:01 +0000 (19:10 +0200)
86 files changed:
docs/MIBS/DNSDIST-MIB.txt [deleted file]
pdns/README-dnsdist.md
pdns/dnsdistdist/.gitignore
pdns/dnsdistdist/DNSDIST-MIB.txt [changed from symlink to file mode: 0644]
pdns/dnsdistdist/Makefile.am
pdns/dnsdistdist/configure.ac
pdns/dnsdistdist/dnsdist.1.md [deleted symlink]
pdns/dnsdistdist/docs/.gitignore [new file with mode: 0644]
pdns/dnsdistdist/docs/Makefile [new file with mode: 0644]
pdns/dnsdistdist/docs/_static/favicon.ico [new file with mode: 0644]
pdns/dnsdistdist/docs/_static/model.dot [new file with mode: 0644]
pdns/dnsdistdist/docs/_static/powerdns-logo-500px.png [moved from pdns/dnsdistdist/website/markdown/img/powerdns-logo-500px.png with 100% similarity]
pdns/dnsdistdist/docs/_static/powerdns-logo-trans.png [new file with mode: 0644]
pdns/dnsdistdist/docs/_templates/pdns_html/layout.html [new file with mode: 0644]
pdns/dnsdistdist/docs/_templates/pdns_html/static/dialog-note.png [new file with mode: 0644]
pdns/dnsdistdist/docs/_templates/pdns_html/static/dialog-seealso.png [new file with mode: 0644]
pdns/dnsdistdist/docs/_templates/pdns_html/static/dialog-todo.png [new file with mode: 0644]
pdns/dnsdistdist/docs/_templates/pdns_html/static/dialog-topic.png [new file with mode: 0644]
pdns/dnsdistdist/docs/_templates/pdns_html/static/dialog-warning.png [new file with mode: 0644]
pdns/dnsdistdist/docs/_templates/pdns_html/static/epub.css [new file with mode: 0644]
pdns/dnsdistdist/docs/_templates/pdns_html/static/footerbg.png [new file with mode: 0644]
pdns/dnsdistdist/docs/_templates/pdns_html/static/headerbg.png [new file with mode: 0644]
pdns/dnsdistdist/docs/_templates/pdns_html/static/ie6.css [new file with mode: 0644]
pdns/dnsdistdist/docs/_templates/pdns_html/static/middlebg.png [new file with mode: 0644]
pdns/dnsdistdist/docs/_templates/pdns_html/static/pyramid.css_t [new file with mode: 0644]
pdns/dnsdistdist/docs/_templates/pdns_html/static/transparent.gif [new file with mode: 0644]
pdns/dnsdistdist/docs/_templates/pdns_html/theme.conf [new file with mode: 0644]
pdns/dnsdistdist/docs/advanced/acl.rst [new file with mode: 0644]
pdns/dnsdistdist/docs/advanced/ebpf.rst [new file with mode: 0644]
pdns/dnsdistdist/docs/advanced/ecs.rst [new file with mode: 0644]
pdns/dnsdistdist/docs/advanced/index.rst [new file with mode: 0644]
pdns/dnsdistdist/docs/advanced/luaaction.rst [new file with mode: 0644]
pdns/dnsdistdist/docs/advanced/qpslimits.rst [new file with mode: 0644]
pdns/dnsdistdist/docs/advanced/snmp.rst [new file with mode: 0644]
pdns/dnsdistdist/docs/advanced/teeaction.rst [new file with mode: 0644]
pdns/dnsdistdist/docs/advanced/timedipsetrule.rst [new file with mode: 0644]
pdns/dnsdistdist/docs/advanced/tuning.rst [new file with mode: 0644]
pdns/dnsdistdist/docs/changelog.rst [new file with mode: 0644]
pdns/dnsdistdist/docs/conf.py [new file with mode: 0644]
pdns/dnsdistdist/docs/glossary.rst [new file with mode: 0644]
pdns/dnsdistdist/docs/guides/cache.rst [new file with mode: 0644]
pdns/dnsdistdist/docs/guides/console.rst [new file with mode: 0644]
pdns/dnsdistdist/docs/guides/dnscrypt.rst [new file with mode: 0644]
pdns/dnsdistdist/docs/guides/downstreams.rst [new file with mode: 0644]
pdns/dnsdistdist/docs/guides/dynblocks.rst [new file with mode: 0644]
pdns/dnsdistdist/docs/guides/index.rst [new file with mode: 0644]
pdns/dnsdistdist/docs/guides/serverpools.rst [new file with mode: 0644]
pdns/dnsdistdist/docs/guides/serverselection.rst [new file with mode: 0644]
pdns/dnsdistdist/docs/guides/webserver.rst [new file with mode: 0644]
pdns/dnsdistdist/docs/index.rst [new file with mode: 0644]
pdns/dnsdistdist/docs/index_TOC.rst [new file with mode: 0644]
pdns/dnsdistdist/docs/install.rst [new file with mode: 0644]
pdns/dnsdistdist/docs/manpages/dnsdist.1.rst [new file with mode: 0644]
pdns/dnsdistdist/docs/quickstart.rst [new file with mode: 0644]
pdns/dnsdistdist/docs/reference/comboaddress.rst [new file with mode: 0644]
pdns/dnsdistdist/docs/reference/config.rst [new file with mode: 0644]
pdns/dnsdistdist/docs/reference/constants.rst [new file with mode: 0644]
pdns/dnsdistdist/docs/reference/dnscrypt.rst [new file with mode: 0644]
pdns/dnsdistdist/docs/reference/dnsname.rst [new file with mode: 0644]
pdns/dnsdistdist/docs/reference/dq.rst [new file with mode: 0644]
pdns/dnsdistdist/docs/reference/ebpf.rst [new file with mode: 0644]
pdns/dnsdistdist/docs/reference/index.rst [new file with mode: 0644]
pdns/dnsdistdist/docs/reference/netmaskgroup.rst [new file with mode: 0644]
pdns/dnsdistdist/docs/reference/protobuf.rst [new file with mode: 0644]
pdns/dnsdistdist/docs/reference/snmp.rst [new file with mode: 0644]
pdns/dnsdistdist/docs/reference/tuning.rst [new file with mode: 0644]
pdns/dnsdistdist/docs/requirements.txt [new file with mode: 0644]
pdns/dnsdistdist/docs/rules-actions.rst [new file with mode: 0644]
pdns/dnsdistdist/docs/running.rst [new file with mode: 0644]
pdns/dnsdistdist/docs/statistics.rst [new file with mode: 0644]
pdns/dnsdistdist/docs/upgrade_guide.rst [new file with mode: 0644]
pdns/dnsdistdist/introduction.md [deleted file]
pdns/dnsdistdist/m4/pdns_check_pandoc.m4 [deleted file]
pdns/dnsdistdist/m4/pdns_check_virtualenv.m4 [new file with mode: 0644]
pdns/dnsdistdist/website/.gitignore [deleted file]
pdns/dnsdistdist/website/Makefile [deleted file]
pdns/dnsdistdist/website/markdown/README.md [deleted symlink]
pdns/dnsdistdist/website/markdown/changelog.md [deleted file]
pdns/dnsdistdist/website/markdown/dnsdist.1.md [deleted symlink]
pdns/dnsdistdist/website/markdown/download.md [deleted file]
pdns/dnsdistdist/website/markdown/extra.css [deleted file]
pdns/dnsdistdist/website/markdown/img/powerdns-dnsdist-live.gif [deleted file]
pdns/dnsdistdist/website/markdown/index.md [deleted file]
pdns/dnsdistdist/website/markdown/introduction.md [deleted symlink]
pdns/dnsdistdist/website/markdown/screenshots.md [deleted file]
pdns/dnsdistdist/website/mkdocs.yml [deleted file]

diff --git a/docs/MIBS/DNSDIST-MIB.txt b/docs/MIBS/DNSDIST-MIB.txt
deleted file mode 100644 (file)
index bf1097c..0000000
+++ /dev/null
@@ -1,703 +0,0 @@
--- -*- snmpv2 -*-
--- ----------------------------------------------------------------------
--- MIB file for dnsdist
--- ----------------------------------------------------------------------
-
-DNSDIST-MIB DEFINITIONS ::= BEGIN
-
-IMPORTS
-    OBJECT-TYPE, MODULE-IDENTITY, enterprises,
-    Counter64, Unsigned32, NOTIFICATION-TYPE
-        FROM SNMPv2-SMI
-    CounterBasedGauge64
-        FROM HCNUM-TC
-    Float64TC
-        FROM FLOAT-TC-MIB
-    OBJECT-GROUP, MODULE-COMPLIANCE, NOTIFICATION-GROUP
-        FROM SNMPv2-CONF
-    InetAddressType
-        FROM INET-ADDRESS-MIB
-    TEXTUAL-CONVENTION, DisplayString
-        FROM SNMPv2-TC;
-
-dnsdist MODULE-IDENTITY
-    LAST-UPDATED "201611080000Z"
-    ORGANIZATION "PowerDNS BV"
-    CONTACT-INFO "support@powerdns.com"
-    DESCRIPTION
-       "This MIB module describes information gathered through dnsdist."
-
-    REVISION "201611080000Z"
-    DESCRIPTION "Initial revision."
-
-    ::= { powerdns 3 }
-
-powerdns               OBJECT IDENTIFIER ::= { enterprises 43315 }
-
-stats OBJECT IDENTIFIER ::= { dnsdist 1 }
-
-queries OBJECT-TYPE
-    SYNTAX Counter64
-    MAX-ACCESS read-only
-    STATUS current
-    DESCRIPTION
-       "Number of queries received"
-    ::= { stats 1 }
-
-responses OBJECT-TYPE
-    SYNTAX Counter64
-    MAX-ACCESS read-only
-    STATUS current
-    DESCRIPTION
-       "Number of responses received"
-    ::= { stats 2 }
-
-servfailResponses OBJECT-TYPE
-    SYNTAX Counter64
-    MAX-ACCESS read-only
-    STATUS current
-    DESCRIPTION
-       "Number of servfail responses received"
-    ::= { stats 3 }
-
-aclDrops OBJECT-TYPE
-    SYNTAX Counter64
-    MAX-ACCESS read-only
-    STATUS current
-    DESCRIPTION
-       "Number of queries dropped because of the ACL"
-    ::= { stats 4 }
-
--- stats 5 was a BlockFilter Counter, removed in 1.2.0
-
-ruleDrop OBJECT-TYPE
-    SYNTAX Counter64
-    MAX-ACCESS read-only
-    STATUS current
-    DESCRIPTION
-       "Number of queries dropped because of a rule"
-    ::= { stats 6 }
-
-ruleNXDomain OBJECT-TYPE
-    SYNTAX Counter64
-    MAX-ACCESS read-only
-    STATUS current
-    DESCRIPTION
-       "Number of NXDomain responses returned because of a rule"
-    ::= { stats 7 }
-
-ruleRefused OBJECT-TYPE
-    SYNTAX Counter64
-    MAX-ACCESS read-only
-    STATUS current
-    DESCRIPTION
-       "Number of Refused responses returned because of a rule"
-    ::= { stats 8 }
-
-selfAnswered OBJECT-TYPE
-    SYNTAX Counter64
-    MAX-ACCESS read-only
-    STATUS current
-    DESCRIPTION
-       "Number of self-answered responses"
-    ::= { stats 9 }
-
-downstreamTimeouts OBJECT-TYPE
-    SYNTAX Counter64
-    MAX-ACCESS read-only
-    STATUS current
-    DESCRIPTION
-       "Number of downstream timeouts"
-    ::= { stats 10 }
-
-downstreamSendErrors OBJECT-TYPE
-    SYNTAX Counter64
-    MAX-ACCESS read-only
-    STATUS current
-    DESCRIPTION
-       "Number of downstream send errors"
-    ::= { stats 11 }
-
-truncFailures OBJECT-TYPE
-    SYNTAX Counter64
-    MAX-ACCESS read-only
-    STATUS current
-    DESCRIPTION
-       "Number of errors while truncating a response"
-    ::= { stats 12 }
-
-noPolicy OBJECT-TYPE
-    SYNTAX Counter64
-    MAX-ACCESS read-only
-    STATUS current
-    DESCRIPTION
-       "Number of queries dropped because no server was available"
-    ::= { stats 13 }
-
-latency01 OBJECT-TYPE
-    SYNTAX Counter64
-    MAX-ACCESS read-only
-    STATUS current
-    DESCRIPTION
-       "Number of queries answered in less than 1 ms"
-    ::= { stats 14 }
-
-latency110 OBJECT-TYPE
-    SYNTAX Counter64
-    MAX-ACCESS read-only
-    STATUS current
-    DESCRIPTION
-       "Number of queries answered in 1-10 ms"
-    ::= { stats 15 }
-
-latency1050 OBJECT-TYPE
-    SYNTAX Counter64
-    MAX-ACCESS read-only
-    STATUS current
-    DESCRIPTION
-       "Number of queries answered in 10-50 ms"
-    ::= { stats 16 }
-
-latency50100 OBJECT-TYPE
-    SYNTAX Counter64
-    MAX-ACCESS read-only
-    STATUS current
-    DESCRIPTION
-       "Number of queries answered in 50-100 ms"
-    ::= { stats 17 }
-
-latency1001000 OBJECT-TYPE
-    SYNTAX Counter64
-    MAX-ACCESS read-only
-    STATUS current
-    DESCRIPTION
-       "Number of queries answered in 100-1000 ms"
-    ::= { stats 18 }
-
-latencySlow OBJECT-TYPE
-    SYNTAX Counter64
-    MAX-ACCESS read-only
-    STATUS current
-    DESCRIPTION
-       "Number of queries answered in more than 1s"
-    ::= { stats 19 }
-
-latencyAVG100 OBJECT-TYPE
-    SYNTAX Float64TC
-    MAX-ACCESS read-only
-    STATUS current
-    DESCRIPTION
-       "Average latency over the last 100 queries"
-    ::= { stats 20 }
-
-latencyAVG1000 OBJECT-TYPE
-    SYNTAX Float64TC
-    MAX-ACCESS read-only
-    STATUS current
-    DESCRIPTION
-       "Average latency over the last 1000 queries"
-    ::= { stats 21 }
-
-latencyAVG10000 OBJECT-TYPE
-    SYNTAX Float64TC
-    MAX-ACCESS read-only
-    STATUS current
-    DESCRIPTION
-       "Average latency over the last 10000 queries"
-    ::= { stats 22 }
-
-latencyAVG1000000 OBJECT-TYPE
-    SYNTAX Float64TC
-    MAX-ACCESS read-only
-    STATUS current
-    DESCRIPTION
-       "Average latency over the last 1000000 queries"
-    ::= { stats 23 }
-
-uptime OBJECT-TYPE
-    SYNTAX CounterBasedGauge64
-    MAX-ACCESS read-only
-    STATUS current
-    DESCRIPTION
-       "Uptime of the dnsdist process, in seconds"
-    ::= { stats 24 }
-
-realMemoryUsage OBJECT-TYPE
-    SYNTAX CounterBasedGauge64
-    MAX-ACCESS read-only
-    STATUS current
-    DESCRIPTION
-       "Memory usage"
-    ::= { stats 25 }
-
-nonCompliantQueries OBJECT-TYPE
-    SYNTAX Counter64
-    MAX-ACCESS read-only
-    STATUS current
-    DESCRIPTION
-       "Number of queries dropped as non-compliant"
-    ::= { stats 26 }
-
-nonCompliantResponses OBJECT-TYPE
-    SYNTAX Counter64
-    MAX-ACCESS read-only
-    STATUS current
-    DESCRIPTION
-       "Number of responses dropped as non-compliant"
-    ::= { stats 27 }
-
-rdQueries OBJECT-TYPE
-    SYNTAX Counter64
-    MAX-ACCESS read-only
-    STATUS current
-    DESCRIPTION
-       "Number of queries with the RD flag set"
-    ::= { stats 28 }
-
-emptyQueries OBJECT-TYPE
-    SYNTAX Counter64
-    MAX-ACCESS read-only
-    STATUS current
-    DESCRIPTION
-       "Number of empty queries received"
-    ::= { stats 29 }
-
-cacheHits OBJECT-TYPE
-    SYNTAX Counter64
-    MAX-ACCESS read-only
-    STATUS current
-    DESCRIPTION
-       "Number of cache hits"
-    ::= { stats 30 }
-
-cacheMisses OBJECT-TYPE
-    SYNTAX Counter64
-    MAX-ACCESS read-only
-    STATUS current
-    DESCRIPTION
-       "Number of cache misses"
-    ::= { stats 31 }
-
-cpuUserMSec OBJECT-TYPE
-    SYNTAX CounterBasedGauge64
-    MAX-ACCESS read-only
-    STATUS current
-    DESCRIPTION
-       "CPU Usage (user)"
-    ::= { stats 32 }
-
-cpuSysMSec OBJECT-TYPE
-    SYNTAX CounterBasedGauge64
-    MAX-ACCESS read-only
-    STATUS current
-    DESCRIPTION
-       "CPU Usage (sys)"
-    ::= { stats 33 }
-
-fdUsage OBJECT-TYPE
-    SYNTAX CounterBasedGauge64
-    MAX-ACCESS read-only
-    STATUS current
-    DESCRIPTION
-       "Number of file descriptors"
-    ::= { stats 34 }
-
-dynBlocked OBJECT-TYPE
-    SYNTAX Counter64
-    MAX-ACCESS read-only
-    STATUS current
-    DESCRIPTION
-       "Number of queries dropped because of a dynamic block"
-    ::= { stats 35 }
-
-dynBlockNMGSize OBJECT-TYPE
-    SYNTAX CounterBasedGauge64
-    MAX-ACCESS read-only
-    STATUS current
-    DESCRIPTION
-       "Dynamic blocks (NMG) size"
-    ::= { stats 36 }
-
-backendStatTable OBJECT-TYPE
-    SYNTAX SEQUENCE OF BackendStatEntry
-    MAX-ACCESS not-accessible
-    STATUS current
-    DESCRIPTION "Statistics for backends"
-    ::= { dnsdist 2 }
-
-backendStatEntry OBJECT-TYPE
-    SYNTAX BackendStatEntry
-    MAX-ACCESS not-accessible
-    STATUS current
-    DESCRIPTION "Statistics for one backend"
-    INDEX { backendId }
-    ::= { backendStatTable 1 }
-
-BackendStatEntry ::= SEQUENCE {
-    backendId           Unsigned32,
-    backendName         DisplayString,
-    backendLatency      CounterBasedGauge64,
-    backendWeight       CounterBasedGauge64,
-    backendOutstanding  CounterBasedGauge64,
-    backendQPSLimit     CounterBasedGauge64,
-    backendReused       Counter64,
-    backendState        DisplayString,
-    backendAddress      OCTET STRING,
-    backendPools        DisplayString,
-    backendQPS          CounterBasedGauge64,
-    backendQueries      Counter64,
-    backendOrder        CounterBasedGauge64
-}
-
-backendId OBJECT-TYPE
-    SYNTAX Unsigned32
-    MAX-ACCESS not-accessible
-    STATUS current
-    DESCRIPTION
-       "Backend ID"
-    ::= { backendStatEntry 1 }
-
-backendName OBJECT-TYPE
-    SYNTAX DisplayString
-    MAX-ACCESS read-only
-    STATUS current
-    DESCRIPTION
-       "Backend name"
-    ::= { backendStatEntry 2 }
-
-backendLatency OBJECT-TYPE
-    SYNTAX CounterBasedGauge64
-    MAX-ACCESS read-only
-    STATUS current
-    DESCRIPTION
-       "Backend latency"
-    ::= { backendStatEntry 3 }
-
-backendWeight OBJECT-TYPE
-    SYNTAX CounterBasedGauge64
-    MAX-ACCESS read-only
-    STATUS current
-    DESCRIPTION
-       "Backend weight"
-    ::= { backendStatEntry 4 }
-
-backendOutstanding OBJECT-TYPE
-    SYNTAX CounterBasedGauge64
-    MAX-ACCESS read-only
-    STATUS current
-    DESCRIPTION
-       "Backend outstanding queries"
-    ::= { backendStatEntry 5 }
-
-backendQPSLimit OBJECT-TYPE
-    SYNTAX CounterBasedGauge64
-    MAX-ACCESS read-only
-    STATUS current
-    DESCRIPTION
-       "Backend QPS limit"
-    ::= { backendStatEntry 6 }
-
-backendReused OBJECT-TYPE
-    SYNTAX Counter64
-    MAX-ACCESS read-only
-    STATUS current
-    DESCRIPTION
-       "Backend reused slots"
-    ::= { backendStatEntry 7 }
-
-backendState OBJECT-TYPE
-    SYNTAX DisplayString
-    MAX-ACCESS read-only
-    STATUS current
-    DESCRIPTION
-       "Backend state"
-    ::= { backendStatEntry 8 }
-
-backendAddress OBJECT-TYPE
-    SYNTAX OCTET STRING (SIZE (2..24))
-    MAX-ACCESS read-only
-    STATUS current
-    DESCRIPTION
-       "Backend address"
-    ::= { backendStatEntry 9 }
-
-backendPools OBJECT-TYPE
-    SYNTAX DisplayString
-    MAX-ACCESS read-only
-    STATUS current
-    DESCRIPTION
-       "List of pools this backend belongs to"
-    ::= { backendStatEntry 10 }
-
-backendQPS OBJECT-TYPE
-    SYNTAX CounterBasedGauge64
-    MAX-ACCESS read-only
-    STATUS current
-    DESCRIPTION
-       "Backend QPS"
-    ::= { backendStatEntry 11 }
-
-backendQueries OBJECT-TYPE
-    SYNTAX Counter64
-    MAX-ACCESS read-only
-    STATUS current
-    DESCRIPTION
-       "Number of queries sent to this backend"
-    ::= { backendStatEntry 12 }
-
-backendOrder OBJECT-TYPE
-    SYNTAX CounterBasedGauge64
-    MAX-ACCESS read-only
-    STATUS current
-    DESCRIPTION
-       "Backend order"
-    ::= { backendStatEntry 13 }
-
----
---- Textual Conventions
----
-
-SocketProtocolType ::= TEXTUAL-CONVENTION
-    STATUS      current
-    DESCRIPTION
-        "A value that represents a type of socket protocol."
-    SYNTAX       INTEGER {
-                     unknown(0),
-                     udp(1),
-                     tcp(2)
-                 }
-
-DNSQueryType ::= TEXTUAL-CONVENTION
-    STATUS      current
-    DESCRIPTION
-        "A value that represents a type of DNS query (question or response)."
-    SYNTAX       INTEGER {
-                     unknown(0),
-                     question(1),
-                     response(2)
-                 }
-
----
---- Traps / Notifications
----
-
-trap OBJECT IDENTIFIER ::= { dnsdist 10 }
-traps OBJECT IDENTIFIER ::= { trap 0 } --- reverse-mappable
-trapObjects OBJECT IDENTIFIER ::= { dnsdist 11 }
-
-socketFamily OBJECT-TYPE
-    SYNTAX InetAddressType
-    MAX-ACCESS read-only
-    STATUS current
-    DESCRIPTION
-        "Socket family type"
-    ::= { trapObjects 1 }
-
-socketProtocol OBJECT-TYPE
-    SYNTAX SocketProtocolType
-    MAX-ACCESS read-only
-    STATUS current
-    DESCRIPTION
-        "Socket protocol type"
-    ::= { trapObjects 2 }
-
-fromAddress OBJECT-TYPE
-    SYNTAX OCTET STRING (SIZE (2..24))
-    MAX-ACCESS read-only
-    STATUS current
-    DESCRIPTION
-       "Requestor address"
-    ::= { trapObjects 3 }
-
-toAddress OBJECT-TYPE
-    SYNTAX OCTET STRING (SIZE (2..24))
-    MAX-ACCESS read-only
-    STATUS current
-    DESCRIPTION
-       "Responder address"
-    ::= { trapObjects 4 }
-
-queryType OBJECT-TYPE
-    SYNTAX DNSQueryType
-    MAX-ACCESS read-only
-    STATUS current
-    DESCRIPTION
-        "Query / Response"
-    ::= { trapObjects 5 }
-
-querySize OBJECT-TYPE
-    SYNTAX Unsigned32
-    MAX-ACCESS read-only
-    STATUS current
-    DESCRIPTION
-        "Size in bytes"
-    ::= { trapObjects 6 }
-
-queryID OBJECT-TYPE
-    SYNTAX Unsigned32
-    MAX-ACCESS read-only
-    STATUS current
-    DESCRIPTION
-        "DNS query ID"
-    ::= { trapObjects 7 }
-
-qName OBJECT-TYPE
-    SYNTAX OCTET STRING (SIZE (0..255))
-    MAX-ACCESS read-only
-    STATUS current
-    DESCRIPTION
-        "DNS qname"
-    ::= { trapObjects 8 }
-
-qClass OBJECT-TYPE
-    SYNTAX Unsigned32
-    MAX-ACCESS read-only
-    STATUS current
-    DESCRIPTION
-        "DNS query class"
-    ::= { trapObjects 9 }
-
-qType OBJECT-TYPE
-    SYNTAX Unsigned32
-    MAX-ACCESS read-only
-    STATUS current
-    DESCRIPTION
-        "DNS query type"
-    ::= { trapObjects 10 }
-
-trapReason OBJECT-TYPE
-    SYNTAX OCTET STRING
-    MAX-ACCESS read-only
-    STATUS current
-    DESCRIPTION
-        "Reason for this trap"
-    ::= { trapObjects 11 }
-
-backendStatusChangeTrap NOTIFICATION-TYPE
-    OBJECTS {
-        backendName,
-        backendAddress,
-        backendState
-    }
-    STATUS current
-    DESCRIPTION "Backend status changed"
-    ::= { traps 1 }
-
-actionTrap NOTIFICATION-TYPE
-    OBJECTS {
-        socketFamily,
-        socketProtocol,
-        fromAddress,
-        toAddress,
-        queryType,
-        querySize,
-        queryID,
-        qName,
-        qClass,
-        qType,
-        trapReason
-    }
-    STATUS current
-    DESCRIPTION "Trap sent by SNMPTrapAction"
-    ::= { traps 2 }
-
-customTrap NOTIFICATION-TYPE
-    OBJECTS {
-        trapReason
-    }
-    STATUS current
-    DESCRIPTION "Trap sent by sendCustomTrap"
-    ::= { traps 3 }
-
----
---- Conformance
----
-
-dnsdistConformance OBJECT IDENTIFIER ::= { dnsdist 100 }
-
-dnsdistCompliances MODULE-COMPLIANCE
-    STATUS current
-    DESCRIPTION "dnsdist compliance statement"
-    MODULE
-    MANDATORY-GROUPS {
-        dnsdistGroup,
-        dnsdistTrapsGroup
-    }
-    ::= { dnsdistConformance 1 }
-
-dnsdistGroup OBJECT-GROUP
-    OBJECTS {
-        queries,
-        responses,
-        servfailResponses,
-        aclDrops,
-        ruleDrop,
-        ruleNXDomain,
-        ruleRefused,
-        selfAnswered,
-        downstreamTimeouts,
-        downstreamSendErrors,
-        truncFailures,
-        noPolicy,
-        latency01,
-        latency110,
-        latency1050,
-        latency50100,
-        latency1001000,
-        latencySlow,
-        latencyAVG100,
-        latencyAVG1000,
-        latencyAVG10000,
-        latencyAVG1000000,
-        uptime,
-        realMemoryUsage,
-        nonCompliantQueries,
-        nonCompliantResponses,
-        rdQueries,
-        emptyQueries,
-        cacheHits,
-        cacheMisses,
-        cpuUserMSec,
-        cpuSysMSec,
-        fdUsage,
-        dynBlocked,
-        dynBlockNMGSize,
-        backendName,
-        backendLatency,
-        backendWeight,
-        backendOutstanding,
-        backendQPSLimit,
-        backendReused,
-        backendState,
-        backendAddress,
-        backendPools,
-        backendQPS,
-        backendQueries,
-        backendOrder,
-        socketFamily,
-        socketProtocol,
-        fromAddress,
-        toAddress,
-        queryType,
-        querySize,
-        queryID,
-        qName,
-        qClass,
-        qType,
-        trapReason
-    }
-    STATUS current
-    DESCRIPTION "Objects conformance group for dnsdist"
-    ::= { dnsdistConformance 2 }
-
-dnsdistTrapsGroup NOTIFICATION-GROUP
-    NOTIFICATIONS {
-        actionTrap,
-        customTrap,
-        backendStatusChangeTrap
-    }
-    STATUS current
-    DESCRIPTION "Traps conformance group for dnsdist"
-    ::= { dnsdistConformance 3 }
-
-END
index 5b70bf0641f4e1f66e6dd7c284464d5d7c6af229..2f9b99929fe7dd32a6ce485ea8ca71243aa0931f 100644 (file)
@@ -1,5 +1,4 @@
-dnsdist
--------
+# dnsdist
 `dnsdist` is a highly DNS-, DoS- and abuse-aware loadbalancer. Its goal in
 life is to route traffic to the best server, delivering top performance
 to legitimate users while shunting or blocking abusive traffic.
@@ -8,1745 +7,4 @@ to legitimate users while shunting or blocking abusive traffic.
 runtime, and that its statistics can be queried from a console-like
 interface.
 
-Compiling
----------
-`dnsdist` depends on boost, Lua or LuaJIT and a pretty recent C++
-compiler (g++ 4.8 or higher, clang 3.5 or higher). It can optionally use libsodium
-for encrypted communications with its client, protobuf for remote logging and re2
-for regular expression matching.
-
-Should `dnsdist` be run on a system with systemd, it is highly recommended to have
-the systemd header files (`libsystemd-dev` on Debian and `systemd-devel` on CentOS)
-installed to have `dnsdist` support `systemd-notify`.
-
-To compile on CentOS 6 / RHEL6, use this script to install a working compiler:
-
-```
-wget -O /etc/yum.repos.d/slc6-devtoolset.repo http://linuxsoft.cern.ch/cern/devtoolset/slc6-devtoolset.repo
-yum install devtoolset-2
-scl enable devtoolset-2 bash
-./configure
-make
-```
-
-To build on OS X, `./configure LIBEDIT_LIBS='-L/usr/lib -ledit' LIBEDIT_CFLAGS=-I/usr/include/editline`
-
-To build on OpenBSD, `./configure CXX=eg++ CPP=ecpp LIBEDIT_LIBS='-ledit -lcurses' LIBEDIT_CFLAGS=' '`
-
-On other recent platforms, installing a Lua and the system C++ compiler should be enough. 
-
-`dnsdist` can drop privileges using the `--uid` and `--gid` command line switches
-to ensure it does not run with root privileges after binding its listening sockets.
-It is highly recommended to create a system user and group for `dnsdist`. Note that
-most packaged versions of `dnsdist` already create this user.
-
-Packaged
---------
-We build packages for `dnsdist` on our [repositories](https://repo.powerdns.com). In addition
-`dnsdist` [has been packaged for FreeBSD](https://freshports.org/dns/dnsdist).
-
-Examples
---------
-
-The absolute minimum configuration:
-
-```
-# dnsdist 2001:4860:4860::8888 8.8.8.8
-```
-
-This will listen on 0.0.0.0:53 and forward queries to the two listed IP
-addresses, with a sensible load balancing policy.
-
-Here is a more complete configuration:
-
-```
-$ cat /etc/dnsdist.conf
-newServer({address="2001:4860:4860::8888", qps=1})
-newServer({address="2001:4860:4860::8844", qps=1})
-newServer({address="2620:0:ccc::2", qps=10})
-newServer({address="2620:0:ccd::2", name="dns1", qps=10})
-newServer("192.168.1.2")
-setServerPolicy(firstAvailable) -- first server within its QPS limit
-
-$ dnsdist --local=0.0.0.0:5200
-Marking downstream [2001:4860:4860::8888]:53 as 'up'
-Marking downstream [2001:4860:4860::8844]:53 as 'up'
-Marking downstream [2620:0:ccc::2]:53 as 'up'
-Marking downstream [2620:0:ccd::2]:53 as 'up'
-Marking downstream 192.168.1.2:53 as 'up'
-Listening on 0.0.0.0:5200
-> 
-```
-
-We can now send queries to port 5200, and get answers:
-
-```
-$ dig -t aaaa powerdns.com @127.0.0.1 -p 5200 +short
-2001:888:2000:1d::2
-```
-
-Note that `dnsdist` offered us a prompt above, and on it we can get some
-statistics:
-
-```
-> showServers()
-#   Address                   State     Qps    Qlim Ord Wt    Queries   Drops Drate   Lat Pools
-0   [2001:4860:4860::8888]:53    up     0.0       1   1  1          1       0   0.0   0.0
-1   [2001:4860:4860::8844]:53    up     0.0       1   1  1          0       0   0.0   0.0
-2   [2620:0:ccc::2]:53           up     0.0      10   1  1          0       0   0.0   0.0
-3   [2620:0:ccd::2]:53           up     0.0      10   1  1          0       0   0.0   0.0
-4   192.168.1.2:53               up     0.0       0   1  1          0       0   0.0   0.0
-All                                     0.0                         1       0     
-```
-
-Here we also see our configuration. 5 downstream servers have been configured, of
-which the first 4 have a QPS limit (of 1, 1, 10, 10 and 0 -which means unlimited- queries per second,
-respectively). The final server has no limit, which we can easily test:
-
-```
-$ for a in {0..1000}; do dig powerdns.com @127.0.0.1 -p 5200 +noall > /dev/null; done
-> showServers()
-#   Address                   State     Qps    Qlim Ord Wt    Queries   Drops Drate   Lat Pools
-0   [2001:4860:4860::8888]:53    up     1.0       1   1  1          7       0   0.0   1.6
-1   [2001:4860:4860::8844]:53    up     1.0       1   1  1          6       0   0.0   0.6
-2   [2620:0:ccc::2]:53           up    10.3      10   1  1         64       0   0.0   2.4
-3   [2620:0:ccd::2]:53           up    10.3      10   1  1         63       0   0.0   2.4
-4   192.168.1.2:53               up   125.8       0   1  1        671       0   0.0   0.4
-All                                   145.0                       811       0     
-```
-
-Note that the first 4 servers were all limited to near their configured QPS,
-and that our final server was taking up most of the traffic. No queries were
-dropped, and all servers remain up.
-
-To force a server down, try:
-
-```
-> getServer(0):setDown()
-> showServers()
-#   Address                   State     Qps    Qlim Ord Wt    Queries   Drops Drate   Lat Pools
-0   [2001:4860:4860::8888]:53  DOWN     0.0       1   1  1          8       0   0.0   0.0 
-...
-```
-
-The 'DOWN' in all caps means it was forced down. A lower case 'down'
-would have meant that `dnsdist` itself had concluded the server was down.
-Similarly, setUp() forces a server to be up, and setAuto() returns it to the
-default availability probing.
-
-To change the QPS for a server:
-```
-> getServer(0):setQPS(1000)
-```
-
-By default, the availability of a downstream server is checked by regularly
-sending an A query for `a.root-servers.net.`. A different query type and target
-can be specified by passing, respectively, the `checkType` and `checkName`
-parameters to `newServer`. The default behavior is to consider any valid response
-with an RCODE different from ServFail as valid. If the `mustResolve` parameter
-of `newServer` is set to true, a response will only be considered valid if
-its RCODE differs from NXDomain, ServFail and Refused.
-The number of health check failures before a server is considered down is
-configurable via the `maxCheckFailures` parameter, defaulting to 1.
-The `CD` flag can be set on the query by setting `setCD` to true.
-
-```
-newServer({address="192.0.2.1", checkType="AAAA", checkName="a.root-servers.net.", mustResolve=true})
-```
-
-In order to provide the downstream server with the address of the real client,
-or at least the one talking to `dnsdist`, the `useClientSubnet` parameter can be used
-when declaring a new server. This parameter indicates whether an EDNS Client Subnet option
-should be added to the request. If the incoming request already contains an EDNS Client Subnet value,
-it will not be overridden unless `setECSOverride()` is set to true.
-The default source prefix-length is 24 for IPv4 and 56 for IPv6, meaning that for a query
-received from 192.0.2.42, the EDNS Client Subnet value sent to the backend will
-be 192.0.2.0/24. This can be changed with:
-```
-> setECSSourcePrefixV4(24)
-> setECSSourcePrefixV6(56)
-```
-
-In addition to the global settings, rules and Lua bindings can alter this behavior per query:
-
-* calling `DisableECSAction()` or setting `dq.useECS` to false prevents the sending of the ECS option
-* calling `ECSOverrideAction(bool)` or setting `dq.ecsOverride` will override the global `setECSOverride()` value
-* calling `ECSPrefixLengthAction(v4, v6)` or setting `dq.ecsPrefixLength` will override the global
-`setECSSourcePrefixV4()` and `setECSSourcePrefixV6()` values
-
-In effect this means that for the EDNS Client Subnet option to be added to the request, `useClientSubnet`
-should be set to true for the backend used (default to false) and ECS should not have been disabled by calling
-`DisableECSAction()` or setting `dq.useECS` to false (default to true).
-
-TCP timeouts
-------------
-
-By default, a 2 second timeout is enforced on the TCP connection from the client,
-meaning that a connection will be closed if the query cannot be read in less than 2 seconds
-or if the answer cannot be sent in less than 2s. This can be configured with:
-```
-> setTCPRecvTimeout(5)
-> setTCPSendTimeout(5)
-```
-
-The same kind of timeouts are enforced on the TCP connections to the downstream servers.
-The default value of 30 seconds can be modified by passing the `tcpRecvTimeout` and `tcpSendTimeout`
-parameters to `newServer`, with an additional `tcpConnectTimeout` parameter controlling
-the connection timeout (5s by default). If the TCP connection to a downstream server fails, `dnsdist`
-will try to establish a new one up to `retries` times before giving up.
-```
-newServer({address="192.0.2.1", tcpConnectTimeout=5, tcpRecvTimeout=10, tcpSendTimeout=10, retries=5})
-```
-
-Source address
---------------
-
-In multi-homed setups, it can be useful to be able to select the source address or the outgoing
-interface used by `dnsdist` to contact a downstream server.
-This can be done by using the `source` parameter:
-```
-newServer({address="192.0.2.1", source="192.0.2.127"})
-newServer({address="192.0.2.1", source="eth1"})
-newServer({address="192.0.2.1", source="192.0.2.127@eth1"})
-```
-
-The supported values for `source` are:
-
- * an IPv4 or IPv6 address, which must exist on the system
- * an interface name
- * an IPv4 or IPv6 address followed by '@' then an interface name
-
-Specifying the interface name is only supported on system having `IP_PKTINFO`.
-
-
-Configuration management
-------------------------
-At startup, configuration is read from the command line and the
-configuration file. The config can also be inspected and changed from the
-console. Sadly, our architecture does not allow us to serialize the running
-configuration for you. However, we do try to offer the next best thing:
-`delta()`.
-
-`delta()` shows all commands entered that changed the configuration. So
-adding a new downstream server with `newServer()` would show up, but
-`showServers()` or even `delta()` itself would not.
-
-It is suggested to study the output of `delta()` carefully before appending
-it to your configuration file. 
-
-```
-> setACL("192.0.2.0/24")
-> showACL()
-192.0.2.0/24
-> delta()
--- Wed Dec 23 2015 15:15:35 CET
-setACL("192.0.2.0/24")
-> addACL("127.0.0.1/8")
-> showACL()
-192.0.2.0/24
-127.0.0.1/8
-> delta()
--- Wed Dec 23 2015 15:15:35 CET
-setACL("192.0.2.0/24")
--- Wed Dec 23 2015 15:15:44 CET
-addACL("127.0.0.1/8")
->
-```
-
-
-Webserver
----------
-To visually interact with `dnsdist`, try adding:
-```
-webserver("127.0.0.1:8083", "supersecretpassword", "supersecretAPIkey")
-```
-
-to the configuration, and point your browser at http://127.0.0.1:8083 and
-log in with any username, and that password. Enjoy!
-
-By default, our web server sends some security-related headers:
-
- * X-Content-Type-Options: nosniff
- * X-Frame-Options: deny
- * X-Permitted-Cross-Domain-Policies: none
- * X-XSS-Protection: 1; mode=block
- * Content-Security-Policy: default-src 'self'; style-src 'self' 'unsafe-inline'
-
-You can override those headers, or add custom headers by using the last parameter to
-`webserver()`. For example, to remove the `X-Frame-Options` header and add a
-`X-Custom` one:
-```
-webserver("127.0.0.1:8080", "supersecret", "apikey", {["X-Frame-Options"]= "", ["X-Custom"]="custom"})
-```
-
-
-Server pools
-------------
-Now for some cool stuff. Let's say we know we're getting a whole bunch of
-traffic for a domain used in DoS attacks, for example 'sh43354.cn'. We can
-do two things with this kind of traffic. Either we block it outright, like
-this:
-
-```
-> addDomainBlock("sh43354.cn.")
-```
-
-Or we configure a server pool dedicated to receiving the nasty stuff:
-
-```
-> newServer({address="192.168.1.3", pool="abuse"})
-> addPoolRule({"sh43353.cn.", "ezdns.it."}, "abuse")
-```
-
-The wonderful thing about this last solution is that it can also be used for
-things where a domain might possibly be legit, but it is still causing load
-on the system and slowing down the Internet for everyone. With such an abuse
-server, 'bad traffic' still gets a chance of an answer, but without
-impacting the rest of the world (too much).
-
-We can similarly add clients to the abuse server:
-
-```
-> addPoolRule({"192.168.12.0/24", "192.168.13.14"}, "abuse")
-```
-
-To define a pool that should receive only a QPS-limited amount of traffic, do:
-
-```
-> addQPSPoolRule("com.", 10000, "gtld-cluster")
-```
-
-Traffic exceeding the QPS limit will not match that rule, and subsequent
-rules will apply normally.
-
-Both `addDomainBlock` and `addPoolRule` end up the list of Rules 
-and Actions (for which see below).
-
-Servers can be added to or removed from pools with:
-```
-> getServer(7):addPool("abuse")
-> getServer(4):rmPool("abuse")
-```
-
-
-Rules
------
-Rules can be inspected with `showRules()`, and can be deleted with
-`rmRule()`.  Rules are evaluated in order, and this order can be changed
-with `mvRule(from, to)` (see below for exact semantics).
-
-Rules have selectors and actions. Current selectors are:
-
- * Source address (directly passing a netmask as a string, or via NetmaskGroupRule)
- * Destination address (NetmaskGroupRule)
- * Query type
- * Query domain
- * QPS Limit total
- * QPS Limit per IP address or subnet
- * QClass (QClassRule)
- * QName (QNameRule)
- * QType (QTypeRule)
- * RegexRule on query name
- * RE2Rule on query name (optional)
- * Response code
- * Packet requests DNSSEC processing
- * Packet requests recursion
- * Query received over UDP or TCP
- * Opcode (OpcodeRule)
- * Number of entries in a given section (RecordsCountRule)
- * Number of entries of a specific type in a given section (RecordsTypeCountRule)
- * Presence of trailing data (TrailingDataRule)
- * Number of labels in the qname (QNameLabelsCountRule)
- * Wire length of the qname (QNameWireLengthRule)
-
-Special rules are:
-
- * `AndRule{rule1, rule2}`, which only matches if all of its subrules match
- * `OrRule{rule1, rule2}`, which matches if at least one of its subrules match
- * `NotRule(rule)`, which matches if its subrule does not match
-
-Current actions are:
-
- * Drop (DropAction)
- * Route to a pool (PoolAction)
- * Return with TC=1 (truncated, i.e., instruction to retry with TCP)
- * Force a ServFail, NotImp or Refused answer
- * Send out a crafted response (NXDOMAIN or "real" data)
- * Delay a response by n milliseconds (DelayAction), over UDP only
- * Modify query to clear the RD or CD bit
- * Add the source MAC address to the query (MacAddrAction, only supported on Linux)
- * Skip the cache, if any
- * Log query content to a remote server (RemoteLogAction)
- * Alter the EDNS Client Subnet parameters (DisableECSAction, ECSOverrideAction, ECSPrefixLengthAction)
- * Send an SNMP trap (SNMPTrapAction)
-
-Current response actions are:
-
- * Allow (AllowResponseAction)
- * Delay a response by n milliseconds (DelayResponseAction), over UDP only
- * Drop (DropResponseAction)
- * Log response content to a remote server (RemoteLogResponseAction)
- * Send an SNMP trap (SNMPTrapResponseAction)
-
-Rules can be added via:
-
- * addAction(DNS rule, DNS Action)
- * addAnyTCRule()
- * addDelay(DNS rule, delay in milliseconds)
- * addDisableValidationRule(DNS rule)
- * addDomainBlock(domain)
- * addDomainSpoof(domain, IPv4[, IPv6]) or addDomainSpoof(domain, {IP, IP, IP..})
- * addDomainCNAMESpoof(domain, CNAME)
- * addLuaAction(DNS rule, Lua function)
- * addNoRecurseRule(DNS rule)
- * addPoolRule(DNS rule, destination pool)
- * addQPSLimit(DNS rule, qps limit)
- * addQPSPoolRule(DNS rule, qps limit, destination pool)
-
-Response rules can be added via:
-
- * addResponseAction(DNS rule, DNS Response Action)
- * AddLuaResponseAction(DNS rule, Lua function)
-
-Cache Hit Response rules, triggered on a cache hit, can be added via:
-
- * addCacheHitResponseAction(DNS rule, DNS Response Action)
-
-A DNS rule can be:
-
- * A string that is either a domain name or netmask
- * A list of strings that are either domain names or netmasks
- * A DNSName
- * A list of DNSNames
- * an AllRule
- * an AndRule
- * a DNSSECRule
- * a MaxQPSIPRule
- * a MaxQPSRule
- * a NetmaskGroupRule
- * a NotRule
- * an OpcodeRule
- * an OrRule
- * a QClassRule
- * a QNameLabelsCountRule
- * a QNameRule
- * a QNameWireLengthRule
- * a QTypeRule
- * a RCodeRule
- * a RDRule
- * a RegexRule
- * a RE2Rule
- * a RecordsCountRule
- * a RecordsTypeCountRule
- * a SuffixMatchNodeRule
- * a TCPRule
- * a TimedIPSetRule
- * a TrailingDataRule
-
-Some specific actions do not stop the processing when they match, contrary to all other actions:
-
- * Delay
- * DisableECS
- * Disable Validation
- * ECSOverride
- * ECSPrefixLength
- * Log
- * MacAddr
- * No Recurse
- * SNMP Trap
- * and of course None
-
-A convenience function `makeRule()` is supplied which will make a NetmaskGroupRule for you or a SuffixMatchNodeRule
-depending on how you call it. `makeRule("0.0.0.0/0")` will for example match all IPv4 traffic, `makeRule({"be","nl","lu"})` will
-match all Benelux DNS traffic.
-
-All the current rules can be removed at once with:
-
-```
-> clearRules()
-```
-
-It is also possible to replace the current rules by a list of new ones in a
-single operation with `setRules()`:
-
-```
-> setRules( { newRuleAction(TCPRule(), AllowAction()), newRuleAction(AllRule(), DropAction()) } )
-```
-
-NOTE: Adding large numbers of rules (200+) is slow, and will also impact performance significantly. Instead of creating numerous rules, consider using smaller numbers of individual rules that match large numbers of domains or IP addresses, for example using a `SuffixMatchNodeRule` or a `NetmaskGroupRule`. These rules are optimized for hosting thousands or millions of domain names or IP addresses. 
-
-More power
-----------
-More powerful things can be achieved by defining a function called
-`blockFilter()` in the configuration file, which can decide to drop traffic
-on any reason it wants. If you return 'true' from there, the query will get
-blocked.
-
-A demo on how to do this and many other things can be found on
-https://github.com/powerdns/pdns/blob/master/pdns/dnsdistconf.lua and
-the exact definition of `blockFilter()` is at the end of this document.
-
-ANY or whatever to TC
----------------------
-The `blockFilter()` also gets passed read/writable copy of the DNS Header,
-via `dq.dh`.
-If you invoke setQR(1) on that, `dnsdist` knows you turned the packet into
-a response, and will send the answer directly to the original client.
-
-If you also called setTC(1), this will tell the remote client to move to
-TCP, and in this way you can implement ANY-to-TCP even for downstream
-servers that lack this feature.
-
-Note that calling `addAnyTCRule()` achieves the same thing, without
-involving Lua.
-
-Rules for traffic exceeding QPS limits
---------------------------------------
-Traffic that exceeds a QPS limit, in total or per IP (subnet) can be matched by a rule.
-
-For example:
-
-```
-addDelay(MaxQPSIPRule(5, 32, 48), 100)
-```
-
-This measures traffic per IPv4 address and per /48 of IPv6, and if traffic for such 
-an address (range) exceeds 5 qps, it gets delayed by 100ms.
-
-As another example:
-
-```
-addAction(MaxQPSIPRule(5), NoRecurseAction())
-```
-
-This strips the Recursion Desired (RD) bit from any traffic per IPv4 or IPv6 /64 
-that exceeds 5 qps. This means any those traffic bins is allowed to make a recursor do 'work'
-for only 5 qps.
-
-If this is not enough, try:
-
-```
-addAction(MaxQPSIPRule(5), DropAction())
--- or
-addAction(MaxQPSIPRule(5), TCAction())
-```
-
-This will respectively drop traffic exceeding that 5 QPS limit per IP or range, or return it with TC=1, forcing
-clients to fall back to TCP.
-
-To turn this per IP or range limit into a global limit, use NotRule(MaxQPSRule(5000)) instead of MaxQPSIPRule.
-
-TeeAction
----------
-This action sends off a copy of a UDP query to another server, and keeps statistics
-on the responses received. Sample use:
-
-```
-> addAction(AllRule(), TeeAction("192.168.1.54"))
-> getAction(0):printStats()
-refuseds       0
-nxdomains      0
-noerrors       0
-servfails      0
-recv-errors    0
-tcp-drops      0
-responses      0
-other-rcode    0
-send-errors    0
-queries        0
-```
-
-It is also possible to share a TeeAction between several rules. Statistics
-will be combined in that case.
-
-Lua actions in rules
---------------------
-While we can pass every packet through the `blockFilter()` functions, it is also
-possible to configure `dnsdist` to only hand off some packets for Lua inspection. 
-If you think Lua is too slow for your query load, or if you are doing heavy processing in Lua, 
-this may make sense.
-
-To select specific packets for Lua attention, use `addLuaAction(x, func)`,
-where x is either a netmask, or a domain suffix, or a table of netmasks or a
-table of domain suffixes.  This is identical to how `addPoolRule()` selects.
-
-The function should look like this:
-```
-function luarule(dq)
-        if(dq.qtype==35) -- NAPTR
-        then
-                return DNSAction.Pool, "abuse" -- send to abuse pool
-        else
-                return DNSAction.None, ""      -- no action
-        end
-end
-```
-
-Valid return values for `LuaAction` functions are:
-
- * DNSAction.Allow: let the query pass, skipping other rules
- * DNSAction.Delay: delay the response for the specified milliseconds (UDP-only), continue to the next rule
- * DNSAction.Drop: drop the query
- * DNSAction.HeaderModify: indicate that the query has been turned into a response
- * DNSAction.None: continue to the next rule
- * DNSAction.Nxdomain: return a response with a NXDomain rcode
- * DNSAction.Pool: use the specified pool to forward this query
- * DNSAction.Refused: return a response with a Refused rcode
- * DNSAction.Spoof: spoof the response using the supplied string (CNAME) value or a comma-separated list of IPv4 (A) or IPv6 (AAAA)
- * DNSAction.Truncate: return a response with TC=1
-
-The same feature exists to hand off some responses for Lua inspection, using `addLuaResponseAction(x, func)`.
-
-DNSSEC
-------
-To provide DNSSEC service from a separate pool, try:
-```
-newServer({address="2001:888:2000:1d::2", pool="dnssec"})
-newServer({address="2a01:4f8:110:4389::2", pool="dnssec"})
-setDNSSECPool("dnssec")
-topRule()
-```
-
-This routes all queries with a DNSSEC OK (DO) or CD bit set to on to the "dnssec" pool.
-The final `topRule()` command moves this rule to the top, so it gets evaluated first.
-
-Regular Expressions
--------------------
-`RegexRule()` matches a regular expression on the query name, and it works like this:
-
-```
-addAction(RegexRule("[0-9]{5,}"), DelayAction(750)) -- milliseconds
-addAction(RegexRule("[0-9]{4,}\\.cn$"), DropAction())
-```
-
-This delays any query for a domain name with 5 or more consecutive digits in it.
-The second rule drops anything with more than 4 consecutive digits within a .CN domain.
-
-Note that the query name is presented without a trailing dot to the regex.
-The regex is applied case insensitively. 
-
-Alternatively, if compiled in, RE2Rule provides similar functionality, but against libre2.
-
-Runtime-modifiable IP address sets
-----------------------------------
-From within maintenance() or other places, we may find that certain IP
-addresses must be treated differently for a certain time.
-
-This may be used to temporarily shunt traffic to another pool for example.
-
-`TimedIPSetRule()` creates an object to which native IP addresses can be
-added in ComboAddress form. 
-
-The following methods are available on this rule:
-
- * `add(CA, seconds)`: Add an IP address to the set for the next `second` seconds
- * `cleanup()`: Purge the set from expired IP addresses
- * `clear()`: Clear the entire set
- * `slice()`: Convert the TimedIPSetRule into a DNSRule that can be passed to `addAction()`
-
-A working example:
-
-```
-tisrElGoog=TimedIPSetRule()
-tisrRest=TimedIPSetRule()
-addAction(tisrElGoog:slice(), PoolAction("elgoog"))
-addAction(tisrRest:slice(), PoolAction(""))
-
-elgoogPeople=newNMG()
-elgoogPeople:addMask("192.168.5.0/28")
-
-function pickPool(dq)
-       if(elgoogPeople:match(dq.remoteaddr)) -- in real life, this would be external
-       then
-               print("Lua caught query for a googlePerson")
-               tisrElGoog:add(dq.remoteaddr, 10)
-               return DNSAction.Pool, "elgoog"
-       else
-               print("Lua caught query for restPerson")
-               tisrRest:add(dq.remoteaddr, 60)
-               return DNSAction.None, ""
-       end
-end
-
-addLuaAction(AllRule(), pickPool)
-```
-
-Inspecting live traffic
------------------------
-This is still much in flux, but for now, try:
-
- * `grepq(Netmask|DNS Name|100ms [, n])`: shows the last n queries and responses matching the specified client address or range (Netmask), or the specified DNS Name, or slower than 100ms
- * `grepq({"::1", "powerdns.com", "100ms"} [, n])`: shows the last n queries and responses matching the specified client address AND range (Netmask) AND the specified DNS Name AND slower than 100ms
- * `topBandwidth(top)`: show top-`top` clients that consume the most bandwidth over length of ringbuffer
- * `topClients(n)`: show top-`n` clients sending the most queries over length of ringbuffer
- * `topQueries(20)`: shows the top-20 queries
- * `topQueries(20,2)`: shows the top-20 two-level domain queries (so `topQueries(20,1)` only shows TLDs)
- * `topResponses(20, 2)`: top-20 servfail responses (use ,3 for NXDOMAIN)
- * `topSlow([top][, limit][, labels])`: show `top` queries slower than `limit` milliseconds, grouped by last `labels` labels
-
-For example:
-```
-> grepq("127.0.0.1/24")
-Time    Client                                          Server       ID    Name                      Type  Lat.   TC RD AA Rcode
--11.9   127.0.0.1:52599                                              16127 nxdomain.powerdns.com.    A               RD    Question
--11.7   127.0.0.1:52599                                 127.0.0.1:53 16127 nxdomain.powerdns.com.    A     175.6     RD    Non-Existent domain
-> grepq("powerdns.com")
-Time    Client                                          Server       ID    Name                      Type  Lat.   TC RD AA Rcode
--38.7   127.0.0.1:52599                                              16127 nxdomain.powerdns.com.    A               RD    Question
--38.6   127.0.0.1:52599                                 127.0.0.1:53 16127 nxdomain.powerdns.com.    A     175.6     RD    Non-Existent domain
-```
-
-Live histogram of latency
--------------------------
-```
-> showResponseLatency()
-Average response latency: 78.84 msec
-   msec        
-   0.10        
-   0.20        .
-   0.40        **********************
-   0.80        ***********
-   1.60        .
-   3.20        
-   6.40        .
-  12.80        *
-  25.60        *
-  51.20        *
- 102.40        **********************************************************************
- 204.80        *************************
- 409.60        **
- 819.20        :
-1638.40        .
-```
-
-Where : stands for 'half a star' and . for 'less than half a star, but
-something was there'.
-
-Per domain or subnet QPS limiting
----------------------------------
-If certain domains or source addresses are generating onerous amounts of
-traffic, you can put ceilings on the amount of traffic you are willing to
-forward:
-
-```
-> addQPSLimit("h4xorbooter.xyz.", 10)
-> addQPSLimit({"130.161.0.0/16", "145.14.0.0/16"} , 20)
-> addQPSLimit({"nl.", "be."}, 1)
-> showRules()
-#     Matches Rule                                               Action
-0           0 h4xorbooter.xyz.                                   qps limit to 10
-1           0 130.161.0.0/16, 145.14.0.0/16                      qps limit to 20
-2           0 nl., be.                                           qps limit to 1
-```
-
-To delete a limit (or a rule in general):
-```
-> rmRule(1)
-> showRules()
-#     Matches Rule                                               Action
-0           0 h4xorbooter.xyz.                                   qps limit to 10
-1           0 nl., be.                                           qps limit to 1
-```
-
-Delaying answers
-----------------
-Sometimes, runaway scripts will hammer your servers with back-to-back
-queries.  While it is possible to drop such packets, this may paradoxically
-lead to more traffic. 
-
-An attractive middleground is to delay answers to such back-to-back queries,
-causing a slowdown on the side of the source of the traffic.
-
-To do so, use:
-```
-> addDelay("yourdomain.in.ua.", 500)
-> addDelay({"65.55.37.0/24"}, 500)
-```
-This will delay responses for questions to the mentioned domain, or coming
-from the configured subnet, by half a second.
-
-Like the QPSLimits and other rules, the delaying instructions can be
-inspected or edited using `showRules()`, `rmRule()`, `topRule()`, `mvRule()` etc.
-
-Dynamic load balancing
-----------------------
-The default load balancing policy is called `leastOutstanding`, which means
-we pick the server with the least queries 'in the air' (and within those,
-the one with the lowest `order`, and within those, the one with the lowest latency).
-
-Another policy, `firstAvailable`, picks the first server that has not
-exceeded its QPS limit. If all servers are above their QPS limit, a
-server is selected based on the `leastOutstanding` policy. For now this
-is the only policy using the QPS limit.
-
-A further policy, `wrandom` assigns queries randomly, but based on the
-`weight` parameter passed to `newServer`. `whashed` is a similar weighted policy,
-but assigns questions with identical hash to identical servers, allowing for
-better cache concentration ('sticky queries').
-
-If you don't like the default policies you can create your own, like this
-for example:
-
-```
-counter=0
-function luaroundrobin(servers, dq)
-        counter=counter+1
-        return servers[1+(counter % #servers)]
-end
-
-setServerPolicyLua("luaroundrobin", luaroundrobin)
-```
-
-Incidentally, this is similar to setting: `setServerPolicy(roundrobin)`
-which uses the C++ based roundrobin policy.
-
-Lua server policies 
--------------------
-If the built in rules do not suffice to pick a server pool, full flexibility is available from Lua. For example:
-
-```
-newServer("192.168.1.2")
-newServer({address="8.8.4.4", pool="numbered"})
-
-function splitSetup(servers, dq)
-         if(string.match(dq.qname:toString(), "%d"))
-         then
-                print("numbered pool")
-                return leastOutstanding.policy(getPoolServers("numbered"), dq)
-         else
-                print("standard pool")
-                return leastOutstanding.policy(servers, dq)
-         end
-end
-
-setServerPolicyLua("splitsetup", splitSetup)
-```
-
-This will forward queries containing a number to the pool of "numbered" 
-servers, and will apply the default load balancing policy to all other
-queries.
-
-Dynamic Rule Generation
------------------------
-To set dynamic rules, based on recent traffic, define a function called `maintenance()` in Lua. It will
-get called every second, and from this function you can set rules to block traffic based on statistics.
-More exactly, the thread handling the `maintenance()` function will sleep for one second between each
-invocation, so if the function takes several seconds to complete it will not be invoked exactly every second.
-
-As an example:
-
-```
-function maintenance()
-       addDynBlocks(exceedQRate(20, 10), "Exceeded query rate", 60)
-end
-```
-
-This will dynamically block all hosts that exceeded 20 queries/s as measured
-over the past 10 seconds, and the dynamic block will last for 60 seconds.
-
-Dynamic blocks in force are displayed with `showDynBlocks()` and can be cleared
-with `clearDynBlocks()`. Full set of `exceed` functions is listed in the table of
-all functions below. They return a table whose key is a `ComboAddress` object,
-representing the client's source address, and whose value is an integer representing
-the number of queries matching the corresponding condition (for example the
-`qtype` for `exceedQTypeRate()`, `rcode` for `exceedServFails()`).
-
-Dynamic blocks drop matched queries by default, but this behavior can be changed
-with `setDynBlocksAction()`. For example, to send a REFUSED code instead of droppping
-the query:
-
-```
-setDynBlocksAction(DNSAction.Refused)
-```
-
-Running it for real
--------------------
-First run on the command line, and generate a key:
-
-```
-# dnsdist
-> makeKey()
-setKey("sepuCcHcQnSAZgNbNPCCpDWbujZ5esZJmrt/wh6ldkQ=")
-```
-
-Now add this setKey line to `dnsdist.conf`, and also add:
-
-```
-controlSocket("0.0.0.0") -- or add portnumber too
-```
-
-Then start `dnsdist` as a daemon, and then connect to it:
-```
-# dnsdist --daemon
-# dnsdist --client
-> 
-```
-
-Please note that, without libsodium support, 'makeKey()' will return
-setKey("plaintext") and the communication between the client and the
-server will not be encrypted.
-
-Some versions of libedit, notably the CentOS 6 one, may require the following
-addition to ~/.editrc in order to support searching through the history:
-
-```
-bind "^R" em-inc-search-prev
-```
-
-ACL, who can use dnsdist
-------------------------
-For safety reasons, by default only private networks can use `dnsdist`, see below
-how to query and change the ACL:
-
-```
-> showACL()
-127.0.0.0/8
-10.0.0.0/8
-(...)
-::1/128
-fc00::/7
-fe80::/10
-> addACL("130.161.0.0/16")
-> setACL({"::/0"}) -- resets the list to this array
-> showACL()
-::/0
-```
-
-Caching
--------
-`dnsdist` implements a simple but effective packet cache, not enabled by default.
-It is enabled per-pool, but the same cache can be shared between several pools.
-The first step is to define a cache, then to assign that cache to the chosen pool,
-the default one being represented by the empty string:
-
-```
-pc = newPacketCache(10000, 86400, 0, 60, 60, false)
-getPool(""):setCache(pc)
-```
-
-The first parameter (10000) is the maximum number of entries stored in the cache, and is the
-only one required. The second, third, fourth and fifth parameters are optional and in seconds.
-The second one (86400) is the maximum lifetime of an entry in the cache, the third one (0) is
-the minimum TTL an entry should have to be considered for insertion in the cache,
-the fourth one (60) is the TTL used for a Server Failure or a Refused response. The fifth
-one (60) is the TTL that will be used when a stale cache entry is returned. The last one
-is a boolean that indicates whether the TTL of reponses should be reduced by the number of
-seconds the response has been in the cache.
-For performance reasons the cache will pre-allocate buckets based on the maximum number
-of entries, so be careful to set the first parameter to a reasonable value. Something
-along the lines of a dozen bytes per pre-allocated entry can be expected on 64-bit.
-That does not mean that the memory is completely allocated up-front, the final memory
-usage depending mostly on the size of cached responses and therefore varying during the
-cache's lifetime. Assuming an average response size of 512 bytes, a cache size of
-10000000 entries on a 64-bit host with 8GB of dedicated RAM would be a safe choice.
-
-The `setStaleCacheEntriesTTL(n)` directive can be used to allow `dnsdist` to use
-expired entries from the cache when no backend is available. Only entries that have
-expired for less than `n` seconds will be used, and the returned TTL can be set
-when creating a new cache with `newPacketCache()`.
-
-A reference to the cache affected to a specific pool can be retrieved with:
-
-```
-getPool("poolname"):getCache()
-```
-
-And removed with:
-
-```
-getPool("poolname"):unsetCache()
-```
-
-Cache usage stats (hits, misses, deferred inserts and lookups, collisions)
-can be displayed by using the `printStats()` method:
-
-```
-getPool("poolname"):getCache():printStats()
-```
-
-Expired cached entries can be removed from a cache using the `purgeExpired(n)`
-method, which will remove expired entries from the cache until at most `n`
-entries remain in the cache. For example, to remove all expired entries:
-
-```
-getPool("poolname"):getCache():purgeExpired(0)
-```
-
-Specific entries can also be removed using the `expungeByName(DNSName [, qtype=ANY, suffixMatch=false])`
-method. If suffixMatch is set to true it will remove any entries below DNSName.
-
-```
-getPool("poolname"):getCache():expungeByName(newDNSName("powerdns.com"), dnsdist.A, true)
-```
-
-Finally, the `expunge(n)` method will remove all entries until at most `n`
-entries remain in the cache:
-
-```
-getPool("poolname"):getCache():expunge(0)
-```
-
-
-Performance tuning
-------------------
-First, a few words about `dnsdist` architecture:
-
- * Each local bind has its own thread listening for incoming UDP queries
- * and its own thread listening for incoming TCP connections,
- dispatching them right away to a pool of threads
- * Each backend has its own thread listening for UDP responses
- * A maintenance thread calls the `maintenance()` Lua function every second
- if any, and is responsible for cleaning the cache
- * A health check thread checks the backends availability
- * A control thread handles console connections
- * A carbon thread exports statistics to carbon servers if needed
- * One or more webserver threads handle queries to the internal webserver
-
-The maximum number of threads in the TCP pool is controlled by the
-`setMaxTCPClientThreads()` directive, and defaults to 10. This number can be
-increased to handle a large number of simultaneous TCP connections.
-If all the TCP threads are busy, new TCP connections are queued while
-they wait to be picked up. The maximum number of queued connections
-can be configured with `setMaxTCPQueuedConnections()` and defaults to 1000.
-Any value larger than 0 will cause new connections to be dropped if there are
-already too many queued.
-By default, every TCP worker thread has its own queue, and the incoming TCP
-connections are dispatched to TCP workers on a round-robin basis. This might
-cause issues if some connections are taking a very long time, since incoming
-ones will be waiting until the TCP worker they have been assigned to has finished
-handling its current query, while other TCP workers might be available.
-The experimental `setTCPUseSinglePipe(true)` directive can be used so that all the
-incoming TCP connections are put into a single queue and handled by the
-first TCP worker available.
-
-When dispatching UDP queries to backend servers, `dnsdist` keeps track of at
-most `n` outstanding queries for each backend. This number `n` can be tuned by
-the `setMaxUDPOutstanding()` directive, defaulting to 10240, with a maximum
-value of 65535. Large installations are advised to increase the default value
-at the cost of a slightly increased memory usage.
-
-Most of the query processing is done in C++ for maximum performance,
-but some operations are executed in Lua for maximum flexibility:
-
- * the `blockfilter()` function
- * rules added by `addLuaAction()`
- * server selection policies defined via `setServerPolicyLua()` or `newServerPolicy()`
-
-While Lua is fast, its use should be restricted to the strict necessary in order
-to achieve maximum performance, it might be worth considering using LuaJIT instead
-of Lua. When Lua inspection is needed, the best course of action is to restrict
-the queries sent to Lua inspection by using `addLuaAction()` instead of inspecting
-all queries in the `blockfilter()` function.
-
-`dnsdist` design choices mean that the processing of UDP queries is done by only
-one thread per local bind. This is great to keep lock contention to a low level,
-but might not be optimal for setups using a lot of processing power, caused for
-example by a large number of complicated rules. To be able to use more CPU cores
-for UDP queries processing, it is possible to use the `reuseport` parameter of
-the `addLocal()` and `setLocal()` directives to be able to add several identical
-local binds to `dnsdist`:
-
-```
-addLocal("192.0.2.1:53", { reusePort=true })
-addLocal("192.0.2.1:53", { reusePort=true })
-addLocal("192.0.2.1:53", { reusePort=true })
-addLocal("192.0.2.1:53", { reusePort=true })
-```
-
-`dnsdist` will then add four identical local binds as if they were different IPs
-or ports, start four threads to handle incoming queries and let the kernel load
-balance those randomly to the threads, thus using four CPU cores for rules
-processing. Note that this require SO_REUSEPORT support in the underlying
-operating system (added for example in Linux 3.9).
-Please also be aware that doing so will increase lock contention and might not
-therefore scale linearly. This is especially true for Lua-intensive setups,
-because Lua processing in `dnsdist` is serialized by an unique lock for all
-threads.
-
-Another possibility is to use the reuseport option to run several `dnsdist`
-processes in parallel on the same host, thus avoiding the lock contention issue
-at the cost of having to deal with the fact that the different processes will
-not share informations, like statistics or DDoS offenders.
-
-The UDP threads handling the responses from the backends do not use a lot of CPU,
-but if needed it is also possible to add the same backend several times to the
-`dnsdist` configuration to distribute the load over several responder threads.
-
-```
-newServer({address="192.0.2.127:53", name="Backend1"})
-newServer({address="192.0.2.127:53", name="Backend2"})
-newServer({address="192.0.2.127:53", name="Backend3"})
-newServer({address="192.0.2.127:53", name="Backend4"})
-```
-
-
-Carbon/Graphite/Metronome
--------------------------
-To emit metrics to Graphite, or any other software supporting the Carbon protocol, use:
-```
-carbonServer('ip-address-of-carbon-server', 'ourname', 30)
-```
-
-Where 'ourname' can be used to override your hostname, and '30' is the
-reporting interval in seconds.  The last two arguments can be omitted.  The
-latest version of [PowerDNS
-Metronome](https://github.com/ahupowerdns/metronome) comes with attractive
-graphs for `dnsdist` by default.
-
-Query counters
--------------
-When using `carbonServer`, it is also possible to send per-records statistics of
-the amount of queries by using `setQueryCount(true)`. With query counting enabled,
-`dnsdist` will increase a counter for every unique record or the behaviour you define
-in a custom Lua function by setting `setQueryCountFilter(func)`. This filter can decide
-whether to keep count on a query at all or rewrite for which query the counter will be
-increased.
-An example of a `QueryCountFilter` would be:
-
-```
-function filter(dq)
-  qname = dq.qname:toString()
-
-  -- don't count PTRs at all
-  if(qname:match('in%-addr.arpa$')) then
-    return false, ""
-  end
-
-  -- count these queries as if they were queried without leading www.
-  if(qname:match('^www.')) then
-    qname = qname:gsub('^www.', '')
-  end
-
-  -- count queries by default
-  return true, qname
-end
-
-setQueryCountFilter(filter)
-```
-
-Valid return values for `QueryCountFilter` functions are:
-
-* `true`: count the specified query
-* `false`: don't count the query
-
-Note that the query counters are buffered and flushed each time statistics are
-sent to the carbon server. The current content of the buffer can be inspected
-with `getQueryCounters()`.  If you decide to enable query counting without
-`carbonServer`, make sure you implement clearing the log from `maintenance()`
-by issuing `clearQueryCounters()`.
-
-DNSCrypt
---------
-`dnsdist`, when compiled with --enable-dnscrypt, can be used as a DNSCrypt server,
-uncurving queries before forwarding them to downstream servers and curving responses back.
-To make `dnsdist` listen to incoming DNSCrypt queries on 127.0.0.1 port 8443,
-with a provider name of "2.providername", using a resolver certificate and associated key
-stored respectively in the `resolver.cert` and `resolver.key` files, the `addDnsCryptBind()`
-directive can be used:
-
-```
-addDNSCryptBind("127.0.0.1:8443", "2.providername", "/path/to/resolver.cert", "/path/to/resolver.key")
-```
-
-To generate the provider and resolver certificates and keys, you can simply do:
-
-```
-> generateDNSCryptProviderKeys("/path/to/providerPublic.key", "/path/to/providerPrivate.key")
-Provider fingerprint is: E1D7:2108:9A59:BF8D:F101:16FA:ED5E:EA6A:9F6C:C78F:7F91:AF6B:027E:62F4:69C3:B1AA
-> generateDNSCryptCertificate("/path/to/providerPrivate.key", "/path/to/resolver.cert", "/path/to/resolver.key", serial, validFrom, validUntil)
-```
-
-Note that 'validFrom' and 'validUntil' are UNIX epoch timestamps. These can
-easily be calculated as 'os.time(), os.time()+2*365*86400' for example to
-get a certificate that is valid for two years from now.
-
-Ideally, the certificates and keys should be generated on an offline dedicated hardware and not on the resolver.
-The resolver key should be regularly rotated and should never touch persistent storage, being stored in a tmpfs
-with no swap configured.
-
-You can display the currently configured DNSCrypt binds with:
-```
-> showDNSCryptBinds()
-#   Address              Provider Name        Serial   Validity              P. Serial P. Validity
-0   127.0.0.1:8443       2.name               14       2016-04-10 08:14:15   0         -
-```
-
-If you forgot to write down the provider fingerprint value after generating the provider keys, you can use `printDNSCryptProviderFingerprint()` to retrieve it later:
-```
-> printDNSCryptProviderFingerprint("/path/to/providerPublic.key")
-Provider fingerprint is: E1D7:2108:9A59:BF8D:F101:16FA:ED5E:EA6A:9F6C:C78F:7F91:AF6B:027E:62F4:69C3:B1AA
-```
-
-AXFR, IXFR and NOTIFY
----------------------
-When `dnsdist` is deployed in front of a master authoritative server, it might
-receive AXFR or IXFR queries destined to this master. There are two issues
-that can arise in this kind of setup:
-
- * If the master is part of a pool of servers, the first SOA query can be directed
-   by `dnsdist` to a different server than the following AXFR/IXFR one, which might
-   fail if the servers are not perfectly synchronised.
- * If the master only allows AXFR/IXFR based on the source address of the requestor,
-   it might be confused by the fact that the source address will be the one from
-   the `dnsdist` server.
-
-The first issue can be solved by routing SOA, AXFR and IXFR requests explicitly
-to the master:
-
-```
-> newServer({address="192.168.1.2", name="master", pool={"master", "otherpool"}})
-> addAction(OrRule({QTypeRule(dnsdist.SOA), QTypeRule(dnsdist.AXFR), QTypeRule(dnsdist.IXFR)}), PoolAction("master"))
-```
-
-The second one might require allowing AXFR/IXFR from the `dnsdist` source address
-and moving the source address check on `dnsdist`'s side:
-
-```
-> addAction(AndRule({OrRule({QTypeRule(dnsdist.AXFR), QTypeRule(dnsdist.IXFR)}), NotRule(makeRule("192.168.1.0/24"))}), RCodeAction(dnsdist.REFUSED))
-```
-
-When `dnsdist` is deployed in front of slaves, however, an issue might arise with NOTIFY
-queries, because the slave will receive a notification coming from the `dnsdist` address,
-and not the master's one. One way to fix this issue is to allow NOTIFY from the `dnsdist`
-address on the slave side (for example with PowerDNS's `trusted-notification-proxy`) and
-move the address check on `dnsdist`'s side:
-
-```
-> addAction(AndRule({OpcodeRule(DNSOpcode.Notify), NotRule(makeRule("192.168.1.0/24"))}), RCodeAction(dnsdist.REFUSED))
-```
-
-eBPF Socket Filtering
----------------------
-`dnsdist` can use eBPF socket filtering on recent Linux kernels (4.1+) built with eBPF
-support (`CONFIG_BPF`, `CONFIG_BPF_SYSCALL`, ideally `CONFIG_BPF_JIT`).
-This feature might require an increase of the memory limit associated to a socket, via
-the `sysctl` setting `net.core.optmem_max`. When attaching an eBPF program to a socket,
-the size of the program is checked against this limit, and the default value might not be
-enough. Large map sizes might also require an increase of `RLIMIT_MEMLOCK`.
-
-This feature allows `dnsdist` to ask the kernel to discard incoming packets in kernel-space
-instead of them being copied to userspace just to be dropped, thus being a lot of faster.
-
-The BPF filter can be used to block incoming queries manually:
-
-```
-> bpf = newBPFFilter(1024, 1024, 1024)
-> bpf:attachToAllBinds()
-> bpf:block(newCA("2001:DB8::42"))
-> bpf:blockQName(newDNSName("evildomain.com"), 255)
-> bpf:getStats()
-[2001:DB8::42]: 0
-evildomain.com. 255: 0
-> bpf:unblock(newCA("2001:DB8::42"))
-> bpf:unblockQName(newDNSName("evildomain.com"), 255)
-> bpf:getStats()
->
-```
-
-The `blockQName()` method can be used to block queries based on the exact qname supplied,
-in a case-insensitive way, and an optional qtype. Using the 255 (ANY) qtype will block all
-queries for the qname, regardless of the qtype.
-Contrary to source address filtering, qname filtering only works over UDP. TCP qname
-filtering can be done the usual way:
-
-```
-> addAction(AndRule({TCPRule(true), makeRule("evildomain.com")}), DropAction())
-```
-
-The `attachToAllBinds()` method attaches the filter to every existing bind at runtime,
-but it's also possible to define a default BPF filter at configuration time, so
-it's automatically attached to every bind:
-
-```
-bpf = newBPFFilter(1024, 1024, 1024)
-setDefaultBPFFilter(bpf)
-```
-
-Finally, it's also possible to attach it to specific binds at runtime:
-
-```
-> bpf = newBPFFilter(1024, 1024, 1024)
-> showBinds()
-#   Address              Protocol  Queries
-0   [::]:53              UDP       0
-1   [::]:53              TCP       0
-> bd = getBind(0)
-> bd:attachFilter(bpf)
-```
-
-`dnsdist` also supports adding dynamic, expiring blocks to a BPF filter:
-
-```
-bpf = newBPFFilter(1024, 1024, 1024)
-setDefaultBPFFilter(bpf)
-dbpf = newDynBPFFilter(bpf)
-function maintenance()
-        addBPFFilterDynBlocks(exceedQRate(20, 10), dbpf, 60)
-        dbpf:purgeExpired()
-end
-```
-
-This will dynamically block all hosts that exceeded 20 queries/s as measured
-over the past 10 seconds, and the dynamic block will last for 60 seconds.
-
-This feature has been successfully tested on Arch Linux, Arch Linux ARM,
-Fedora Core 23 and Ubuntu Xenial.
-
-SNMP support
-------------
-`dnsdist` supports exporting statistics and sending traps over SNMP when compiled
-with `Net SNMP` support, acting as an `AgentX` subagent.
-`SNMP` support is enabled via the `snmpAgent(enableTraps [, masterSocket])` directive,
-where `enableTraps` is a boolean indicating whether traps should be sent and `masterSocket`
-is an optional string specifying how to connect to the master agent. The default for this
-last parameter is to use an Unix socket, but others options are available, such as TCP: `tcp:localhost:705`
-
-By default, the only traps sent when `enableTraps` is set to `true` are backend status change notifications, but traps can also be sent:
-
- * from Lua, with `sendCustomTrap(string)` and `dq:sendTrap(string)`
- * for selected queries and responses, using `SNMPTrapAction([string])` and `SNMPTrapResponseAction([string])`
-
-`Net SNMP snmpd` doesn't accept subagent connections by default, so to use the `SNMP`
-features of `dnsdist` the following line should be added to the `snmpd.conf` configuration
-file:
-
-```
-master agentx
-```
-
-In addition to that, the permissions on the resulting socket might need to be adjusted
-so that the `dnsdist` user can write to it. This can be done with the following lines in
-`snmpd.conf` (assuming `dnsdist` is running as `dnsdist:dnsdist`):
-
-```
-agentxperms 0700 0700 dnsdist dnsdist
-```
-
-In order to allow the retrieval of statistics via `SNMP`, `snmpd`'s access control
-has to configured. A very simple `SNMPv2c` setup only needs the configuration of
-a read-only community in `snmpd.conf`:
-
-```
-rocommunity dnsdist42
-```
-
-`snmpd` also supports more secure `SNMPv3` setup, using for example the `createUser` and
-`rouser` directives:
-
-```
-createUser myuser SHA "my auth key" AES "my enc key"
-rouser myuser
-```
-
-`snmpd` can be instructed to send `SNMPv2` traps to a remote `SNMP` trap receiver by adding the
-following directive to the `snmpd.conf` configuration file:
-
-```
-trap2sink 192.0.2.1
-```
-
-The description of `dnsdist`'s `SNMP MIB` is available in `DNSDIST-MIB.txt`.
-
-All functions and types
------------------------
-Within `dnsdist` several core object types exist:
-
- * Server: generated with newServer, represents a downstream server
- * ComboAddress: represents an IP address and port
- * DNSName: represents a domain name
- * NetmaskGroup: represents a group of netmasks
- * QPSLimiter: implements a QPS-based filter
- * SuffixMatchNode: represents a group of domain suffixes for rapid testing of membership
- * DNSHeader: represents the header of a DNS packet
-
-The existence of most of these objects can mostly be ignored, unless you
-plan to write your own hooks and policies, but it helps to understand an
-expressions like:
-
-```
-> getServer(0).order=12         -- set order of server 0 to 12
-> getServer(0):addPool("abuse") -- add this server to the abuse pool
-```
-The '.' means 'order' is a data member, while the ':' means addPool is a member function.
-
-Here are all functions:
-
- * Practical
-    * `shutdown()`: shut down `dnsdist`
-    * quit or ^D: exit the console
-    * `webserver(address:port, password [, apiKey [, customHeaders ]])`: launch a webserver with stats on that address with that password
-    * `includeDirectory(dir)`: all files ending in `.conf` in the directory `dir` are loaded into the configuration. Starting with 1.2.0 they are loaded in a sorted manner. Sorting order is ascending and case sensitive.
-    * `setAPIWritable(bool, [dir])`: allow modifications via the API. If `dir` is set, it must be a valid directory where the configuration files will be written by the API. Otherwise the modifications done via the API will not be written to the configuration and will not persist after a reload
- * ACL related:
-    * `addACL(netmask)`: add to the ACL set who can use this server
-    * `setACL({netmask, netmask})`: replace the ACL set with these netmasks. Use `setACL({})` to reset the list, meaning no one can use us
-    * `showACL()`: show our ACL set
- * ClientState related:
-    * function `showBinds()`: list every local bind
-    * function `getBind(n)`: return the corresponding `ClientState` object
-    * member `attachFilter(BPFFilter)`: attach a BPF Filter to this bind
-    * member `detachFilter()`: detach the BPF Filter attached to this bind, if any
-    * member `muted`: if set to true, UDP responses will not be sent for queries received on this bind. Default to false
-    * member `toString()`: print the address this bind listens to
- * Network related:
-    * `addLocal(addr, [, {doTCP=true, reusePort=false, tcpFastOpenSize=0, interface=\"\"}])`: add `addr` to the list of addresses we listen on. The second parameter is an optional table: `doTCP` sets TCP or not (UDP is always enabled), `reusePort` sets SO_REUSEPORT when available, `tcpFastOpenSize` sets the TCP Fast Open queue size, enabling TCP Fast Open when available and the value is larger than 0, `interface` sets the network interface to use
-    * `setLocal(addr, [, {doTCP=true, reusePort=false, tcpFastOpenSize=0, interface=\"\"}])`: reset list of addresses we listen on to this address. The second parameter is the same optional table than the one described in `addLocal()`
- * Blocking related:
-    * `addDomainBlock(domain)`: block queries within this domain
- * Carbon/Graphite/Metronome statistics related:
-    * `carbonServer(serverIP, [ourname], [interval])`: report statistics to serverIP using our hostname, or 'ourname' if provided, every 'interval' seconds
- * Query counting related:
-    * `clearQueryCounters()`: clears the query counter buffer.
-    * `getQueryCounters([max])`: show current buffer of query counters, limited by `max` if provided.
-    * `setQueryCount(bool)`: set whether queries should be counted.
-    * `setQueryCountFilter(func)`: filter queries that would be counted, where `func` is a function with parameter `dq` which decides whether a query should and how it should be counted.
- * Control socket related:
-    * `makeKey()`: generate a new server access key, emit configuration line ready for pasting
-    * `setKey(key)`: set access key to that key.
-    * `testCrypto()`: test of the crypto all works
-    * `controlSocket(addr)`: open a control socket on this address / connect to this address in client mode
- * Diagnostics and statistics
-    * `dumpStats()`: print all statistics we gather
-    * `getStatisticsCounters()`: return the statistics counters as a Lua table
-    * `grepq(Netmask|DNS Name|100ms [, n])`: shows the last n queries and responses matching the specified client address or range (Netmask), or the specified DNS Name, or slower than 100ms
-    * `grepq({"::1", "powerdns.com", "100ms"} [, n])`: shows the last n queries and responses matching the specified client address AND range (Netmask) AND the specified DNS Name AND slower than 100ms
-    * `topQueries(n[, labels])`: show top 'n' queries, as grouped when optionally cut down to 'labels' labels
-    * `topResponses(n, kind[, labels])`: show top 'n' responses with RCODE=kind (0=NO Error, 2=ServFail, 3=ServFail), as grouped when optionally cut down to 'labels' labels
-    * `topSlow([top][, limit][, labels])`: show `top` queries slower than `limit` milliseconds, grouped by last `labels` labels
-    * `topBandwidth(top)`: show top-`top` clients that consume the most bandwidth over length of ringbuffer
-    * `topClients(n)`: show top-`n` clients sending the most queries over length of ringbuffer
-    * `setRingBuffersSize(n)`: set the capacity of the ringbuffers used for live traffic inspection to `n` (default to 10000)
-    * `showResponseLatency()`: show a plot of the response time latency distribution
-    * `showTCPStats()`: show some statistics regarding TCP
-    * `showVersion()`: show the current version of dnsdist
- * Logging related
-    * `infolog(string)`: log at level info
-    * `warnlog(string)`: log at level warning
-    * `errlog(string)`: log at level error
-    * `setVerboseHealthChecks(bool)`: set whether health check errors will be logged
- * Server related:
-    * `newServer("ip:port")`: instantiate a new downstream server with default settings
-    * `newServer({address="ip:port", qps=1000, order=1, weight=10, pool="abuse", retries=5, tcpConnectTimeout=5, tcpSendTimeout=30, tcpRecvTimeout=30, tcpFastOpen=false, checkName="a.root-servers.net.", checkType="A", setCD=false, maxCheckFailures=1, mustResolve=false, useClientSubnet=true, source="address|interface name|address@interface"})`:
-instantiate a server with additional parameters
-    * `showServers()`: output all servers
-    * `getServer(n)`: returns server with index n 
-    * `getServers()`: returns a table with all defined servers
-    * `rmServer(n)`: remove server with index n
-    * `rmServer(server)`: remove this server object
- * Server member functions:
-    * `addPool(pool)`: add this server to that pool
-    * `getName()`: return the server name if any
-    * `getNameWithAddr()`: return a string containing the server name if any plus the server address and port
-    * `getOutstanding()`: this *returns* the number of outstanding queries (doesn't print it!)
-    * `rmPool(pool)`: remove server from that pool
-    * `setQPS(n)`: set the QPS setting to n
-    * `setAuto()`: set this server to automatic availability testing
-    * `setDown()`: force this server to be down
-    * `setUp()`: force this server to be UP
-    * `isUp()`: if this server is available
- * Server member data:
-    * `upStatus`: if `dnsdist` considers this server available (overridden by `setDown()` and `setUp()`)
-    * `name`: name of the server
-    * `order`: order of this server in order-based server selection policies
-    * `weight`: weight of this server in weighted server selection policies
- * Rule related:
-    * `AllRule()`: matches all traffic
-    * `AndRule()`: matches if all sub-rules matches
-    * `DNSSECRule()`: matches queries with the DO flag set
-    * `MaxQPSIPRule(qps, v4Mask=32, v6Mask=64)`: matches traffic exceeding the qps limit per subnet
-    * `MaxQPSRule(qps)`: matches traffic **not** exceeding this qps limit
-    * `NetmaskGroupRule(nmg, [src-bool])`: matches traffic from/to the specified network range. Pass `false` as second parameter to match against the destination address (ie the local one) instead of the source one
-    * `NotRule()`: matches if the sub-rule does not match
-    * `OrRule()`: matches if at least one of the sub-rules matches
-    * `OpcodeRule()`: matches queries with the specified opcode
-    * `QClassRule(qclass)`: matches queries with the specified qclass (numeric)
-    * `QNameLabelsCountRule(min, max)`: matches if the qname has less than `min` or more than `max` labels
-    * `QNameRule(qname)`: matches queries with the specified qname
-    * `QNameWireLengthRule(min, max)`: matches if the qname's length on the wire is less than `min` or more than `max` bytes
-    * `QTypeRule(qtype)`: matches queries with the specified qtype
-    * `RCodeRule(rcode)`: matches queries or responses the specified rcode
-    * `RDRule()`: matches queries with the `RD` flag set
-    * `RegexRule(regex)`: matches the query name against the supplied regex
-    * `RecordsCountRule(section, minCount, maxCount)`: matches if there is at least `minCount` and at most `maxCount` records in the `section` section
-    * `RecordsTypeCountRule(section, type, minCount, maxCount)`: matches if there is at least `minCount` and at most `maxCount` records of type `type` in the `section` section
-    * `RE2Rule(regex)`: matches the query name against the supplied regex using the RE2 engine
-    * `SuffixMatchNodeRule(smn, [quiet-bool])`: matches based on a group of domain suffixes for rapid testing of membership. Pass `true` as second parameter to prevent listing of all domains matched.
-    * `TCPRule(tcp)`: matches question received over TCP if `tcp` is true, over UDP otherwise
-    * `TimedIPSetRule()`: rule which matches a runtime-modifiable set of IP addresses, which also expire
-    * `TrailingDataRule()`: matches if the query has trailing data
- * Rule management related:
-    * `clearRules()`: remove all current rules
-    * `getAction(num)`: returns the Action associate with rule 'num'.
-    * `mvCacheHitResponseRule(from, to)`: move cache hit response rule 'from' to a position where it is in front of 'to'. 'to' can be one larger than the largest rule,
-     in which case the rule will be moved to the last position.
-    * `mvResponseRule(from, to)`: move response rule 'from' to a position where it is in front of 'to'. 'to' can be one larger than the largest rule,
-     in which case the rule will be moved to the last position.
-    * `mvRule(from, to)`: move rule 'from' to a position where it is in front of 'to'. 'to' can be one larger than the largest rule,
-     in which case the rule will be moved to the last position.
-    * `newRuleAction(DNS Rule, DNS Action)`: return a pair of DNS Rule and DNS Action, to be used with `setRules()`
-    * `rmCacheHitResponseRule(n)`: remove cache hit response rule n
-    * `rmResponseRule(n)`: remove response rule n
-    * `rmRule(n)`: remove rule n
-    * `setRules(list)`: replace the current rules with the supplied list of pairs of DNS Rules and DNS Actions (see `newRuleAction()`)
-    * `showCacheHitResponseRules()`: show all defined cache hit response rules
-    * `showResponseRules()`: show all defined response rules
-    * `showRules()`: show all defined rules
-    * `topCacheHitResponseRule()`: move the last cache hit response rule to the first position
-    * `topResponseRule()`: move the last response rule to the first position
-    * `topRule()`: move the last rule to the first position
- * Built-in Actions for Rules:
-    * `AllowAction()`: let these packets go through
-    * `AllowResponseAction()`: let these packets go through
-    * `DelayAction(milliseconds)`: delay the response by the specified amount of milliseconds (UDP-only)
-    * `DelayResponseAction(milliseconds)`: delay the response by the specified amount of milliseconds (UDP-only)
-    * `DisableECSAction()`: disable the sending of ECS to the backend
-    * `DisableValidationAction()`: set the CD bit in the question, let it go through
-    * `DropAction()`: drop these packets
-    * `DropResponseAction()`: drop these packets
-    * `ECSOverrideAction(bool)`: whether an existing ECS value should be overridden (true) or not (false)
-    * `ECSPrefixLengthAction(v4, v6)`: set the ECS prefix length
-    * `LogAction([filename], [binary], [append], [buffered])`: Log a line for each query, to the specified file if any, to the console (require verbose) otherwise. When logging to a file, the `binary` optional parameter specifies whether we log in binary form (default) or in textual form, the `append` optional parameter specifies whether we open the file for appending or truncate each time (default), and the `buffered` optional parameter specifies whether writes to the file are buffered (default) or not.
-    * `MacAddrAction(option code)`: add the source MAC address to the query as EDNS0 option `option code`. This action is currently only supported on Linux
-    * `NoRecurseAction()`: strip RD bit from the question, let it go through
-    * `PoolAction(poolname)`: set the packet into the specified pool
-    * `QPSPoolAction(maxqps, poolname)`: set the packet into the specified pool only if it **does not** exceed the specified QPS limits, letting the subsequent rules apply otherwise
-    * `QPSAction(rule, maxqps)`: drop these packets if the QPS limits are exceeded
-    * `RCodeAction(rcode)`: reply immediatly by turning the query into a response with the specified rcode
-    * `RemoteLogAction(RemoteLogger [, alterFunction])`: send the content of this query to a remote logger via Protocol Buffer. `alterFunction` is a callback, receiving a DNSQuestion and a DNSDistProtoBufMessage, that can be used to modify the Protocol Buffer content, for example for anonymization purposes
-    * `RemoteLogResponseAction(RemoteLogger [,alterFunction [,includeCNAME]])`: send the content of this response to a remote logger via Protocol Buffer. `alterFunction` is the same callback than the one in `RemoteLogAction` and `includeCNAME` indicates whether CNAME records inside the response should be parsed and exported. The default is to only exports A and AAAA records
-    * `SkipCacheAction()`: don't lookup the cache for this query, don't store the answer
-    * `SNMPTrapAction([reason])`: send an SNMP trap, adding the optional `reason` string as the query description
-    * `SNMPTrapResponseAction([reason])`: send an SNMP trap, adding the optional `reason` string as the response description
-    * `SpoofAction(ip[, ip])` or `SpoofAction({ip, ip, ..}): forge a response with the specified IPv4 (for an A query) or IPv6 (for an AAAA). If you specify multiple addresses, all that match the query type (A, AAAA or ANY) will get spoofed in
-    * `SpoofCNAMEAction(cname)`: forge a response with the specified CNAME value
-    * `TCAction()`: create answer to query with TC and RD bits set, to move to TCP
-    * `TeeAction(remote[, addECS])`: send copy of query to remote, keep stats on responses. If `addECS` is set to `true`, EDNS Client Subnet information will be added to the query
- * Specialist rule generators
-    * `addAnyTCRule()`: generate TC=1 answers to ANY queries received over UDP, moving them to TCP
-    * `addDomainSpoof(domain, ip[, ip6])` or `addDomainSpoof(domain, {IP, IP, IP..})`: generate answers for A/AAAA/ANY queries using the ip parameters
-    * `addDomainCNAMESpoof(domain, cname)`: generate CNAME answers for queries using the specified value
-    * `addDisableValidationRule(domain)`: set the CD flags to 1 for all queries matching the specified domain
-    * `addNoRecurseRule(domain)`: clear the RD flag for all queries matching the specified domain
-    * `setDNSSECPool(pool)`: move queries requesting DNSSEC processing to this pool
- * Policy member data:
-    * `name`: the policy name
-    * `policy`: the policy function
- * Pool related:
-    * `addPoolRule(domain, pool)`: send queries to this domain to that pool
-    * `addPoolRule({domain, domain}, pool)`: send queries to these domains to that pool
-    * `addPoolRule(netmask, pool)`: send queries from this netmask to that pool
-    * `addPoolRule({netmask, netmask}, pool)`: send queries from these netmasks to that pool
-    * `addQPSPoolRule(x, limit, pool)`: like `addPoolRule`, but only select at most 'limit' queries/s for this pool, letting the subsequent rules apply otherwise
-    * `getPool(poolname)`: return the ServerPool named `poolname`
-    * `getPoolServers(pool)`: return servers part of this pool
-    * `showPools()`: list the current server pools
- * Lua Action related:
-    * `addLuaAction(x, func)`: where 'x' is all the combinations from `addPoolRule`, and func is a 
-      function with the parameter `dq`, which returns an action to be taken on this packet.
-    * `addLuaResponseAction(x, func)`: where 'x' is all the combinations from `addPoolRule`, and func is a
-      function with the parameter `dr`, which returns an action to be taken on this response packet.
-      Good for rare packets but where you want to do a lot of processing.
- * Server selection policy related:
-    * `setWHashedPertubation(value)`: set the hash perturbation value to be used in the `whashed` policy instead of a random one, allowing to have consistent `whashed` results on different instances
-    * `setServerPolicy(policy)`: set server selection policy to that policy
-    * `setServerPolicyLua(name, function)`: set server selection policy to one named 'name' and provided by 'function'
-    * `showServerPolicy()`: show name of currently operational server selection policy
-    * `newServerPolicy(name, function)`: create a policy object from a Lua function
-    * `setServFailWhenNoServer(bool)`: if set, return a ServFail when no servers are available, instead of the default behaviour of dropping the query
-    * `setPoolServerPolicy(policy, pool)`: set the server selection policy for this pool to that policy
-    * `setPoolServerPolicyLua(name, function, poool)`: set the server selection policy for this pool to one named 'name' and provided by 'function'
-    * `showPoolServerPolicy()`: show server selection policy for this pool
- * Available policies:
-    * `firstAvailable`: Pick first server that has not exceeded its QPS limit, ordered by the server 'order' parameter
-    * `whashed`: Weighted hashed ('sticky') distribution over available servers, based on the server 'weight' parameter
-    * `wrandom`: Weighted random over available servers, based on the server 'weight' parameter
-    * `roundrobin`: Simple round robin over available servers
-    * `leastOutstanding`: Send traffic to downstream server with least outstanding queries, with the lowest 'order', and within that the lowest recent latency
- * Shaping related:
-    * `addQPSLimit(domain, n)`: limit queries within that domain to n per second
-    * `addQPSLimit({domain, domain}, n)`: limit queries within those domains (together) to n per second
-    * `addQPSLimit(netmask, n)`: limit queries within that netmask to n per second
-    * `addQPSLimit({netmask, netmask}, n)`: limit queries within those netmasks (together) to n per second   
- * Delaying related:
-    * `addDelay(domain, n)`: delay answers within that domain by n milliseconds
-    * `addDelay({domain, domain}, n)`: delay answers within those domains (together) by n milliseconds
-    * `addDelay(netmask, n)`: delay answers within that netmask by n milliseconds
-    * `addDelay({netmask, netmask}, n)`: delay answers within those netmasks (together) by n milliseconds
- * Answer changing functions:
-    * `truncateTC(bool)`: if set (defaults to no starting with dnsdist 1.2.0) truncate TC=1 answers so they are actually empty. Fixes an issue for PowerDNS Authoritative Server 2.9.22. Note: turning this on breaks compatibility with RFC 6891.
-    * `fixupCase(bool)`: if set (default to no), rewrite the first qname of the question part of the answer to match the one from the query. It is only useful when you have a downstream server that messes up the case of the question qname in the answer
- * Dynamic Block related:
-    * `maintenance()`: called every second by dnsdist if defined, call functions below from it
-    * `clearDynBlocks()`: clear all dynamic blocks
-    * `showDynBlocks()`: show dynamic blocks in force
-    * `addDynBlocks(addresses, message[, seconds[, action]])`: block the set of addresses with message `msg`, for `seconds` seconds (10 by default), applying `action` (default to the one set with `setDynBlocksAction()`)
-    * `setDynBlocksAction(DNSAction)`: set which action is performed when a query is blocked. Only DNSAction.Drop (the default), DNSAction.Refused and DNSAction.Truncate are supported
-    * `addBPFFilterDynBlocks(addresses, DynBPFFilter[, seconds])`: block the set of addresses using the supplied BPF Filter, for `seconds` seconds (10 by default)
-    * `exceedServFails(rate, seconds)`: get set of addresses that exceed `rate` servfails/s over `seconds` seconds
-    * `exceedNXDOMAINs(rate, seconds)`: get set of addresses that exceed `rate` NXDOMAIN/s over `seconds` seconds
-    * `exceedRespByterate(rate, seconds)`: get set of addresses that exceeded `rate` bytes/s answers over `seconds` seconds
-    * `exceedQRate(rate, seconds)`: get set of address that exceed `rate` queries/s over `seconds` seconds
-    * `exceedQTypeRate(type, rate, seconds)`: get set of address that exceed `rate` queries/s for queries of type `type` over `seconds` seconds
- * ServerPool related:
-    * `getCache()`: return the current packet cache, if any
-    * `setCache(PacketCache)`: set the cache for this pool
-    * `unsetCache()`: remove the packet cache from this pool
- * PacketCache related:
-    * `expunge(n)`: remove entries from the cache, leaving at most `n` entries
-    * `expungeByName(DNSName [, qtype=ANY, suffixMatch=false])`: remove entries matching the supplied DNSName and type from the cache. If suffixMatch is specified also removes names below DNSName
-    * `isFull()`: return true if the cache has reached the maximum number of entries
-    * `newPacketCache(maxEntries[, maxTTL=86400, minTTL=0, temporaryFailureTTL=60, staleTTL=60, dontAge=false])`: return a new PacketCache
-    * `printStats()`: print the cache stats (hits, misses, deferred lookups and deferred inserts)
-    * `purgeExpired(n)`: remove expired entries from the cache until there is at most `n` entries remaining in the cache
-    * `toString()`: return the number of entries in the Packet Cache, and the maximum number of entries
- * Advanced functions for writing your own policies and hooks
-    * ComboAddress related:
-        * `newCA(address)`: return a new ComboAddress
-        * `getPort()`: return the port number
-        * `isIPv4()`: return true if the address is an IPv4, false otherwise
-        * `isIPv6()`: return true if the address is an IPv6, false otherwise
-        * `isMappedIPv4()`: return true if the address is an IPv4 mapped into an IPv6, false otherwise
-        * `mapToIPv4()`: convert an IPv4 address mapped in a v6 one into an IPv4
-        * `tostring()`: return in human-friendly format
-        * `toString()`: alias for `tostring()`
-        * `tostringWithPort()`: return in human-friendly format, with port number
-        * `toStringWithPort()`: alias for `tostringWithPort()`
-        * `truncate(bits)`: truncate the address to the specified number of bits
-    * DNSName related:
-        * `newDNSName(name)`: make a DNSName based on this .-terminated name
-        * member `chopOff()`: remove left-most label and return true, or false if there are no labels
-        * member `countLabels()`: return the number of labels
-        * member `isPartOf(dnsname)`: is this dnsname part of that dnsname
-        * member `tostring()`: return as a human friendly . terminated string
-        * member `toString()`: alias for `tostring()`
-        * member `wirelength()`: return the length on the wire
-    * DNSQuestion related:
-        * member `dh`: DNSHeader
-        * member `ecsOverride`: whether an existing ECS value should be overridden (settable)
-        * member `ecsPrefixLength`: the ECS prefix length to use (settable)
-        * member `getDO()`: return true if the DNSSEC OK (DO) bit is set
-        * member `len`: the question length
-        * member `localaddr`: ComboAddress of the local bind this question was received on
-        * member `opcode`: the question opcode
-        * member `qname`: DNSName of this question
-        * member `qclass`: QClass (as an unsigned integer) of this question
-        * member `qtype`: QType (as an unsigned integer) of this question
-        * member `remoteaddr`: ComboAddress of the remote client
-        * member `rcode`: RCode of this question
-        * member `sendTrap([reason])`: send a trap containing the description of the query, and the optional `reason` string
-        * member `size`: the total size of the buffer starting at `dh`
-        * member `skipCache`: whether to skip cache lookup / storing the answer for this question (settable)
-        * member `tcp`: whether this question was received over a TCP socket
-        * member `useECS`: whether to send ECS to the backend (settable)
-    * DNSResponse gets the same member than DNSQuestion, plus some:
-        * member `editTTLs(func)`: the function `func` is invoked for every entries in the answer, authority
-        and additional section taking the section number (1 for answer, 2 for authority, 3 for additional),
-        the qclass and qtype values and the current TTL, and returning the new TTL or 0 to leave it unchanged
-    * DNSHeader related
-        * member `getRD()`: get recursion desired flag
-        * member `setRD(bool)`: set recursion desired flag
-        * member `setTC(bool)`: set truncation flag (TC)
-        * member `setQR(bool)`: set Query Response flag (setQR(true) indicates an *answer* packet)
-        * member `getCD()`: get checking disabled flag
-        * member `setCD(bool)`: set checking disabled flag
-    * NetmaskGroup related
-        * function `newNMG()`: returns a NetmaskGroup
-        * member `addMask(mask)`: adds `mask` to the NetmaskGroup. Prefix with `!` to exclude this mask from matching.
-        * member `addMasks(table)`: adds the keys of `table` to the NetmaskGroup. `table` should be a table whose keys
-        are `ComboAddress` objects and values are integers, as returned by `exceed*` functions
-        * member `match(ComboAddress)`: checks if ComboAddress is matched by this NetmaskGroup
-        * member `clear()`: clears the NetmaskGroup
-        * member `size()`: returns number of netmasks in this NetmaskGroup
-    * QPSLimiter related:
-        * `newQPSLimiter(rate, burst)`: configure a QPS limiter with that rate and that burst capacity
-        * member `check()`: check if this QPSLimiter has a token for us. If yes, you must use it.
-    * SuffixMatchNode related:
-        * `newSuffixMatchNode()`: returns a new SuffixMatchNode
-        * member `check(DNSName)`: returns true if DNSName is matched by this group
-        * member `add(DNSName)`: add this DNSName to the node
- * Tuning related:
-    * `setMaxTCPClientThreads(n)`: set the maximum of TCP client threads, handling TCP connections
-    * `setMaxTCPConnectionDuration(n)`: set the maximum duration of an incoming TCP connection, in seconds. 0 (the default) means unlimited
-    * `setMaxTCPConnectionsPerClient(n)`: set the maximum number of TCP connections per client. 0 (the default) means unlimited
-    * `setMaxTCPQueriesPerConnection(n)`: set the maximum number of queries in an incoming TCP connection. 0 (the default) means unlimited
-    * `setMaxTCPQueuedConnections(n)`: set the maximum number of TCP connections queued (waiting to be picked up by a client thread), defaults to 1000. 0 means unlimited
-    * `setMaxUDPOutstanding(n)`: set the maximum number of outstanding UDP queries to a given backend server. This can only be set at configuration time and defaults to 10240
-    * `setCacheCleaningDelay(n)`: set the interval in seconds between two runs of the cache cleaning algorithm, removing expired entries
-    * `setCacheCleaningPercentage(n)`: set the percentage of the cache that the cache cleaning algorithm will try to free by removing expired entries. By default (100), all expired entries are removed
-    * `setStaleCacheEntriesTTL(n)`: allows using cache entries expired for at most `n` seconds when no backend available to answer for a query
-    * `setTCPDownstreamCleanupInterval(interval)`: minimum interval in seconds between two cleanups of the idle TCP downstream connections. Defaults to 60s
-    * `setTCPUseSinglePipe(bool)`: whether the incoming TCP connections should be put into a single queue instead of using per-thread queues. Defaults to false
-    * `setTCPRecvTimeout(n)`: set the read timeout on TCP connections from the client, in seconds
-    * `setTCPSendTimeout(n)`: set the write timeout on TCP connections from the client, in seconds
-    * `setUDPTimeout(n)`: set the maximum time dnsdist will wait for a response from a backend over UDP, in seconds. Defaults to 2
- * DNSCrypt related:
-    * `addDNSCryptBind("127.0.0.1:8443", "provider name", "/path/to/resolver.cert", "/path/to/resolver.key", [, {doTCP=true, reusePort=false, tcpFastOpenSize=0, interface=\"\"}]):` listen to incoming DNSCrypt queries on 127.0.0.1 port 8443, with a provider name of "provider name", using a resolver certificate and associated key stored respectively in the `resolver.cert` and `resolver.key` files. The fifth parameter is the same optional table than the one described in `addLocal()`, except that TCP is always enabled
-    * `generateDNSCryptProviderKeys("/path/to/providerPublic.key", "/path/to/providerPrivate.key"):` generate a new provider keypair
-    * `generateDNSCryptCertificate("/path/to/providerPrivate.key", "/path/to/resolver.cert", "/path/to/resolver.key", serial, validFrom, validUntil):` generate a new resolver private key and related certificate, valid from the `validFrom` UNIX timestamp until the `validUntil` one, signed with the provider private key
-    * `getDNSCryptBind(n)`: return the `DNSCryptContext` object corresponding to the bind `n`
-    * `printDNSCryptProviderFingerprint("/path/to/providerPublic.key")`: display the fingerprint of the provided resolver public key
-    * `showDNSCryptBinds():`: display the currently configured DNSCrypt binds
- * BPFFilter related:
-    * function `newBPFFilter(maxV4, maxV6, maxQNames)`: return a new eBPF socket filter with a maximum of maxV4 IPv4, maxV6 IPv6 and maxQNames qname entries in the block tables
-    * function `setDefaultBPFFilter(BPFFilter)`: when used at configuration time, the corresponding BPFFilter will be attached to every bind
-    * member `attachToAllBinds()`: attach this filter to every bind already defined. This is the run-time equivalent of `setDefaultBPFFilter(bpf)`
-    * member `block(ComboAddress)`: block this address
-    * member `blockQName(DNSName [, qtype=255])`: block queries for this exact qname. An optional qtype can be used, default to 255
-    * member `getStats()`: print the block tables
-    * member `unblock(ComboAddress)`: unblock this address
-    * member `unblockQName(DNSName [, qtype=255])`: remove this qname from the block list
- * DNSCryptCert related:
-    * member `getClientMagic`: return this certificate's client magic value, as a string
-    * member `getEsVersion()`: return the cryptographic construction to use with this certificate, as a string
-    * member `getMagic()`: return the certificate magic number, as a string
-    * member `getProtocolMinorVersion()`: return this certificate's minor version, as a string
-    * member `getResolverPublicKey()`: return the public key corresponding to this certificate, as a string
-    * member `getSerial()`: return the certificate serial number
-    * member `getSignature()`: return this certificate's signature, as a string
-    * member `getTSEnd()`: return the date the certificate is valid from, as a Unix timestamp
-    * member `getTSStart()`: return the date the certificate is valid until (inclusive), as a Unix timestamp
- * DNSCryptContext related:
-    * member `generateAndLoadInMemoryCertificate(path/to/provider/private/key/file, serial, begin, end)`: generate a new resolver key and the associated certificate in-memory, sign it with the provided provider key, and use the new certificate
-    * member `getCurrentCertificate()`: return the current certificate as a `DnsCryptCert` object
-    * member `getOldCertificate()`: return the previous certificate as a `DnsCryptCert` object
-    * member `getProviderName()`: return the provider name
-    * member `hasOldCertificate()`: return a boolean indicating if the context has a previous certificate, from a certificate rotation
-    * member `loadNewCertificate(path/to/certificate, path/to/key)`: load a new certificate and the corresponding private key, and use it
- * DNSDistProtoBufMessage related:
-    * member `setBytes(bytes)`: set the size of the query
-    * member `setEDNSSubnet(Netmask)`: set the EDNS Subnet
-    * member `setQueryTime(sec, usec)`: in a response message, set the time at which the query has been received
-    * member `setQuestion(DNSName, qtype, qclass)`: set the question
-    * member `setRequestor(ComboAddress)`: set the requestor
-    * member `setRequestorFromString(string)`: set the requestor
-    * member `setResponder(ComboAddress)`: set the responder
-    * member `setResponderFromString(string)`: set the responder
-    * member `setResponseCode(rcode)`: set the response code
-    * member `setTime(sec, usec)`: set the time at which the query or response has been received
-    * member `toDebugString()`: return an string containing the content of the message
- * DynBPFFilter related:
-    * function `newDynBPFFilter(BPFFilter)`: return a new DynBPFFilter object using this BPF Filter
-    * member `block(ComboAddress[, seconds]): add this address to the underlying BPF Filter for `seconds` seconds (default to 10 seconds)
-    * member `purgeExpired()`: remove expired entries
-    * function `registerDynBPFFilter(DynBPFFilter)`: register this dynamic BPF filter into the web interface so that its counters are displayed
-    * function `unregisterDynBPFFilter(DynBPFFilter)`: unregister this dynamic BPF filter
- * RemoteLogger related:
-    * `newRemoteLogger(address:port [, timeout=2, maxQueuedEntries=100, reconnectWaitTime=1])`: create a Remote Logger object, to use with `RemoteLogAction()` and `RemoteLogResponseAction()`
- * SNMP related:
-    * `snmpAgent(enableTraps [, masterSocket])`: enable `SNMP` support. `enableTraps` is a boolean indicating whether traps should be sent and `masterSocket` an optional string specifying how to connect to the master agent
-    * `sendCustomTrap(str)`: send a custom `SNMP` trap from Lua, containing the `str` string
-
-All hooks
----------
-`dnsdist` can call Lua per packet if so configured, and will do so with the following hooks:
-
-  * `bool blockFilter(dq)`: if defined, called for every packet. If this
-    returns true, the packet is dropped. If false is returned, `dnsdist` will check if the DNSHeader indicates
-    the packet is now a query response. If so, `dnsdist` will answer the client directly with the modified packet.
-  * `server policy(candidates, DNSQuestion)`: if configured with `setServerPolicyLua()`
-    gets called for every packet. Candidates is a table of potential servers to pick from, ComboAddress is the 
-    address of the requestor, DNSName and qtype describe name and type of query. DNSHeader meanwhile is available for 
-    your inspection.
-
-
-  
+All `dnsdist` features are documented at [dnsdist.org](http://dnsdist.org).
index 0cc6785d1cd4692cf96cdf09f7f66af9b7cd801f..1bb513a65af31e01cefd0bf372b0810846f5e816 100644 (file)
@@ -35,3 +35,9 @@
 /dnsdist.service
 /lua.hpp
 /test-driver
+dnsdist.pdf
+html-docs
+html-docs.tar.bz2
+doctrees/
+latex/
+.doctrees/
deleted file mode 120000 (symlink)
index e406bb937617cd0a065e3b32e810efc12abcd024..0000000000000000000000000000000000000000
+++ /dev/null
@@ -1 +0,0 @@
-../../docs/MIBS/DNSDIST-MIB.txt
\ No newline at end of file
new file mode 100644 (file)
index 0000000000000000000000000000000000000000..bf1097c0fa1339ff288dbfbfc039feff2126be64
--- /dev/null
@@ -0,0 +1,703 @@
+-- -*- snmpv2 -*-
+-- ----------------------------------------------------------------------
+-- MIB file for dnsdist
+-- ----------------------------------------------------------------------
+
+DNSDIST-MIB DEFINITIONS ::= BEGIN
+
+IMPORTS
+    OBJECT-TYPE, MODULE-IDENTITY, enterprises,
+    Counter64, Unsigned32, NOTIFICATION-TYPE
+        FROM SNMPv2-SMI
+    CounterBasedGauge64
+        FROM HCNUM-TC
+    Float64TC
+        FROM FLOAT-TC-MIB
+    OBJECT-GROUP, MODULE-COMPLIANCE, NOTIFICATION-GROUP
+        FROM SNMPv2-CONF
+    InetAddressType
+        FROM INET-ADDRESS-MIB
+    TEXTUAL-CONVENTION, DisplayString
+        FROM SNMPv2-TC;
+
+dnsdist MODULE-IDENTITY
+    LAST-UPDATED "201611080000Z"
+    ORGANIZATION "PowerDNS BV"
+    CONTACT-INFO "support@powerdns.com"
+    DESCRIPTION
+       "This MIB module describes information gathered through dnsdist."
+
+    REVISION "201611080000Z"
+    DESCRIPTION "Initial revision."
+
+    ::= { powerdns 3 }
+
+powerdns               OBJECT IDENTIFIER ::= { enterprises 43315 }
+
+stats OBJECT IDENTIFIER ::= { dnsdist 1 }
+
+queries OBJECT-TYPE
+    SYNTAX Counter64
+    MAX-ACCESS read-only
+    STATUS current
+    DESCRIPTION
+       "Number of queries received"
+    ::= { stats 1 }
+
+responses OBJECT-TYPE
+    SYNTAX Counter64
+    MAX-ACCESS read-only
+    STATUS current
+    DESCRIPTION
+       "Number of responses received"
+    ::= { stats 2 }
+
+servfailResponses OBJECT-TYPE
+    SYNTAX Counter64
+    MAX-ACCESS read-only
+    STATUS current
+    DESCRIPTION
+       "Number of servfail responses received"
+    ::= { stats 3 }
+
+aclDrops OBJECT-TYPE
+    SYNTAX Counter64
+    MAX-ACCESS read-only
+    STATUS current
+    DESCRIPTION
+       "Number of queries dropped because of the ACL"
+    ::= { stats 4 }
+
+-- stats 5 was a BlockFilter Counter, removed in 1.2.0
+
+ruleDrop OBJECT-TYPE
+    SYNTAX Counter64
+    MAX-ACCESS read-only
+    STATUS current
+    DESCRIPTION
+       "Number of queries dropped because of a rule"
+    ::= { stats 6 }
+
+ruleNXDomain OBJECT-TYPE
+    SYNTAX Counter64
+    MAX-ACCESS read-only
+    STATUS current
+    DESCRIPTION
+       "Number of NXDomain responses returned because of a rule"
+    ::= { stats 7 }
+
+ruleRefused OBJECT-TYPE
+    SYNTAX Counter64
+    MAX-ACCESS read-only
+    STATUS current
+    DESCRIPTION
+       "Number of Refused responses returned because of a rule"
+    ::= { stats 8 }
+
+selfAnswered OBJECT-TYPE
+    SYNTAX Counter64
+    MAX-ACCESS read-only
+    STATUS current
+    DESCRIPTION
+       "Number of self-answered responses"
+    ::= { stats 9 }
+
+downstreamTimeouts OBJECT-TYPE
+    SYNTAX Counter64
+    MAX-ACCESS read-only
+    STATUS current
+    DESCRIPTION
+       "Number of downstream timeouts"
+    ::= { stats 10 }
+
+downstreamSendErrors OBJECT-TYPE
+    SYNTAX Counter64
+    MAX-ACCESS read-only
+    STATUS current
+    DESCRIPTION
+       "Number of downstream send errors"
+    ::= { stats 11 }
+
+truncFailures OBJECT-TYPE
+    SYNTAX Counter64
+    MAX-ACCESS read-only
+    STATUS current
+    DESCRIPTION
+       "Number of errors while truncating a response"
+    ::= { stats 12 }
+
+noPolicy OBJECT-TYPE
+    SYNTAX Counter64
+    MAX-ACCESS read-only
+    STATUS current
+    DESCRIPTION
+       "Number of queries dropped because no server was available"
+    ::= { stats 13 }
+
+latency01 OBJECT-TYPE
+    SYNTAX Counter64
+    MAX-ACCESS read-only
+    STATUS current
+    DESCRIPTION
+       "Number of queries answered in less than 1 ms"
+    ::= { stats 14 }
+
+latency110 OBJECT-TYPE
+    SYNTAX Counter64
+    MAX-ACCESS read-only
+    STATUS current
+    DESCRIPTION
+       "Number of queries answered in 1-10 ms"
+    ::= { stats 15 }
+
+latency1050 OBJECT-TYPE
+    SYNTAX Counter64
+    MAX-ACCESS read-only
+    STATUS current
+    DESCRIPTION
+       "Number of queries answered in 10-50 ms"
+    ::= { stats 16 }
+
+latency50100 OBJECT-TYPE
+    SYNTAX Counter64
+    MAX-ACCESS read-only
+    STATUS current
+    DESCRIPTION
+       "Number of queries answered in 50-100 ms"
+    ::= { stats 17 }
+
+latency1001000 OBJECT-TYPE
+    SYNTAX Counter64
+    MAX-ACCESS read-only
+    STATUS current
+    DESCRIPTION
+       "Number of queries answered in 100-1000 ms"
+    ::= { stats 18 }
+
+latencySlow OBJECT-TYPE
+    SYNTAX Counter64
+    MAX-ACCESS read-only
+    STATUS current
+    DESCRIPTION
+       "Number of queries answered in more than 1s"
+    ::= { stats 19 }
+
+latencyAVG100 OBJECT-TYPE
+    SYNTAX Float64TC
+    MAX-ACCESS read-only
+    STATUS current
+    DESCRIPTION
+       "Average latency over the last 100 queries"
+    ::= { stats 20 }
+
+latencyAVG1000 OBJECT-TYPE
+    SYNTAX Float64TC
+    MAX-ACCESS read-only
+    STATUS current
+    DESCRIPTION
+       "Average latency over the last 1000 queries"
+    ::= { stats 21 }
+
+latencyAVG10000 OBJECT-TYPE
+    SYNTAX Float64TC
+    MAX-ACCESS read-only
+    STATUS current
+    DESCRIPTION
+       "Average latency over the last 10000 queries"
+    ::= { stats 22 }
+
+latencyAVG1000000 OBJECT-TYPE
+    SYNTAX Float64TC
+    MAX-ACCESS read-only
+    STATUS current
+    DESCRIPTION
+       "Average latency over the last 1000000 queries"
+    ::= { stats 23 }
+
+uptime OBJECT-TYPE
+    SYNTAX CounterBasedGauge64
+    MAX-ACCESS read-only
+    STATUS current
+    DESCRIPTION
+       "Uptime of the dnsdist process, in seconds"
+    ::= { stats 24 }
+
+realMemoryUsage OBJECT-TYPE
+    SYNTAX CounterBasedGauge64
+    MAX-ACCESS read-only
+    STATUS current
+    DESCRIPTION
+       "Memory usage"
+    ::= { stats 25 }
+
+nonCompliantQueries OBJECT-TYPE
+    SYNTAX Counter64
+    MAX-ACCESS read-only
+    STATUS current
+    DESCRIPTION
+       "Number of queries dropped as non-compliant"
+    ::= { stats 26 }
+
+nonCompliantResponses OBJECT-TYPE
+    SYNTAX Counter64
+    MAX-ACCESS read-only
+    STATUS current
+    DESCRIPTION
+       "Number of responses dropped as non-compliant"
+    ::= { stats 27 }
+
+rdQueries OBJECT-TYPE
+    SYNTAX Counter64
+    MAX-ACCESS read-only
+    STATUS current
+    DESCRIPTION
+       "Number of queries with the RD flag set"
+    ::= { stats 28 }
+
+emptyQueries OBJECT-TYPE
+    SYNTAX Counter64
+    MAX-ACCESS read-only
+    STATUS current
+    DESCRIPTION
+       "Number of empty queries received"
+    ::= { stats 29 }
+
+cacheHits OBJECT-TYPE
+    SYNTAX Counter64
+    MAX-ACCESS read-only
+    STATUS current
+    DESCRIPTION
+       "Number of cache hits"
+    ::= { stats 30 }
+
+cacheMisses OBJECT-TYPE
+    SYNTAX Counter64
+    MAX-ACCESS read-only
+    STATUS current
+    DESCRIPTION
+       "Number of cache misses"
+    ::= { stats 31 }
+
+cpuUserMSec OBJECT-TYPE
+    SYNTAX CounterBasedGauge64
+    MAX-ACCESS read-only
+    STATUS current
+    DESCRIPTION
+       "CPU Usage (user)"
+    ::= { stats 32 }
+
+cpuSysMSec OBJECT-TYPE
+    SYNTAX CounterBasedGauge64
+    MAX-ACCESS read-only
+    STATUS current
+    DESCRIPTION
+       "CPU Usage (sys)"
+    ::= { stats 33 }
+
+fdUsage OBJECT-TYPE
+    SYNTAX CounterBasedGauge64
+    MAX-ACCESS read-only
+    STATUS current
+    DESCRIPTION
+       "Number of file descriptors"
+    ::= { stats 34 }
+
+dynBlocked OBJECT-TYPE
+    SYNTAX Counter64
+    MAX-ACCESS read-only
+    STATUS current
+    DESCRIPTION
+       "Number of queries dropped because of a dynamic block"
+    ::= { stats 35 }
+
+dynBlockNMGSize OBJECT-TYPE
+    SYNTAX CounterBasedGauge64
+    MAX-ACCESS read-only
+    STATUS current
+    DESCRIPTION
+       "Dynamic blocks (NMG) size"
+    ::= { stats 36 }
+
+backendStatTable OBJECT-TYPE
+    SYNTAX SEQUENCE OF BackendStatEntry
+    MAX-ACCESS not-accessible
+    STATUS current
+    DESCRIPTION "Statistics for backends"
+    ::= { dnsdist 2 }
+
+backendStatEntry OBJECT-TYPE
+    SYNTAX BackendStatEntry
+    MAX-ACCESS not-accessible
+    STATUS current
+    DESCRIPTION "Statistics for one backend"
+    INDEX { backendId }
+    ::= { backendStatTable 1 }
+
+BackendStatEntry ::= SEQUENCE {
+    backendId           Unsigned32,
+    backendName         DisplayString,
+    backendLatency      CounterBasedGauge64,
+    backendWeight       CounterBasedGauge64,
+    backendOutstanding  CounterBasedGauge64,
+    backendQPSLimit     CounterBasedGauge64,
+    backendReused       Counter64,
+    backendState        DisplayString,
+    backendAddress      OCTET STRING,
+    backendPools        DisplayString,
+    backendQPS          CounterBasedGauge64,
+    backendQueries      Counter64,
+    backendOrder        CounterBasedGauge64
+}
+
+backendId OBJECT-TYPE
+    SYNTAX Unsigned32
+    MAX-ACCESS not-accessible
+    STATUS current
+    DESCRIPTION
+       "Backend ID"
+    ::= { backendStatEntry 1 }
+
+backendName OBJECT-TYPE
+    SYNTAX DisplayString
+    MAX-ACCESS read-only
+    STATUS current
+    DESCRIPTION
+       "Backend name"
+    ::= { backendStatEntry 2 }
+
+backendLatency OBJECT-TYPE
+    SYNTAX CounterBasedGauge64
+    MAX-ACCESS read-only
+    STATUS current
+    DESCRIPTION
+       "Backend latency"
+    ::= { backendStatEntry 3 }
+
+backendWeight OBJECT-TYPE
+    SYNTAX CounterBasedGauge64
+    MAX-ACCESS read-only
+    STATUS current
+    DESCRIPTION
+       "Backend weight"
+    ::= { backendStatEntry 4 }
+
+backendOutstanding OBJECT-TYPE
+    SYNTAX CounterBasedGauge64
+    MAX-ACCESS read-only
+    STATUS current
+    DESCRIPTION
+       "Backend outstanding queries"
+    ::= { backendStatEntry 5 }
+
+backendQPSLimit OBJECT-TYPE
+    SYNTAX CounterBasedGauge64
+    MAX-ACCESS read-only
+    STATUS current
+    DESCRIPTION
+       "Backend QPS limit"
+    ::= { backendStatEntry 6 }
+
+backendReused OBJECT-TYPE
+    SYNTAX Counter64
+    MAX-ACCESS read-only
+    STATUS current
+    DESCRIPTION
+       "Backend reused slots"
+    ::= { backendStatEntry 7 }
+
+backendState OBJECT-TYPE
+    SYNTAX DisplayString
+    MAX-ACCESS read-only
+    STATUS current
+    DESCRIPTION
+       "Backend state"
+    ::= { backendStatEntry 8 }
+
+backendAddress OBJECT-TYPE
+    SYNTAX OCTET STRING (SIZE (2..24))
+    MAX-ACCESS read-only
+    STATUS current
+    DESCRIPTION
+       "Backend address"
+    ::= { backendStatEntry 9 }
+
+backendPools OBJECT-TYPE
+    SYNTAX DisplayString
+    MAX-ACCESS read-only
+    STATUS current
+    DESCRIPTION
+       "List of pools this backend belongs to"
+    ::= { backendStatEntry 10 }
+
+backendQPS OBJECT-TYPE
+    SYNTAX CounterBasedGauge64
+    MAX-ACCESS read-only
+    STATUS current
+    DESCRIPTION
+       "Backend QPS"
+    ::= { backendStatEntry 11 }
+
+backendQueries OBJECT-TYPE
+    SYNTAX Counter64
+    MAX-ACCESS read-only
+    STATUS current
+    DESCRIPTION
+       "Number of queries sent to this backend"
+    ::= { backendStatEntry 12 }
+
+backendOrder OBJECT-TYPE
+    SYNTAX CounterBasedGauge64
+    MAX-ACCESS read-only
+    STATUS current
+    DESCRIPTION
+       "Backend order"
+    ::= { backendStatEntry 13 }
+
+---
+--- Textual Conventions
+---
+
+SocketProtocolType ::= TEXTUAL-CONVENTION
+    STATUS      current
+    DESCRIPTION
+        "A value that represents a type of socket protocol."
+    SYNTAX       INTEGER {
+                     unknown(0),
+                     udp(1),
+                     tcp(2)
+                 }
+
+DNSQueryType ::= TEXTUAL-CONVENTION
+    STATUS      current
+    DESCRIPTION
+        "A value that represents a type of DNS query (question or response)."
+    SYNTAX       INTEGER {
+                     unknown(0),
+                     question(1),
+                     response(2)
+                 }
+
+---
+--- Traps / Notifications
+---
+
+trap OBJECT IDENTIFIER ::= { dnsdist 10 }
+traps OBJECT IDENTIFIER ::= { trap 0 } --- reverse-mappable
+trapObjects OBJECT IDENTIFIER ::= { dnsdist 11 }
+
+socketFamily OBJECT-TYPE
+    SYNTAX InetAddressType
+    MAX-ACCESS read-only
+    STATUS current
+    DESCRIPTION
+        "Socket family type"
+    ::= { trapObjects 1 }
+
+socketProtocol OBJECT-TYPE
+    SYNTAX SocketProtocolType
+    MAX-ACCESS read-only
+    STATUS current
+    DESCRIPTION
+        "Socket protocol type"
+    ::= { trapObjects 2 }
+
+fromAddress OBJECT-TYPE
+    SYNTAX OCTET STRING (SIZE (2..24))
+    MAX-ACCESS read-only
+    STATUS current
+    DESCRIPTION
+       "Requestor address"
+    ::= { trapObjects 3 }
+
+toAddress OBJECT-TYPE
+    SYNTAX OCTET STRING (SIZE (2..24))
+    MAX-ACCESS read-only
+    STATUS current
+    DESCRIPTION
+       "Responder address"
+    ::= { trapObjects 4 }
+
+queryType OBJECT-TYPE
+    SYNTAX DNSQueryType
+    MAX-ACCESS read-only
+    STATUS current
+    DESCRIPTION
+        "Query / Response"
+    ::= { trapObjects 5 }
+
+querySize OBJECT-TYPE
+    SYNTAX Unsigned32
+    MAX-ACCESS read-only
+    STATUS current
+    DESCRIPTION
+        "Size in bytes"
+    ::= { trapObjects 6 }
+
+queryID OBJECT-TYPE
+    SYNTAX Unsigned32
+    MAX-ACCESS read-only
+    STATUS current
+    DESCRIPTION
+        "DNS query ID"
+    ::= { trapObjects 7 }
+
+qName OBJECT-TYPE
+    SYNTAX OCTET STRING (SIZE (0..255))
+    MAX-ACCESS read-only
+    STATUS current
+    DESCRIPTION
+        "DNS qname"
+    ::= { trapObjects 8 }
+
+qClass OBJECT-TYPE
+    SYNTAX Unsigned32
+    MAX-ACCESS read-only
+    STATUS current
+    DESCRIPTION
+        "DNS query class"
+    ::= { trapObjects 9 }
+
+qType OBJECT-TYPE
+    SYNTAX Unsigned32
+    MAX-ACCESS read-only
+    STATUS current
+    DESCRIPTION
+        "DNS query type"
+    ::= { trapObjects 10 }
+
+trapReason OBJECT-TYPE
+    SYNTAX OCTET STRING
+    MAX-ACCESS read-only
+    STATUS current
+    DESCRIPTION
+        "Reason for this trap"
+    ::= { trapObjects 11 }
+
+backendStatusChangeTrap NOTIFICATION-TYPE
+    OBJECTS {
+        backendName,
+        backendAddress,
+        backendState
+    }
+    STATUS current
+    DESCRIPTION "Backend status changed"
+    ::= { traps 1 }
+
+actionTrap NOTIFICATION-TYPE
+    OBJECTS {
+        socketFamily,
+        socketProtocol,
+        fromAddress,
+        toAddress,
+        queryType,
+        querySize,
+        queryID,
+        qName,
+        qClass,
+        qType,
+        trapReason
+    }
+    STATUS current
+    DESCRIPTION "Trap sent by SNMPTrapAction"
+    ::= { traps 2 }
+
+customTrap NOTIFICATION-TYPE
+    OBJECTS {
+        trapReason
+    }
+    STATUS current
+    DESCRIPTION "Trap sent by sendCustomTrap"
+    ::= { traps 3 }
+
+---
+--- Conformance
+---
+
+dnsdistConformance OBJECT IDENTIFIER ::= { dnsdist 100 }
+
+dnsdistCompliances MODULE-COMPLIANCE
+    STATUS current
+    DESCRIPTION "dnsdist compliance statement"
+    MODULE
+    MANDATORY-GROUPS {
+        dnsdistGroup,
+        dnsdistTrapsGroup
+    }
+    ::= { dnsdistConformance 1 }
+
+dnsdistGroup OBJECT-GROUP
+    OBJECTS {
+        queries,
+        responses,
+        servfailResponses,
+        aclDrops,
+        ruleDrop,
+        ruleNXDomain,
+        ruleRefused,
+        selfAnswered,
+        downstreamTimeouts,
+        downstreamSendErrors,
+        truncFailures,
+        noPolicy,
+        latency01,
+        latency110,
+        latency1050,
+        latency50100,
+        latency1001000,
+        latencySlow,
+        latencyAVG100,
+        latencyAVG1000,
+        latencyAVG10000,
+        latencyAVG1000000,
+        uptime,
+        realMemoryUsage,
+        nonCompliantQueries,
+        nonCompliantResponses,
+        rdQueries,
+        emptyQueries,
+        cacheHits,
+        cacheMisses,
+        cpuUserMSec,
+        cpuSysMSec,
+        fdUsage,
+        dynBlocked,
+        dynBlockNMGSize,
+        backendName,
+        backendLatency,
+        backendWeight,
+        backendOutstanding,
+        backendQPSLimit,
+        backendReused,
+        backendState,
+        backendAddress,
+        backendPools,
+        backendQPS,
+        backendQueries,
+        backendOrder,
+        socketFamily,
+        socketProtocol,
+        fromAddress,
+        toAddress,
+        queryType,
+        querySize,
+        queryID,
+        qName,
+        qClass,
+        qType,
+        trapReason
+    }
+    STATUS current
+    DESCRIPTION "Objects conformance group for dnsdist"
+    ::= { dnsdistConformance 2 }
+
+dnsdistTrapsGroup NOTIFICATION-GROUP
+    NOTIFICATIONS {
+        actionTrap,
+        customTrap,
+        backendStatusChangeTrap
+    }
+    STATUS current
+    DESCRIPTION "Traps conformance group for dnsdist"
+    ::= { dnsdistConformance 3 }
+
+END
index 5ae8da3154b4cd8e3f64af70cc246fd613d4ab1e..aa889ad21a885d47d2a73f58a9da9113498e30d0 100644 (file)
@@ -35,7 +35,6 @@ EXTRA_DIST=dnslabeltext.rl \
           README.md \
           delaypipe.cc delaypipe.hh \
           html \
-          dnsdist.1.md \
           .version \
           contrib \
           build-aux/gen-version \
@@ -198,17 +197,47 @@ MANPAGES=dnsdist.1
 
 dist_man_MANS=$(MANPAGES)
 
-if HAVE_PANDOC
-$(MANPAGES): %: %.md
-       $(AM_V_GEN)$(PANDOC) -s -t man $< -o $@
-else
-if HAVE_MANPAGES
-#nothing
-else
+if HAVE_VIRTUALENV
+if !HAVE_MANPAGES
+$(MANPAGES): %: docs/manpages/%.rst .venv
+       $(AM_V_GEN).venv/bin/python -msphinx -b man docs . $<
+endif # if !HAVE_MANPAGES
+
+.venv: docs/requirements.txt
+       virtualenv .venv
+       .venv/bin/pip install -r $<
+
+latex/dnsdist.pdf: docs/** .venv
+       .venv/bin/python -msphinx -M latexpdf docs .
+
+dnsdist.pdf: latex/dnsdist.pdf
+       mv $< $@
+
+html-docs.tar.bz2: html-docs
+       tar cjf $@ $<
+
+html-docs: docs/** .venv
+       .venv/bin/python -msphinx -b html docs html-docs
+
+all-docs: html-docs html-docs.tar.bz2 dnsdist.pdf
+
+upload-docs: all-docs
+       rsync -crv --delete --no-p --chmod=g=rwX --exclude '*~' ./html-docs/ web1.powerdns.com:/srv/www/dnsdist.org/new
+       rsync -crv --no-p --chmod=g=rwX --exclude '*~' ./html-docs.tar.bz2 web1.powerdns.com:/srv/www/dnsdist.org/new
+       rsync -crv --no-p --chmod=g=rwX --exclude '*~' ./dnsdist.pdf web1.powerdns.com:/srv/www/dnsdist.org/new
+
+else # if HAVE_VIRTUALENV
 $(MANPAGES):
-       echo "You need pandoc to generate the manpages"
+       @echo "You need virtualenv to generate the manpages"
+       exit 1
+
+html-docs: %: docs/manpages/%.rst .venv
+       @echo "You need virtualenv to generate the HTML documentation"
+       exit 1
+
+dnsdist.pdf:
+       @echo "You need virtualenv to generate the pdf documentation"
        exit 1
-endif
 endif
 
 if HAVE_SYSTEMD
index 717cb17db676b15560fed2a1c8b02f957226f1a5..c45ac70255570e311b1b547ef7a30f1a4c79b190 100644 (file)
@@ -72,7 +72,7 @@ AS_IF([test "x$enable_hardening" != "xno"], [
 
 PDNS_ENABLE_SANITIZERS
 
-PDNS_CHECK_PANDOC
+PDNS_CHECK_VIRTUALENV
 
 LDFLAGS="$RELRO_LDFLAGS $LDFLAGS"
 
diff --git a/pdns/dnsdistdist/dnsdist.1.md b/pdns/dnsdistdist/dnsdist.1.md
deleted file mode 120000 (symlink)
index 883bd2f..0000000
+++ /dev/null
@@ -1 +0,0 @@
-../../docs/manpages/dnsdist.1.md
\ No newline at end of file
diff --git a/pdns/dnsdistdist/docs/.gitignore b/pdns/dnsdistdist/docs/.gitignore
new file mode 100644 (file)
index 0000000..e35d885
--- /dev/null
@@ -0,0 +1 @@
+_build
diff --git a/pdns/dnsdistdist/docs/Makefile b/pdns/dnsdistdist/docs/Makefile
new file mode 100644 (file)
index 0000000..a079506
--- /dev/null
@@ -0,0 +1,25 @@
+# Minimal makefile for Sphinx documentation
+#
+
+# You can set these variables from the command line.
+SPHINXOPTS    =
+SPHINXBUILD   = sphinx-build
+SPHINXPROJ    = dnsdist
+SOURCEDIR     = .
+BUILDDIR      = _build
+
+# Put it first so that "make" without argument is like "make help".
+help:
+       @$(SPHINXBUILD) -M help "$(SOURCEDIR)" "$(BUILDDIR)" $(SPHINXOPTS) $(O)
+
+upload: html latexpdf
+       rsync -r $(BUILDDIR)/html/* mango.plexis.eu:/srv/www/dump.plexis.eu/pdns/dnsdist-docs/html
+       rsync $(BUILDDIR)/latex/dnsdist.pdf mango.plexis.eu:/srv/www/dump.plexis.eu/pdns/dnsdist-docs
+
+
+.PHONY: help Makefile
+
+# Catch-all target: route all unknown targets to Sphinx using the new
+# "make mode" option.  $(O) is meant as a shortcut for $(SPHINXOPTS).
+%: Makefile
+       @$(SPHINXBUILD) -M $@ "$(SOURCEDIR)" "$(BUILDDIR)" $(SPHINXOPTS) $(O)
diff --git a/pdns/dnsdistdist/docs/_static/favicon.ico b/pdns/dnsdistdist/docs/_static/favicon.ico
new file mode 100644 (file)
index 0000000..4b0eae3
Binary files /dev/null and b/pdns/dnsdistdist/docs/_static/favicon.ico differ
diff --git a/pdns/dnsdistdist/docs/_static/model.dot b/pdns/dnsdistdist/docs/_static/model.dot
new file mode 100644 (file)
index 0000000..d5bd837
--- /dev/null
@@ -0,0 +1,79 @@
+digraph {
+  graph [fontname = "monospace"];
+  node [fontname = "monospace"];
+  edge [fontname = "monospace"];
+
+  Drop [label="Drop query"];
+
+  Incoming_Query [label="Incoming Query"];
+
+  Allowed_ACL [label="In the ACL allow list?"];
+
+  Incoming_Query -> Allowed_ACL;
+  Allowed_ACL -> Drop [label="no"];
+  Allowed_ACL -> Dynamically_Blocked [label="yes"];
+
+  Dynamically_Blocked [label="DynBlocked?"];
+  Perform_DynBlock_Action [label="Perform DynBlock action"];
+  MatchRules [label="Query matches a rule?"];
+
+  Dynamically_Blocked -> Perform_DynBlock_Action [label="yes"];
+  Dynamically_Blocked -> MatchRules [label="no"];
+
+  MatchRules -> "Perform Action" [label="yes"];
+  MatchRules -> DeterminePool [label="no"];
+  DeterminePool [label="Determine pool and policy"];
+
+  "Perform Action" -> IsResponse;
+  "Perform Action" -> MatchRules [label="Action is non-terminal"];
+  "Perform Action" -> Drop [label="DropAction()"];
+
+  IsResponse [label="Query is now a response?"];
+
+  IsResponse -> "Return response to client" [label="yes"];
+  IsResponse -> DeterminePool [label="no"];
+
+  HasCache [label="Does the pool have a packet cache?"];
+  skipCache [label="Should the cache be skipped?"];
+
+  DeterminePool -> HasCache;
+  HasCache -> skipCache [label="yes"];
+  HasCache -> HasPolicy [label="no"];
+
+  skipCache -> HasPolicy [label="yes"];
+  skipCache -> CacheHit [label="no"];
+
+  CacheHit [label="Cache Hit?"];
+  CacheHit -> MakeResponse [label="yes"];
+  CacheHit -> HasPolicy [label="no"];
+
+  MakeResponse [label="Create Response"];
+  MatchCacheRespRule [label="Response matches CacheHitRule?"];
+  MakeResponse -> MatchCacheRespRule;
+
+  MatchCacheRespRule -> "Return response to client" [label="no"];
+  MatchCacheRespRule -> "Perform CacheHit Action" [label="yes"];
+  "Perform CacheHit Action" -> "Return response to client";
+
+  HasPolicy [label="Does the pool have a policy?"];
+
+  HasPolicy -> "Is servFailOnNoPolicy set?" [label="no"];
+  "Is servFailOnNoPolicy set?" -> Drop [label="no"];
+  "Is servFailOnNoPolicy set?" -> ServFail [label="yes"];
+
+  HasPolicy -> "Send Query to backend server" [label="yes"];
+
+  "Send Query to backend server" -> "Got Response from backend";
+
+  RespRule [label="Response matches a ResponseRule?"];
+  "Got Response from backend" -> RespRule;
+  RespRule -> "Perform ResponseAction" [label="yes"];
+  "Perform ResponseAction" -> RespRule [label="Action was non-terminal"];
+  RespRule -> AddToCache [label="no"];
+  "Perform ResponseAction" -> AddToCache;
+  "Perform ResponseAction" -> Drop [label="DropAction()"];
+
+  AddToCache [label="Add to PacketCache"];
+
+  AddToCache -> "Return response to client";
+}
diff --git a/pdns/dnsdistdist/docs/_static/powerdns-logo-trans.png b/pdns/dnsdistdist/docs/_static/powerdns-logo-trans.png
new file mode 100644 (file)
index 0000000..d49bdf0
Binary files /dev/null and b/pdns/dnsdistdist/docs/_static/powerdns-logo-trans.png differ
diff --git a/pdns/dnsdistdist/docs/_templates/pdns_html/layout.html b/pdns/dnsdistdist/docs/_templates/pdns_html/layout.html
new file mode 100644 (file)
index 0000000..07a288b
--- /dev/null
@@ -0,0 +1,21 @@
+{%- extends "basic/layout.html" %}
+
+{%- block extrahead %}
+<link rel="stylesheet" href="https://fonts.googleapis.com/css?family=Nobile:regular,italic,bold,bolditalic&amp;subset=latin" type="text/css" media="screen" charset="utf-8" />
+<!--[if lte IE 6]>
+<link rel="stylesheet" href="{{ pathto('_static/ie6.css', 1) }}" type="text/css" media="screen" charset="utf-8" />
+<![endif]-->
+{% endblock %}
+
+{% block header %}
+<div class="header" role="banner">
+  <div class="logo">
+    <a href="{{ pathto('index') }}">
+      <img class="logo" src="{{ pathto('_static/powerdns-logo-trans.png', 1) }}" alt="PowerDNS Logo"/>
+    </a>
+  </div>
+</div>
+{% endblock %}
+
+{%- block sidebarlogo %}{%- endblock %}
+{%- block sidebarsourcelink %}{%- endblock %}
diff --git a/pdns/dnsdistdist/docs/_templates/pdns_html/static/dialog-note.png b/pdns/dnsdistdist/docs/_templates/pdns_html/static/dialog-note.png
new file mode 100644 (file)
index 0000000..5a6336d
Binary files /dev/null and b/pdns/dnsdistdist/docs/_templates/pdns_html/static/dialog-note.png differ
diff --git a/pdns/dnsdistdist/docs/_templates/pdns_html/static/dialog-seealso.png b/pdns/dnsdistdist/docs/_templates/pdns_html/static/dialog-seealso.png
new file mode 100644 (file)
index 0000000..97553a8
Binary files /dev/null and b/pdns/dnsdistdist/docs/_templates/pdns_html/static/dialog-seealso.png differ
diff --git a/pdns/dnsdistdist/docs/_templates/pdns_html/static/dialog-todo.png b/pdns/dnsdistdist/docs/_templates/pdns_html/static/dialog-todo.png
new file mode 100644 (file)
index 0000000..cfbc280
Binary files /dev/null and b/pdns/dnsdistdist/docs/_templates/pdns_html/static/dialog-todo.png differ
diff --git a/pdns/dnsdistdist/docs/_templates/pdns_html/static/dialog-topic.png b/pdns/dnsdistdist/docs/_templates/pdns_html/static/dialog-topic.png
new file mode 100644 (file)
index 0000000..a75afea
Binary files /dev/null and b/pdns/dnsdistdist/docs/_templates/pdns_html/static/dialog-topic.png differ
diff --git a/pdns/dnsdistdist/docs/_templates/pdns_html/static/dialog-warning.png b/pdns/dnsdistdist/docs/_templates/pdns_html/static/dialog-warning.png
new file mode 100644 (file)
index 0000000..8bb7d8d
Binary files /dev/null and b/pdns/dnsdistdist/docs/_templates/pdns_html/static/dialog-warning.png differ
diff --git a/pdns/dnsdistdist/docs/_templates/pdns_html/static/epub.css b/pdns/dnsdistdist/docs/_templates/pdns_html/static/epub.css
new file mode 100644 (file)
index 0000000..6fdf477
--- /dev/null
@@ -0,0 +1,310 @@
+/*
+ * default.css_t
+ * ~~~~~~~~~~~~~
+ *
+ * Sphinx stylesheet -- default theme.
+ *
+ * :copyright: Copyright 2007-2016 by the Sphinx team, see AUTHORS.
+ * :license: BSD, see LICENSE for details.
+ *
+ */
+
+@import url("basic.css");
+
+/* -- page layout ----------------------------------------------------------- */
+
+body {
+    font-family: {{ theme_bodyfont }};
+    font-size: 100%;
+    background-color: {{ theme_footerbgcolor }};
+    color: #000;
+    margin: 0;
+    padding: 0;
+}
+
+div.document {
+    background-color: {{ theme_sidebarbgcolor }};
+}
+
+div.documentwrapper {
+    float: left;
+    width: 100%;
+}
+
+div.bodywrapper {
+    margin: 0 0 0 230px;
+}
+
+div.body {
+    background-color: {{ theme_bgcolor }};
+    color: {{ theme_textcolor }};
+    padding: 0 20px 30px 20px;
+}
+
+{%- if theme_rightsidebar|tobool %}
+div.bodywrapper {
+    margin: 0 230px 0 0;
+}
+{%- endif %}
+
+div.footer {
+    color: {{ theme_footertextcolor }};
+    width: 100%;
+    padding: 9px 0 9px 0;
+    text-align: center;
+    font-size: 75%;
+}
+
+div.footer a {
+    color: {{ theme_footertextcolor }};
+    text-decoration: underline;
+}
+
+div.related {
+    background-color: {{ theme_relbarbgcolor }};
+    line-height: 30px;
+    color: {{ theme_relbartextcolor }};
+}
+
+div.related a {
+    color: {{ theme_relbarlinkcolor }};
+}
+
+div.sphinxsidebar {
+    {%- if theme_stickysidebar|tobool %}
+    top: 30px;
+    bottom: 0;
+    margin: 0;
+    position: fixed;
+    overflow: auto;
+    height: auto;
+    {%- endif %}
+    {%- if theme_rightsidebar|tobool %}
+    float: right;
+    {%- if theme_stickysidebar|tobool %}
+    right: 0;
+    {%- endif %}
+    {%- endif %}
+}
+
+{%- if theme_stickysidebar|tobool %}
+/* this is nice, but it it leads to hidden headings when jumping
+   to an anchor */
+/*
+div.related {
+    position: fixed;
+}
+
+div.documentwrapper {
+    margin-top: 30px;
+}
+*/
+{%- endif %}
+
+div.sphinxsidebar h3 {
+    font-family: {{ theme_headfont }};
+    color: {{ theme_sidebartextcolor }};
+    font-size: 1.4em;
+    font-weight: normal;
+    margin: 0;
+    padding: 0;
+}
+
+div.sphinxsidebar h3 a {
+    color: {{ theme_sidebartextcolor }};
+}
+
+div.sphinxsidebar h4 {
+    font-family: {{ theme_headfont }};
+    color: {{ theme_sidebartextcolor }};
+    font-size: 1.3em;
+    font-weight: normal;
+    margin: 5px 0 0 0;
+    padding: 0;
+}
+
+div.sphinxsidebar p {
+    color: {{ theme_sidebartextcolor }};
+}
+
+div.sphinxsidebar p.topless {
+    margin: 5px 10px 10px 10px;
+}
+
+div.sphinxsidebar ul {
+    margin: 10px;
+    padding: 0;
+    color: {{ theme_sidebartextcolor }};
+}
+
+div.sphinxsidebar a {
+    color: {{ theme_sidebarlinkcolor }};
+}
+
+div.sphinxsidebar input {
+    border: 1px solid {{ theme_sidebarlinkcolor }};
+    font-family: sans-serif;
+    font-size: 1em;
+}
+
+{% if theme_collapsiblesidebar|tobool %}
+/* for collapsible sidebar */
+div#sidebarbutton {
+    background-color: {{ theme_sidebarbtncolor }};
+}
+{% endif %}
+
+/* -- hyperlink styles ------------------------------------------------------ */
+
+a {
+    color: {{ theme_linkcolor }};
+    text-decoration: none;
+}
+
+a:visited {
+    color: {{ theme_visitedlinkcolor }};
+    text-decoration: none;
+}
+
+a:hover {
+    text-decoration: underline;
+}
+
+{% if theme_externalrefs|tobool %}
+a.external {
+   text-decoration: none;
+   border-bottom: 1px dashed {{ theme_linkcolor }};
+}
+
+a.external:hover {
+   text-decoration: none;
+   border-bottom: none;
+}
+
+a.external:visited {
+    text-decoration: none;
+    border-bottom: 1px dashed {{ theme_visitedlinkcolor }};
+}
+{% endif %}
+
+/* -- body styles ----------------------------------------------------------- */
+
+div.body h1,
+div.body h2,
+div.body h3,
+div.body h4,
+div.body h5,
+div.body h6 {
+    font-family: {{ theme_headfont }};
+    background-color: {{ theme_headbgcolor }};
+    font-weight: normal;
+    color: {{ theme_headtextcolor }};
+    border-bottom: 1px solid #ccc;
+    margin: 20px -20px 10px -20px;
+    padding: 3px 0 3px 10px;
+}
+
+div.body h1 { margin-top: 0; font-size: 200%; }
+div.body h2 { font-size: 160%; }
+div.body h3 { font-size: 140%; }
+div.body h4 { font-size: 120%; }
+div.body h5 { font-size: 110%; }
+div.body h6 { font-size: 100%; }
+
+a.headerlink {
+    color: {{ theme_headlinkcolor }};
+    font-size: 0.8em;
+    padding: 0 4px 0 4px;
+    text-decoration: none;
+}
+
+a.headerlink:hover {
+    background-color: {{ theme_headlinkcolor }};
+    color: white;
+}
+
+div.body p, div.body dd, div.body li {
+    text-align: justify;
+    line-height: 130%;
+}
+
+div.admonition p.admonition-title + p {
+    display: inline;
+}
+
+div.admonition p {
+    margin-bottom: 5px;
+}
+
+div.admonition pre {
+    margin-bottom: 5px;
+}
+
+div.admonition ul, div.admonition ol {
+    margin-bottom: 5px;
+}
+
+div.note {
+    background-color: #eee;
+    border: 1px solid #ccc;
+}
+
+div.seealso {
+    background-color: #ffc;
+    border: 1px solid #ff6;
+}
+
+div.topic {
+    background-color: #eee;
+}
+
+div.warning {
+    background-color: #ffe4e4;
+    border: 1px solid #f66;
+}
+
+p.admonition-title {
+    display: inline;
+}
+
+p.admonition-title:after {
+    content: ":";
+}
+
+pre {
+    padding: 5px;
+    background-color: {{ theme_codebgcolor }};
+    color: {{ theme_codetextcolor }};
+    line-height: 120%;
+    border: 1px solid #ac9;
+    border-left: none;
+    border-right: none;
+}
+
+code {
+    background-color: #ecf0f3;
+    padding: 0 1px 0 1px;
+    font-size: 0.95em;
+}
+
+th {
+    background-color: #ede;
+}
+
+.warning code {
+    background: #efc2c2;
+}
+
+.note code {
+    background: #d6d6d6;
+}
+
+.viewcode-back {
+    font-family: {{ theme_bodyfont }};
+}
+
+div.viewcode-block:target {
+    background-color: #f4debf;
+    border-top: 1px solid #ac9;
+    border-bottom: 1px solid #ac9;
+}
diff --git a/pdns/dnsdistdist/docs/_templates/pdns_html/static/footerbg.png b/pdns/dnsdistdist/docs/_templates/pdns_html/static/footerbg.png
new file mode 100644 (file)
index 0000000..1fbc873
Binary files /dev/null and b/pdns/dnsdistdist/docs/_templates/pdns_html/static/footerbg.png differ
diff --git a/pdns/dnsdistdist/docs/_templates/pdns_html/static/headerbg.png b/pdns/dnsdistdist/docs/_templates/pdns_html/static/headerbg.png
new file mode 100644 (file)
index 0000000..e1051af
Binary files /dev/null and b/pdns/dnsdistdist/docs/_templates/pdns_html/static/headerbg.png differ
diff --git a/pdns/dnsdistdist/docs/_templates/pdns_html/static/ie6.css b/pdns/dnsdistdist/docs/_templates/pdns_html/static/ie6.css
new file mode 100644 (file)
index 0000000..74baa5d
--- /dev/null
@@ -0,0 +1,7 @@
+* html img,
+* html .png{position:relative;behavior:expression((this.runtimeStyle.behavior="none")&&(this.pngSet?this.pngSet=true:(this.nodeName == "IMG" && this.src.toLowerCase().indexOf('.png')>-1?(this.runtimeStyle.backgroundImage = "none",
+this.runtimeStyle.filter = "progid:DXImageTransform.Microsoft.AlphaImageLoader(src='" + this.src + "',sizingMethod='image')",
+this.src = "_static/transparent.gif"):(this.origBg = this.origBg? this.origBg :this.currentStyle.backgroundImage.toString().replace('url("','').replace('")',''),
+this.runtimeStyle.filter = "progid:DXImageTransform.Microsoft.AlphaImageLoader(src='" + this.origBg + "',sizingMethod='crop')",
+this.runtimeStyle.backgroundImage = "none")),this.pngSet=true)
+);}
diff --git a/pdns/dnsdistdist/docs/_templates/pdns_html/static/middlebg.png b/pdns/dnsdistdist/docs/_templates/pdns_html/static/middlebg.png
new file mode 100644 (file)
index 0000000..5ee55db
Binary files /dev/null and b/pdns/dnsdistdist/docs/_templates/pdns_html/static/middlebg.png differ
diff --git a/pdns/dnsdistdist/docs/_templates/pdns_html/static/pyramid.css_t b/pdns/dnsdistdist/docs/_templates/pdns_html/static/pyramid.css_t
new file mode 100644 (file)
index 0000000..a1cbfe0
--- /dev/null
@@ -0,0 +1,346 @@
+/*
+ * pyramid.css_t
+ * ~~~~~~~~~~~~
+ *
+ * Sphinx stylesheet -- pylons theme.
+ *
+ * :copyright: Copyright 2007-2016 by the Sphinx team, see AUTHORS.
+ * :license: BSD, see LICENSE for details.
+ *
+ */
+@import url("basic.css");
+/* -- page layout ----------------------------------------------------------- */
+body {
+    font-family: sans-serif;
+    font-size: 100%;
+    background-color: #393939;
+    color: #ffffff;
+    margin: 0;
+    padding: 0;
+}
+
+div.documentwrapper {
+    float: left;
+    width: 100%;
+}
+
+div.bodywrapper {
+    margin: 0 0 0 {{ theme_sidebarwidth }}px;
+}
+
+hr {
+    border: 1px solid #B1B4B6;
+}
+div.document {
+    background-color: #eee;
+}
+
+div.header {
+    width:100%;
+    background-color: #eee;
+}
+
+div.logo {
+    text-align: center;
+    padding-top: 10px;
+}
+
+div.body {
+    background-color: #ffffff;
+    color: #3E4349;
+    padding: 0 30px 30px 30px;
+    font-size: 1em;
+    border: 2px solid #ddd;
+    border-right-style: none;
+    overflow: auto;
+}
+div.footer {
+    color: #ffffff;
+    width: 100%;
+    padding: 13px 0;
+    text-align: center;
+    font-size: 75%;
+    background: transparent;
+    clear:both;
+}
+div.footer a {
+    color: #ffffff;
+    text-decoration: none;
+}
+
+div.footer a:hover {
+    color: #e88f00;
+    text-decoration: underline;
+}
+div.related {
+    line-height: 30px;
+    color: #373839;
+    font-size: 0.8em;
+    background-color: #eee;
+}
+div.related a {
+    color: #1b61d6;
+}
+
+div.related ul {
+    padding-left: {{ theme_sidebarwidth|toint + 10 }}px;
+}
+div.sphinxsidebar {
+    font-size: 0.75em;
+    line-height: 1.5em;
+}
+
+div.sphinxsidebarwrapper{
+    padding: 10px 0;
+}
+div.sphinxsidebar h3,
+div.sphinxsidebar h4 {
+    font-family: sans-serif;
+    color: #373839;
+    font-size: 1.4em;
+    font-weight: normal;
+    margin: 0;
+    padding: 5px 10px;
+    border-bottom: 2px solid #ddd;
+}
+
+div.sphinxsidebar h4{
+    font-size: 1.3em;
+}
+div.sphinxsidebar h3 a {
+    color: #000000;
+}
+div.sphinxsidebar p {
+    color: #888;
+    padding: 5px 20px;
+}
+div.sphinxsidebar p.topless {
+}
+div.sphinxsidebar ul {
+    margin: 10px 20px;
+    padding: 0;
+    color: #373839;
+}
+div.sphinxsidebar a {
+    color: #444;
+}
+div.sphinxsidebar input {
+    border: 1px solid #ccc;
+    font-family: sans-serif;
+    font-size: 1em;
+}
+
+div.sphinxsidebar input[type=text]{
+    margin-left: 20px;
+}
+
+/* -- sidebars -------------------------------------------------------------- */
+
+div.sidebar {
+    margin: 0 0 0.5em 1em;
+    border: 2px solid #c6d880;
+    background-color: #e6efc2;
+    width: 40%;
+    float: right;
+    border-right-style: none;
+    border-left-style: none;
+    padding: 10px 20px;
+}
+
+p.sidebar-title {
+    font-weight: bold;
+}
+
+/* -- body styles ----------------------------------------------------------- */
+a, a .pre {
+    color: #1b61d6;
+    text-decoration: none;
+}
+a:hover, a:hover .pre {
+    text-decoration: underline;
+}
+div.body h1,
+div.body h2,
+div.body h3,
+div.body h4,
+div.body h5,
+div.body h6 {
+    font-family: sans-serif;
+    background-color: #ffffff;
+    font-weight: normal;
+    color: #373839;
+    margin: 30px 0px 10px 0px;
+    padding: 5px 0;
+}
+div.body h1 { border-top: 20px solid white; margin-top: 0; font-size: 200%; }
+div.body h2 { font-size: 150%; background-color: #ffffff; }
+div.body h3 { font-size: 120%; background-color: #ffffff; }
+div.body h4 { font-size: 110%; background-color: #ffffff; }
+div.body h5 { font-size: 100%; background-color: #ffffff; }
+div.body h6 { font-size: 100%; background-color: #ffffff; }
+a.headerlink {
+    color: #1b61d6;
+    font-size: 0.8em;
+    padding: 0 4px 0 4px;
+    text-decoration: none;
+}
+a.headerlink:hover {
+    text-decoration: underline;
+}
+div.body p, div.body dd, div.body li {
+    line-height: 1.5em;
+}
+div.admonition p.admonition-title + p {
+    display: inline;
+}
+
+div.admonition {
+    background: #eeeeec;
+    border: 2px solid #babdb6;
+    border-right-style: none;
+    border-left-style: none;
+    padding: 10px 20px 10px 60px;
+}
+
+div.highlight{
+    background-color: white;
+}
+
+div.note {
+    border: 2px solid #7a9eec;
+    border-right-style: none;
+    border-left-style: none;
+    padding: 10px 20px 10px 60px;
+    background: #e1ecfe url(dialog-note.png) no-repeat 10px 8px;
+}
+div.seealso {
+    background: #fff6bf url(dialog-seealso.png) no-repeat 10px 8px;
+    border: 2px solid #ffd324;
+    border-left-style: none;
+    border-right-style: none;
+    padding: 10px 20px 10px 60px;
+}
+div.topic {
+    background: #eeeeee;
+    border: 2px solid #C6C9CB;
+    padding: 10px 20px;
+    border-right-style: none;
+    border-left-style: none;
+}
+div.warning {
+    background: #fbe3e4 url(dialog-warning.png) no-repeat 10px 8px;
+    border: 2px solid #fbc2c4;
+    border-right-style: none;
+    border-left-style: none;
+    padding: 10px 20px 10px 60px;
+}
+
+div.admonition-todo {
+    background: #f2d9b4 url(dialog-todo.png) no-repeat 10px 8px;
+    border: 2px solid #e9b96e;
+    border-right-style: none;
+    border-left-style: none;
+    padding: 10px 20px 10px 60px;
+}
+div.note p.admonition-title,
+div.warning p.admonition-title,
+div.seealso p.admonition-title,
+div.admonition-todo p.admonition-title {
+    display: none;
+}
+p.admonition-title:after {
+    content: ":";
+}
+pre {
+    padding: 10px;
+    background-color: #fafafa;
+    color: #222;
+    line-height: 1.2em;
+    border: 2px solid #C6C9CB;
+    font-size: 1.1em;
+    margin: 1.5em 0 1.5em 0;
+    border-right-style: none;
+    border-left-style: none;
+}
+code {
+    background-color: transparent;
+    color: #222;
+    font-size: 1.1em;
+    font-family: monospace;
+}
+
+.viewcode-back {
+    font-family: "Nobile", sans-serif;
+}
+
+div.viewcode-block:target {
+    background-color: #fff6bf;
+    border: 2px solid #ffd324;
+    border-left-style: none;
+    border-right-style: none;
+    padding: 10px 20px;
+}
+
+table.highlighttable {
+    width: 100%;
+}
+
+table.highlighttable td {
+    padding: 0;
+}
+
+a em.std-term {
+   color: #007f00;
+}
+
+a:hover em.std-term {
+    text-decoration: underline;
+}
+
+.download {
+    font-family: "Nobile", sans-serif;
+    font-weight: normal;
+    font-style: normal;
+}
+
+code.xref {
+    font-weight: normal;
+    font-style: normal;
+}
+
+div.code-block-caption {
+    background-color: #ddd;
+    color: #222;
+}
diff --git a/pdns/dnsdistdist/docs/_templates/pdns_html/static/transparent.gif b/pdns/dnsdistdist/docs/_templates/pdns_html/static/transparent.gif
new file mode 100644 (file)
index 0000000..0341802
Binary files /dev/null and b/pdns/dnsdistdist/docs/_templates/pdns_html/static/transparent.gif differ
diff --git a/pdns/dnsdistdist/docs/_templates/pdns_html/theme.conf b/pdns/dnsdistdist/docs/_templates/pdns_html/theme.conf
new file mode 100644 (file)
index 0000000..24eeae7
--- /dev/null
@@ -0,0 +1,7 @@
+[theme]
+inherit = basic
+stylesheet = pyramid.css
+pygments_style = sphinx.pygments_styles.PyramidStyle
+
+[options]
+logo = logo.png
diff --git a/pdns/dnsdistdist/docs/advanced/acl.rst b/pdns/dnsdistdist/docs/advanced/acl.rst
new file mode 100644 (file)
index 0000000..bce4197
--- /dev/null
@@ -0,0 +1,59 @@
+.. _ACL:
+
+Access Control
+==============
+
+dnsdist can be used to front traditional recursive nameservers, these usually come with a way to limit the network ranges that may query it to prevent becoming an :term:`open resolver`.
+To be a good internet citizen, dnsdist by default listens on the loopback address (`127.0.0.1:53`) and limits queries to these loopback, :rfc:`1918` and other local addresses:
+
+- ``127.0.0.0/8``
+- ``10.0.0.0/8``
+- ``100.64.0.0/10``
+- ``169.254.0.0/16``
+- ``192.168.0.0/16``
+- ``172.16.0.0/12``
+- ``::1/128``
+- ``fc00::/7``
+- ``fe80::/10``
+
+Further more, dnsdist only listens for queries on the local-loopback interface by default.
+
+Listening on different addresses
+--------------------------------
+
+To listen on other addresses than just the local addresses, use :func:`setLocal` and :func:`addLocal`.
+
+:func:`setLocal` **resets** the list of current listen addresses to the specified address and :func:`addLocal` adds an additional listen address.
+To listen on ``127.0.0.1:5300``, ``192.0.2.1:53`` and UDP-only on ``[2001:db8::15::47]:53``, configure the following:
+
+.. code-block:: lua
+
+  setLocal('127.0.0.1:5300')
+  addLocal('192.0.2.1') -- Port 53 is default is none is specified
+  addLocal('2001:db8::15::47', false)
+
+Listen addresses cannot be modified at runtime and must be specified in the configuration file.
+
+As dnsdist is IPv4 and IPv6 agnostic, this means that dnsdist internally does not know the difference.
+So feel free to listen on the magic ``0.0.0.0`` or ``::`` addresses, dnsdist does the right thing to set the return address of queries, but set your :term:`ACL` properly.
+
+Modifying the ACL
+-----------------
+
+ACLs can be modfied at runtime from the :ref:`Console`.
+To inspect the currently active :term:`ACL`, run :func:`showACL`.
+
+To add a new network range to the existing ACL, use :func:`addACL`:
+
+.. code-block:: lua
+
+  addACL('192.0.2.0/25')
+  addACL('2001:db8::1') -- No netmask specified, only allow this address
+
+dnsdist also has the :func:`setACL` function that accepts a list of netmasks and resets the ACL to that list:
+
+
+.. code-block:: lua
+
+  setACL({'192.0.2.0/25', '2001:db8:15::bea/64'})
+
diff --git a/pdns/dnsdistdist/docs/advanced/ebpf.rst b/pdns/dnsdistdist/docs/advanced/ebpf.rst
new file mode 100644 (file)
index 0000000..d0fe4c4
--- /dev/null
@@ -0,0 +1,57 @@
+eBPF Socket Filtering
+=====================
+
+:program:`dnsdist` can use `eBPF <http://www.brendangregg.com/ebpf.html>`_ socket filtering on recent Linux kernels (4.1+) built with eBPF support (``CONFIG_BPF``, ``CONFIG_BPF_SYSCALL``, ideally ``CONFIG_BPF_JIT``).
+This feature might require an increase of the memory limit associated to a socket, via the sysctl setting ``net.core.optmem_max``.
+When attaching an eBPF program to a socket, the size of the program is checked against this limit, and the default value might not be enough.
+Large map sizes might also require an increase of ``RLIMIT_MEMLOCK``.
+
+This feature allows dnsdist to ask the kernel to discard incoming packets in kernel-space instead of them being copied to userspace just to be dropped, thus being a lot of faster.
+
+The BPF filter can be used to block incoming queries manually::
+
+  > bpf = newBPFFilter(1024, 1024, 1024)
+  > bpf:attachToAllBinds()
+  > bpf:block(newCA("2001:DB8::42"))
+  > bpf:blockQName(newDNSName("evildomain.com"), 255)
+  > bpf:getStats()
+  [2001:DB8::42]: 0
+  evildomain.com. 255: 0
+  > bpf:unblock(newCA("2001:DB8::42"))
+  > bpf:unblockQName(newDNSName("evildomain.com"), 255)
+  > bpf:getStats()
+
+The :meth:`BPFFilter:blockQName` method can be used to block queries based on the exact qname supplied, in a case-insensitive way, and an optional qtype.
+Using the 255 (ANY) qtype will block all queries for the qname, regardless of the qtype.
+Contrary to source address filtering, qname filtering only works over UDP. TCP qname filtering can be done the usual way::
+
+  addAction(AndRule({TCPRule(true), makeRule("evildomain.com")}), DropAction())
+
+The :meth:`BPFFilter:attachToAllBinds` method attaches the filter to every existing bind at runtime, but it's also possible to define a default BPF filter at configuration time, so it's automatically attached to every bind::
+
+  bpf = newBPFFilter(1024, 1024, 1024)
+  setDefaultBPFFilter(bpf)
+
+Finally, it's also possible to attach it to specific binds at runtime::
+
+  > bpf = newBPFFilter(1024, 1024, 1024)
+  > showBinds()
+  #   Address              Protocol  Queries
+  0   [::]:53              UDP       0
+  1   [::]:53              TCP       0
+  > bd = getBind(0)
+  > bd:attachFilter(bpf)
+
+:program:`dnsdist` also supports adding dynamic, expiring blocks to a BPF filter::
+
+  bpf = newBPFFilter(1024, 1024, 1024)
+  setDefaultBPFFilter(bpf)
+  dbpf = newDynBPFFilter(bpf)
+  function maintenance()
+          addBPFFilterDynBlocks(exceedQRate(20, 10), dbpf, 60)
+          dbpf:purgeExpired()
+  end
+
+This will dynamically block all hosts that exceeded 20 queries/s as measured over the past 10 seconds, and the dynamic block will last for 60 seconds.
+
+This feature has been successfully tested on Arch Linux, Arch Linux ARM, Fedora Core 23 and Ubuntu Xenial
diff --git a/pdns/dnsdistdist/docs/advanced/ecs.rst b/pdns/dnsdistdist/docs/advanced/ecs.rst
new file mode 100644 (file)
index 0000000..2264031
--- /dev/null
@@ -0,0 +1,16 @@
+Using ENDS Client Subnet
+------------------------
+
+In order to provide the downstream server with the address of the real client, or at least the one talking to dnsdist, the ``useClientSubnet`` parameter can be used when creating a :func:`new server <newServer>`.
+This parameter indicates whether an EDNS Client Subnet option should be added to the request.
+If the incoming request already contains an EDNS Client Subnet value, it will not be overriden unless :func:`setECSOverride` is set to ``true``.
+The default source prefix-length is 24 for IPv4 and 56 for IPv6, meaning that for a query received from 192.0.2.42, the EDNS Client Subnet value sent to the backend will be 192.0.2.0.
+This can be changed with :func:`setECSSourcePrefixV4` and :func:`setECSSourcePrefixV6`.
+
+In addition to the global settings, rules and Lua bindings can alter this behavior per query:
+
+ * calling :func:`DisableECSAction` or setting ``dq.useECS`` to ``false`` prevents the sending of the ECS option.
+ * calling :func:`ECSOverrideAction` or setting ``dq.ecsOverride`` will override the global :func:`setECSOverride` value.
+ * calling :func:`ECSPrefixLengthAction(v4, v6)` or setting ``dq.ecsPrefixLength`` will override the global :func:`setECSSourcePrefixV4()` and :func:`setECSSourcePrefixV6()` values.
+
+In effect this means that for the EDNS Client Subnet option to be added to the request, ``useClientSubnet`` should be set to ``true`` for the backend used (default to ``false``) and ECS should not have been disabled by calling :func:`DisableECSAction` or setting ``dq.useECS`` to ``false`` (default to true).
diff --git a/pdns/dnsdistdist/docs/advanced/index.rst b/pdns/dnsdistdist/docs/advanced/index.rst
new file mode 100644 (file)
index 0000000..212ee45
--- /dev/null
@@ -0,0 +1,17 @@
+Advanced Topics
+===============
+
+These chapters contain information on the advanced features of dnsdist
+
+.. toctree::
+   :maxdepth: 2
+
+   acl
+   teeaction
+   luaaction
+   timedipsetrule
+   ecs
+   qpslimits
+   ebpf
+   tuning
+   snmp
diff --git a/pdns/dnsdistdist/docs/advanced/luaaction.rst b/pdns/dnsdistdist/docs/advanced/luaaction.rst
new file mode 100644 (file)
index 0000000..d3c1f13
--- /dev/null
@@ -0,0 +1,20 @@
+Lua actions in rules
+====================
+
+While we can pass every packet through the :func:`blockFilter` functions, it is also possible to configure :program:`dnsdist` to only hand off some packets for Lua inspection. 
+If you think Lua is too slow for your query load, or if you are doing heavy processing in Lua, this may make sense.
+
+To select specific packets for Lua attention, use :func:`addLuaAction` or :func:`addLuaReponseAction`.
+
+A sample configuration could look like this::
+
+  function luarule(dq)
+    if(dq.qtype==35) -- NAPTR
+    then
+      return DNSAction.Pool, "abuse" -- send to abuse pool
+    else
+      return DNSAction.None, ""      -- no action
+    end
+  end
+
+  addLuaAction(AllRule(), luarule)
diff --git a/pdns/dnsdistdist/docs/advanced/qpslimits.rst b/pdns/dnsdistdist/docs/advanced/qpslimits.rst
new file mode 100644 (file)
index 0000000..dc1795b
--- /dev/null
@@ -0,0 +1,30 @@
+Rules for traffic exceeding QPS limits
+======================================
+
+Traffic that exceeds a QPS limit, in total or per IP (subnet) can be matched by the :func:`MaxQPSIPRule`-rule. For example:
+
+.. code-block:: lua
+
+  addDelay(MaxQPSIPRule(5, 32, 48), 100)
+
+This measures traffic per IPv4 address and per /48 of IPv6, and if traffic for such an address (range) exceeds 5 :term:`qps`, it gets delayed by 100ms.
+
+As another example:
+
+.. code-block:: lua
+
+  addAction(MaxQPSIPRule(5), NoRecurseAction())
+
+This strips the Recursion Desired (RD) bit from any traffic per IPv4 or IPv6 /64 that exceeds 5 qps. This means any those traffic bins is allowed to make a recursor do 'work' for only 5 qps.
+
+If this is not enough, try:
+
+.. code-block:: lua
+
+  addAction(MaxQPSIPRule(5), DropAction())
+  -- or
+  addAction(MaxQPSIPRule(5), TCAction())
+
+This will respectively drop traffic exceeding that 5 QPS limit per IP or range, or return it with TC=1, forcing clients to fall back to TCP.
+
+To turn this per IP or range limit into a global limit, use ``NotRule(MaxQPSRule(5000))`` instead of :func:`MaxQPSIPRule`.
diff --git a/pdns/dnsdistdist/docs/advanced/snmp.rst b/pdns/dnsdistdist/docs/advanced/snmp.rst
new file mode 100644 (file)
index 0000000..7b0ff80
--- /dev/null
@@ -0,0 +1,38 @@
+SNMP support
+============
+
+:program:`dnsdist` supports exporting statistics and sending traps over SNMP when compiled with ``Net SNMP`` support, acting as an ``AgentX`` subagent.
+SNMP support is enabled via the :func:`snmpAgent` directive.
+
+By default, the only traps sent when Traps are enabled, are backend status change notifications.
+But custom traps can also be sent:
+
+ * from Lua, with :func:`sendCustomTrap` and :meth:`DNSQuestion:sendTrap`
+ * For selected queries and responses, using :func:`SNMPTrapAction` and :func:`SNMPTrapResponseAction`
+
+``Net SNMP snmpd`` doesn't accept subagent connections by default, so to use the SNMP features of :program:`dnsdist` the following line should be added to the ``snmpd.conf`` configuration file::
+
+  master agentx
+
+In addition to that, the permissions on the resulting socket might need to be adjusted so that the ``dnsdist`` user can write to it.
+This can be done with the following lines in ``snmpd.conf`` (assuming `dnsdist` is running as `dnsdist:dnsdist`)::
+
+  agentxperms 0700 0700 dnsdist dnsdist
+
+In order to allow the retrieval of statistics via SNMP, ``snmpd``'s access control has to configured.
+A very simple SNMPv2c setup only needs the configuration of a read-only community in ``snmpd.conf``::
+
+  rocommunity dnsdist42
+
+``snmpd`` also supports more secure SNMPv3 setup, using for example the ``createUser`` and ``rouser`` directives::
+
+  createUser myuser SHA "my auth key" AES "my enc key"
+  rouser myuser
+
+``snmpd`` can be instructed to send SNMPv2 traps to a remote SNMP trap receiver by adding the following directive to the ``snmpd.conf`` configuration file::
+
+  trap2sink 192.0.2.1
+
+The description of :program:`dnsdist`'s SNMP MIB is as follows:
+
+.. literalinclude:: ../../DNSDIST-MIB.txt
diff --git a/pdns/dnsdistdist/docs/advanced/teeaction.rst b/pdns/dnsdistdist/docs/advanced/teeaction.rst
new file mode 100644 (file)
index 0000000..44a3787
--- /dev/null
@@ -0,0 +1,19 @@
+TeeAction: copy the DNS traffic stream
+======================================
+
+This action sends off a copy of a UDP query to another server, and keeps statistics on the responses received. Sample use::
+
+  > addAction(AllRule(), TeeAction("192.0.2.54"))
+  > getAction(0):printStats()
+  refuseds    0
+  nxdomains   0
+  noerrors    0
+  servfails   0
+  recv-errors 0
+  tcp-drops   0
+  responses   0
+  other-rcode 0
+  send-errors 0
+  queries 0
+
+It is also possible to share a :func:`TeeAction` between several rules. Statistics will be combined in that case.
diff --git a/pdns/dnsdistdist/docs/advanced/timedipsetrule.rst b/pdns/dnsdistdist/docs/advanced/timedipsetrule.rst
new file mode 100644 (file)
index 0000000..96c33be
--- /dev/null
@@ -0,0 +1,66 @@
+Runtime-modifiable IP address sets
+==================================
+
+.. versionadded:: 1.2.0
+
+From within :func:`maintenance` or other places, we may find that certain IP
+addresses must be treated differently for a certain time.
+
+This may be used to temporarily shunt traffic to another pool for example.
+
+:func:`TimedIPSetRule` creates an object to which native IP addresses can be
+added in :class:`ComboAddress` form.
+
+.. function:: TimedIPSetRule() -> TimedIPSetRule
+
+  Returns a :class:`TimedIPSetRule`.
+
+.. class:: TimedIPSetRule
+
+  Can be used to handle IP addresses differentlt based on the date and time
+
+.. classmethod:: TimedIPSetRule:add(address, seconds)
+
+  Add an IP address to the set for the next ``second`` seconds.
+
+  :param ComboAddress address: The address to add
+  :param int seconds: Time to keep the address in the Rule
+
+.. classmethod:: TimedIPSetRule:cleanup()
+
+  Purge the set from expired IP addresses
+
+.. classmethod:: TimedIPSetRule:clear()
+
+  Clear the entire set
+
+.. classmethod:: TimedIPSetRule:slice()
+
+  Convert the TimedIPSetRule into a DNSRule that can be passed to :func:`addAction`
+
+A working example:
+
+.. code-block:: lua
+
+  tisrElGoog=TimedIPSetRule()
+  tisrRest=TimedIPSetRule()
+  addAction(tisrElGoog:slice(), PoolAction("elgoog"))
+  addAction(tisrRest:slice(), PoolAction(""))
+
+  elgoogPeople=newNMG()
+  elgoogPeople:addMask("192.168.5.0/28")
+
+  function pickPool(dq)
+          if(elgoogPeople:match(dq.remoteaddr)) -- in real life, this would be external
+          then
+                  print("Lua caught query for a googlePerson")
+                  tisrElGoog:add(dq.remoteaddr, 10)
+                  return DNSAction.Pool, "elgoog"
+          else
+                  print("Lua caught query for restPerson")
+                  tisrRest:add(dq.remoteaddr, 60)
+                  return DNSAction.None, ""
+          end
+  end
+
+  addLuaAction(AllRule(), pickPool)
diff --git a/pdns/dnsdistdist/docs/advanced/tuning.rst b/pdns/dnsdistdist/docs/advanced/tuning.rst
new file mode 100644 (file)
index 0000000..1c90e25
--- /dev/null
@@ -0,0 +1,60 @@
+Performance Tuning
+==================
+
+First, a few words about :program:`dnsdist` architecture:
+
+ * Each local bind has its own thread listening for incoming UDP queries
+ * and its own thread listening for incoming TCP connections, dispatching them right away to a pool of threads
+ * Each backend has its own thread listening for UDP responses
+ * A maintenance thread calls the maintenance() Lua function every second if any, and is responsible for cleaning the cache
+ * A health check thread checks the backends availability
+ * A control thread handles console connections
+ * A carbon thread exports statistics to carbon servers if needed
+ * One or more webserver threads handle queries to the internal webserver
+
+The maximum number of threads in the TCP pool is controlled by the :func:`setMaxTCPClientThreads` directive, and defaults to 10.
+This number can be increased to handle a large number of simultaneous TCP connections.
+If all the TCP threads are busy, new TCP connections are queued while they wait to be picked up.
+
+The maximum number of queued connections can be configured with :func:`setMaxTCPQueuedConnections` and defaults to 1000.
+Any value larger than 0 will cause new connections to be dropped if there are already too many queued.
+By default, every TCP worker thread has its own queue, and the incoming TCP connections are dispatched to TCP workers on a round-robin basis.
+This might cause issues if some connections are taking a very long time, since incoming ones will be waiting until the TCP worker they have been assigned to has finished handling its current query, while other TCP workers might be available.
+
+The experimental :func:`setTCPUseSinglePipe` directive can be used so that all the incoming TCP connections are put into a single queue and handled by the first TCP worker available.
+
+When dispatching UDP queries to backend servers, dnsdist keeps track of at most **n** outstanding queries for each backend.
+This number **n** can be tuned by the :func:`setMaxUDPOutstanding` directive, defaulting to 10240, with a maximum value of 65535.
+Large installations are advised to increase the default value at the cost of a slightly increased memory usage.
+
+Most of the query processing is done in C++ for maximum performance, but some operations are executed in Lua for maximum flexibility:
+
+ * The :func:`blockfilter` function
+ * Rules added by :func:`addLuaAction`
+ * Server selection policies defined via :func:`setServerPolicyLua` or :func:`newServerPolicy`
+
+While Lua is fast, its use should be restricted to the strict necessary in order to achieve maximum performance, it might be worth considering using LuaJIT instead of Lua.
+When Lua inspection is needed, the best course of action is to restrict the queries sent to Lua inspection by using :func:`addLuaAction` instead of inspecting all queries in the :func:`blockfilter` function.
+
+:program:`dnsdist` design choices mean that the processing of UDP queries is done by only one thread per local bind.
+This is great to keep lock contention to a low level, but might not be optimal for setups using a lot of processing power, caused for example by a large number of complicated rules.
+To be able to use more CPU cores for UDP queries processing, it is possible to use the ``reuseport`` parameter of the :func:`addLocal` and :func:`setLocal` directives to be able to add several identical local binds to dnsdist::
+
+  addLocal("192.0.2.1:53", {reuseport=true})
+  addLocal("192.0.2.1:53", {reuseport=true})
+  addLocal("192.0.2.1:53", {reuseport=true})
+  addLocal("192.0.2.1:53", {reuseport=true})
+
+:program:`dnsdist` will then add four identical local binds as if they were different IPs or ports, start four threads to handle incoming queries and let the kernel load balance those randomly to the threads, thus using four CPU cores for rules processing.
+Note that this require ``SO_REUSEPORT`` support in the underlying operating system (added for example in Linux 3.9).
+Please also be aware that doing so will increase lock contention and might not therefore scale linearly.
+This is especially true for Lua-intensive setups, because Lua processing in dnsdist is serialized by an unique lock for all threads.
+
+Another possibility is to use the reuseport option to run several dnsdist processes in parallel on the same host, thus avoiding the lock contention issue at the cost of having to deal with the fact that the different processes will not share informations, like statistics or DDoS offenders.
+
+The UDP threads handling the responses from the backends do not use a lot of CPU, but if needed it is also possible to add the same backend several times to the dnsdist configuration to distribute the load over several responder threads::
+
+  newServer({address="192.0.2.127:53", name="Backend1"})
+  newServer({address="192.0.2.127:53", name="Backend2"})
+  newServer({address="192.0.2.127:53", name="Backend3"})
+  newServer({address="192.0.2.127:53", name="Backend4"})
diff --git a/pdns/dnsdistdist/docs/changelog.rst b/pdns/dnsdistdist/docs/changelog.rst
new file mode 100644 (file)
index 0000000..62fa48d
--- /dev/null
@@ -0,0 +1,802 @@
+Changelog
+=========
+
+.. changelog::
+  :version: 1.2.0
+
+  .. change::
+    :tags: Improvements
+    :pullreq: 4852
+    :tickets: 4851
+
+    DNSName: Check that both first two bits are set in compressed labels.
+
+  .. change::
+    :tags: Improvements
+    :pullreq: 4285
+    :tickets: 4131, 4155
+
+    Handle unreachable servers at startup, reconnect stale sockets
+
+  .. change::
+    :tags: Improvements
+    :pullreq: 4474
+    :tickets: 4471
+
+    Gracefully handle invalid addresses in :func:`newServer`.
+
+  .. change::
+    :tags: New Features
+    :pullreq: 4536
+    :tickets: 4527
+
+    Add an option to 'mute' UDP responses per bind.
+
+  .. change::
+    :tags: New Features, Performance
+    :pullreq: 4611
+
+    Add TCP management options from :rfc:`RFC 7766 section 10 <7766#section-10>`.
+
+  .. change::
+    :tags: Bug Fixes
+    :pullreq: 4775
+
+    LuaWrapper: Use the correct index when storing a function.
+
+  .. change::
+    :tags: New Features
+    :pullreq: 4779
+    :tickets: 4562
+
+    Save history to home-dir, only use CWD as a last resort.
+
+  .. change::
+    :tags: New Features
+    :pullreq: 4898
+
+    Add the :func:`setRingBuffersSize` directive to allows changing the ringbuffer size.
+
+  .. change::
+    :tags: Improvements, Security
+    :pullreq: 4815
+
+    Merge the client and server nonces to prevent replay attacks.
+
+  .. change::
+    :tags: Improvements
+    :pullreq: 4786
+
+    Use ``IP_BIND_ADDRESS_NO_PORT`` when available.
+
+  .. change::
+    :tags: Bug Fixes
+    :pullreq: 4785
+    :tickets: 4689
+
+    Send a latency of 0 over carbon, null over API for down servers.
+
+  .. change::
+    :tags: Improvements
+    :pullreq: 4780
+    :tickets: 4775, 4660
+
+    Add an optional ``seconds`` parameter to :func:`statNodeRespRing`.
+
+  .. change::
+    :tags: Improvements
+    :pullreq: 4910
+
+    Report a more specific lua version and report luajit in ``--version``.
+
+  .. change::
+    :tags: Improvements, DNSCrypt
+    :pullreq: 4813, 4926
+
+    Store the computed shared key and reuse it for the response for DNSCrypt messages.
+
+  .. change::
+    :tags: New Features, Protobuf
+    :pullreq: 4776
+    :tickets: 4709
+
+    Add an option to export CNAME records over protobuf.
+
+  .. change::
+    :tags: New Features
+    :pullreq: 4787
+    :tickets: 4707
+
+    Allow TTL alteration via Lua.
+
+  .. change::
+    :tags: New Features
+    :pullreq: 4837
+
+    Add :func:`RDRule` to match queries with the ``RD`` flag set.
+
+  .. change::
+    :tags: New Features
+    :pullreq: 4897
+
+    Add :func:`setWHashedPertubation` for consistent ``whashed`` results.
+
+  .. change::
+    :tags: New Features
+    :pullreq: 4818
+
+    Add ``tcpConnectTimeout`` to :func:`newServer`.
+
+  .. change::
+    :tags: Bug Fixes
+    :pullreq: 4911
+
+    Fix negative port detection for IPv6 addresses on 32-bit.
+
+  .. change::
+    :tags: Bug Fixes
+    :pullreq: 4877
+    :tickets: 4579
+
+    Fix crashed on SmartOS/Illumos (Roman Dayneko).
+
+  .. change::
+    :tags: New Features
+    :pullreq: 4788, 5036
+    :tickets: 4708
+
+    Add cache hit response rules.
+
+  .. change::
+    :tags: Improvements, Performance
+    :pullreq: 4817
+
+    Add :func:`setTCPUseSinglePipe` to use a single TCP waiting queue.
+
+  .. change::
+    :tags: Bug Fixes
+    :pullreq: 4859
+    :tickets: 4857
+
+    Change ``truncateTC`` to defaulting to off, having it enabled by default causes an compatibility with :rfc:`6891` (Robin Geuze).
+
+  .. change::
+    :tags: Bug Fixes
+    :pullreq: 4987, 5037
+    :tickets: 4983
+
+    Don't cache answers without any TTL (like SERVFAIL).
+
+  .. change::
+    :tags: Improvements, Performance
+    :pullreq: 4985, 5501
+    :tickets: 5494
+
+    Add ``sendSizeAndMsgWithTimeout`` to send size and data in a single call and use it for TCP Fast Open towards backends.
+
+  .. change::
+    :tags: Improvements
+    :pullreq: 5056
+
+    Prevent issues by unshadowing variables.
+
+  .. change::
+    :tags: New Features, SNMP
+    :pullreq: 4989, 5123, 5204
+
+    Add :doc:`SNMP support <advanced/snmp>`.
+
+  .. change::
+    :tags: Bug Fixes, Performance
+    :pullreq: 4950
+    :tickets: 4761
+
+    Refactor SuffixMatchNode using a SuffixMatchTree.
+
+  .. change::
+    :tags: Improvements
+    :pullreq: 4920
+
+    Register DNSName::chopOff (@plzz).
+
+  .. change::
+    :tags: New Features
+    :pullreq: 5070
+
+    Allow passing :class:`DNSName`\ s as DNSRules.
+
+  .. change::
+    :tags: Bug Fixes, Webserver
+    :pullreq: 5089
+
+    Send an HTTP 404 on unknown API paths.
+
+  .. change::
+    :tags: Improvements, Performance
+    :pullreq: 4958
+
+    Tune systemd unit-file for medium-sized installations (Winfried Angele).
+
+  .. change::
+    :tags: New Features
+    :pullreq: 5113
+
+    Add support for setting the server selection policy on a per pool basis (Robin Geuze).
+
+  .. change::
+    :tags: Improvements
+    :pullreq: 5150, 5171
+    :tickets: 5053
+
+    Make :func:`includeDirectory` work sorted (Robin Geuze).
+
+  .. change::
+    :tags: Improvements, LuaWrapper
+    :pullreq: 5147
+
+    Allow embedded NULs in strings received from Lua.
+
+  .. change::
+    :tags: New Features
+    :pullreq: 5159
+
+    Add a ``suffixMatch`` parameter to :meth:`PacketCache:expungeByName` (Robin Geuze).
+
+  .. change::
+    :tags: Improvements
+    :pullreq: 5163
+
+    Cleanup closed TCP downstream connections.
+
+  .. change::
+    :tags: Bug Fixes
+    :pullreq: 5194
+
+    Fix destination port reporting on "any" binds.
+
+  .. change::
+    :tags: New Features
+    :pullreq: 5136
+    :tickets: 5126
+
+    Add an option so the packet cache entries don't age.
+
+  .. change::
+    :tags: Bug Fixes, Security
+    :pullreq: 5199
+
+    Unified ``-k`` and :func:`setKey` behaviour for client and server mode now.
+
+  .. change::
+    :tags: Improvements
+    :pullreq: 5230
+
+    Improve reporting of C++ exceptions that bubble up via Lua.
+
+  .. change::
+    :tags: Improvements, Performance
+    :pullreq: 5185
+
+    Add the possiblity to fill a :class:`NetmaskGroup` (using :meth:`NetmaskGroup:addMask`) from `exceeds*` results.
+
+  .. change::
+    :tags: Improvements
+    :pullreq: 5253
+
+    Add better logging on queries that get dropped, timed out or received.
+
+  .. change::
+    :tags: New Features
+    :pullreq: 5235
+
+    Add :func:`QNameRule`.
+
+  .. change::
+    :tags: Bug Fixes
+    :pullreq: 5320
+
+    Correctly truncate EDNS Client Subnetmasks.
+
+  .. change::
+    :tags: Improvements
+    :pullreq: 5342
+
+    Print useful messages when query and response actions are mixed.
+
+  .. change::
+    :tags: New Features
+    :pullreq: 5337
+
+    Add an optional action to :func:`addDynBlocks`.
+
+  .. change::
+    :tags: New Features
+    :pullreq: 5344
+
+    Add an optional interface parameter to :func:`addLocal`/:func:`setLocal`.
+
+  .. change::
+    :tags: Bug Fixes, Performance
+    :pullreq: 5359
+
+    Get rid of ``std::move()`` calls preventing copy elision.
+
+  .. change::
+    :tags: Bug Fixes
+    :pullreq: 5369
+    :tickets: 5365
+
+    Fix :func:`RecordsTypeCountRule`\ 's handling of the # of records in a section.
+
+  .. change::
+    :tags: New Features
+    :pullreq: 5386
+
+    Make a ``truncate`` action available to DynBlock and Lua.
+
+  .. change::
+    :tags: Bug Fixes
+    :pullreq: 5383
+    :tickets: 5287
+
+    Change stats functions to always return lowercase names (Robin Geuze).
+
+  .. change::
+    :tags: New Features
+    :pullreq: 5336
+
+    Implement a runtime changeable rule that matches IP address for a certain time called :func:`TimedIPSetRule`.
+
+  .. change::
+    :tags: Bug Fixes
+    :pullreq: 5449, 5454
+
+    Only use TCP Fast Open when supported and prevent compiler warnings.
+
+  .. change::
+    :tags: Improvements
+    :pullreq: 5497
+
+    Add ``DNSRule::toString()`` and add virtual destructors to DNSRule, DNSAction and DNSResponseAction so the destructors of derived classes are run even when deleted via the base type.
+
+  .. change::
+    :tags: New Features
+    :pullreq: 5496
+
+    Add support for returning several IPs to spoof from Lua.
+
+  .. change::
+    :tags: New Features
+    :pullreq: 5490, 5508
+    :tickets: 5420, 5507
+
+    Add Lua bindings to be able to rotate DNSCrypt keys, see :doc:`guides/dnscrypt`.
+
+  .. change::
+    :tags: Improvements, Performance
+    :pullreq: 5353
+
+    Add labels count to StatNode, only set the name once.
+
+  .. change::
+    :tags: Removals
+    :pullreq: 5514
+    :tickets: 5513
+
+    Remove BlockFilter.
+
+1.1.0
+-----
+
+Released December 29th 2016
+
+Changes since 1.1.0-beta2:
+
+Improvements
+~~~~~~~~~~~~
+
+-  `#4783 <https://github.com/PowerDNS/pdns/pull/4783>`__: Add -latomic
+   on powerpc
+-  `#4812 <https://github.com/PowerDNS/pdns/pull/4812>`__: Handle
+   header-only responses, handle Refused as Servfail in the cache
+
+Bug fixes
+~~~~~~~~~
+
+-  `#4762 <https://github.com/PowerDNS/pdns/pull/4762>`__:
+   SuffixMatchNode: Fix an insertion issue for an existing node
+-  `#4772 <https://github.com/PowerDNS/pdns/pull/4772>`__: Fix dnsdist
+   initscript config check
+
+1.1.0-beta2
+-----------
+
+Released December 14th 2016
+
+Changes since 1.1.0-beta1:
+
+New features
+~~~~~~~~~~~~
+
+-  `#4518 <https://github.com/PowerDNS/pdns/pull/4518>`__: Fix dynblocks
+   over TCP, allow refusing dyn blocked queries
+-  `#4519 <https://github.com/PowerDNS/pdns/pull/4519>`__: Allow
+   altering the ECS behavior via rules and Lua
+-  `#4535 <https://github.com/PowerDNS/pdns/pull/4535>`__: Add
+   ``DNSQuestion:getDO()``
+-  `#4653 <https://github.com/PowerDNS/pdns/pull/4653>`__:
+   ``getStatisticsCounters()`` to access counters from Lua
+-  `#4657 <https://github.com/PowerDNS/pdns/pull/4657>`__: Add
+   ``includeDirectory(dir)``
+-  `#4658 <https://github.com/PowerDNS/pdns/pull/4658>`__: Allow editing
+   the ACL via the API
+-  `#4702 <https://github.com/PowerDNS/pdns/pull/4702>`__: Add
+   ``setUDPTimeout(n)``
+-  `#4726 <https://github.com/PowerDNS/pdns/pull/4726>`__: Add an option
+   to return ServFail when no server is available
+-  `#4748 <https://github.com/PowerDNS/pdns/pull/4748>`__: Add
+   ``setCacheCleaningPercentage()``
+
+Improvements
+~~~~~~~~~~~~
+
+-  `#4533 <https://github.com/PowerDNS/pdns/pull/4533>`__: Fix building
+   with clang on OS X and FreeBSD
+-  `#4537 <https://github.com/PowerDNS/pdns/pull/4537>`__: Replace
+   luawrapper's std::forward/std::make\_tuple combo with
+   std::forward\_as\_tuple (Sangwhan "fish" Moon)
+-  `#4596 <https://github.com/PowerDNS/pdns/pull/4596>`__: Change the
+   default max number of queued TCP conns to 1000
+-  `#4632 <https://github.com/PowerDNS/pdns/pull/4632>`__: Improve
+   dnsdist error message on a common typo/config mistake
+-  `#4694 <https://github.com/PowerDNS/pdns/pull/4694>`__: Don't use a
+   const\_iterator for erasing (fix compilation with some versions of
+   gcc)
+-  `#4715 <https://github.com/PowerDNS/pdns/pull/4715>`__: Specify that
+   dnsmessage.proto uses protobuf version 2
+-  `#4765 <https://github.com/PowerDNS/pdns/pull/4765>`__: Some service
+   improvements
+
+Bug fixes
+~~~~~~~~~
+
+-  `#4425 <https://github.com/PowerDNS/pdns/pull/4425>`__: Fix a
+   protobuf regression (requestor/responder mix-up) caused by a94673e
+-  `#4541 <https://github.com/PowerDNS/pdns/pull/4541>`__: Fix insertion
+   issues in SuffixMatchTree, move it to dnsname.hh
+-  `#4553 <https://github.com/PowerDNS/pdns/pull/4553>`__: Flush output
+   in single command client mode
+-  `#4578 <https://github.com/PowerDNS/pdns/pull/4578>`__: Fix
+   destination address reporting
+-  `#4640 <https://github.com/PowerDNS/pdns/pull/4640>`__: Don't exit
+   dnsdist on an exception in maintenance
+-  `#4721 <https://github.com/PowerDNS/pdns/pull/4721>`__: Handle
+   exceptions in the UDP responder thread
+-  `#4734 <https://github.com/PowerDNS/pdns/pull/4734>`__: Add the TCP
+   socket to the map only if the connection succeeds. Closes #4733
+-  `#4742 <https://github.com/PowerDNS/pdns/pull/4742>`__: Decrement the
+   queued TCP conn count if writing to the pipe fails
+-  `#4743 <https://github.com/PowerDNS/pdns/pull/4743>`__: Ignore
+   newBPFFilter() and newDynBPFFilter() in client mode
+-  `#4753 <https://github.com/PowerDNS/pdns/pull/4753>`__: Fix FD leak
+   on TCP connection failure, handle TCP worker creation failure
+-  `#4764 <https://github.com/PowerDNS/pdns/pull/4764>`__: Prevent race
+   while creating new TCP worker threads
+
+1.1.0-beta1
+-----------
+
+Released September 1st 2016
+
+Changes since 1.0.0:
+
+New features
+~~~~~~~~~~~~
+
+-  `#3762 <https://github.com/PowerDNS/pdns/pull/3762>`__ Teeaction:
+   send copy of query to second nameserver, sponge responses
+-  `#3876 <https://github.com/PowerDNS/pdns/pull/3876>`__ Add
+   ``showResponseRules()``, ``{mv,rm,top}ResponseRule()``
+-  `#3936 <https://github.com/PowerDNS/pdns/pull/3936>`__ Filter on
+   opcode, records count/type, trailing data
+-  `#3975 <https://github.com/PowerDNS/pdns/pull/3975>`__ Make dnsdist
+   {A,I}XFR aware, document possible issues
+-  `#4006 <https://github.com/PowerDNS/pdns/pull/4006>`__ Add eBPF
+   source address and qname/qtype filtering
+-  `#4008 <https://github.com/PowerDNS/pdns/pull/4008>`__ Node
+   infrastructure for querying recent traffic
+-  `#4042 <https://github.com/PowerDNS/pdns/pull/4042>`__ Add
+   server-side TCP Fast Open support
+-  `#4050 <https://github.com/PowerDNS/pdns/pull/4050>`__ Add
+   ``clearRules()`` and ``setRules()``
+-  `#4114 <https://github.com/PowerDNS/pdns/pull/4114>`__ Add
+   ``QNameLabelsCountRule()`` and ``QNameWireLengthRule()``
+-  `#4116 <https://github.com/PowerDNS/pdns/pull/4116>`__ Added src
+   boolean to NetmaskGroupRule to match destination address (Reinier
+   Schoof)
+-  `#4175 <https://github.com/PowerDNS/pdns/pull/4175>`__ Implemented
+   query counting (Reinier Schoof)
+-  `#4244 <https://github.com/PowerDNS/pdns/pull/4244>`__ Add a
+   ``setCD`` parameter to set cd=1 on health check queries
+-  `#4284 <https://github.com/PowerDNS/pdns/pull/4284>`__ Add
+   RCodeRule(), Allow, Delay and Drop response actions
+-  `#4305 <https://github.com/PowerDNS/pdns/pull/4305>`__ Add an
+   optional Lua callback for altering a Protobuf message
+-  `#4309 <https://github.com/PowerDNS/pdns/pull/4309>`__ Add
+   showTCPStats function (RobinGeuze)
+-  `#4329 <https://github.com/PowerDNS/pdns/pull/4329>`__ Add options to
+   LogAction() so it can append (instead of truncate) (Duane Wessels)
+
+Improvements
+~~~~~~~~~~~~
+
+-  `#3714 <https://github.com/PowerDNS/pdns/pull/3714>`__ Add
+   documentation links to dnsdist.service (Ruben Kerkhof)
+-  `#3754 <https://github.com/PowerDNS/pdns/pull/3754>`__ Allow the use
+   of custom headers in the web server
+-  `#3826 <https://github.com/PowerDNS/pdns/pull/3826>`__ Implement a
+   'quiet' mode for SuffixMatchNodeRule()
+-  `#3836 <https://github.com/PowerDNS/pdns/pull/3836>`__ Log the
+   content of webserver's exceptions
+-  `#3858 <https://github.com/PowerDNS/pdns/pull/3858>`__ Only log
+   YaHTTP's parser exceptions in verbose mode
+-  `#3877 <https://github.com/PowerDNS/pdns/pull/3877>`__ Increase max
+   FDs in systemd unit, warn if clearly too low
+-  `#4019 <https://github.com/PowerDNS/pdns/pull/4019>`__ Add an
+   optional ``addECS`` option to ``TeeAction()``
+-  `#4029 <https://github.com/PowerDNS/pdns/pull/4029>`__ Add version
+   and feature information to version output
+-  `#4079 <https://github.com/PowerDNS/pdns/pull/4079>`__ Return an
+   error on RemoteLog{,Response}Action() w/o protobuf
+-  `#4246 <https://github.com/PowerDNS/pdns/pull/4246>`__ API now sends
+   pools as a JSON array instead of a string
+-  `#4302 <https://github.com/PowerDNS/pdns/pull/4302>`__ Add ``help()``
+   and ``showVersion()``
+-  `#4286 <https://github.com/PowerDNS/pdns/pull/4286>`__ Add response
+   rules to the API and Web status page
+-  `#4068 <https://github.com/PowerDNS/pdns/pull/4068>`__ Display the
+   dyn eBPF filters stats in the web interface
+
+Bug fixes
+~~~~~~~~~
+
+-  `#3755 <https://github.com/PowerDNS/pdns/pull/3755>`__ Fix RegexRule
+   example in dnsdistconf.lua
+-  `#3773 <https://github.com/PowerDNS/pdns/pull/3773>`__ Stop copying
+   the HTTP request headers to the response
+-  `#3837 <https://github.com/PowerDNS/pdns/pull/3837>`__ Remove dnsdist
+   service file on trusty
+-  `#3840 <https://github.com/PowerDNS/pdns/pull/3840>`__ Catch
+   WrongTypeException in client mode
+-  `#3906 <https://github.com/PowerDNS/pdns/pull/3906>`__ Keep the
+   servers ordered inside pools
+-  `#3988 <https://github.com/PowerDNS/pdns/pull/3988>`__ Fix
+   ``grepq()`` output in the README
+-  `#3992 <https://github.com/PowerDNS/pdns/pull/3992>`__ Fix some typos
+   in the AXFR/IXFR documentation
+-  `#3995 <https://github.com/PowerDNS/pdns/pull/3995>`__ Fix comparison
+   between signed and unsigned integer
+-  `#4049 <https://github.com/PowerDNS/pdns/pull/4049>`__ Fix dnsdist
+   rpm building script #4048 (Daniel Stirnimann)
+-  `#4065 <https://github.com/PowerDNS/pdns/pull/4065>`__ Include
+   editline/readline.h instead of readline.h/history.h
+-  `#4067 <https://github.com/PowerDNS/pdns/pull/4067>`__ Disable eBPF
+   support when BPF\_FUNC\_tail\_call is not found
+-  `#4069 <https://github.com/PowerDNS/pdns/pull/4069>`__ Fix a buffer
+   overflow when displaying an OpcodeRule
+-  `#4101 <https://github.com/PowerDNS/pdns/pull/4101>`__ Fix $
+   expansion in build-dnsdist-rpm
+-  `#4198 <https://github.com/PowerDNS/pdns/pull/4198>`__ newServer
+   setting maxCheckFailures makes no sense (stutiredboy)
+-  `#4205 <https://github.com/PowerDNS/pdns/pull/4205>`__ Prevent the
+   use of "any" addresses for downstream server
+-  `#4220 <https://github.com/PowerDNS/pdns/pull/4220>`__ Don't log an
+   error when parsing an invalid UDP query
+-  `#4348 <https://github.com/PowerDNS/pdns/pull/4348>`__ Fix invalid
+   outstanding count for {A,I}XFR over TCP
+-  `#4365 <https://github.com/PowerDNS/pdns/pull/4365>`__ Reset origFD
+   asap to keep the outstanding count correct
+-  `#4375 <https://github.com/PowerDNS/pdns/pull/4375>`__ Tuple requires
+   make\_tuple to initialize
+-  `#4380 <https://github.com/PowerDNS/pdns/pull/4380>`__ Fix
+   compilation with clang when eBPF support is enabled
+
+1.0.0
+-----
+
+Released April 21st 2016
+
+Changes since 1.0.0-beta1:
+
+Improvements
+~~~~~~~~~~~~
+
+-  `#3700 <https://github.com/PowerDNS/pdns/pull/3700>`__ Create user
+   from the RPM package to drop privs
+-  `#3712 <https://github.com/PowerDNS/pdns/pull/3712>`__ Make check
+   should run testrunner
+-  `#3713 <https://github.com/PowerDNS/pdns/pull/3713>`__ Remove
+   contrib/dnsdist.service (Ruben Kerkhof)
+-  `#3722 <https://github.com/PowerDNS/pdns/pull/3722>`__ Use LT\_INIT
+   and disable static objects (Ruben Kerkhof)
+-  `#3724 <https://github.com/PowerDNS/pdns/pull/3724>`__ Include
+   PDNS\_CHECK\_OS in configure (Christian Hofstaedtler)
+-  `#3728 <https://github.com/PowerDNS/pdns/pull/3728>`__ Document
+   libedit Ctrl-R workaround for CentOS 6
+-  `#3730 <https://github.com/PowerDNS/pdns/pull/3730>`__ Make
+   ``topBandwidth()`` behave like other top\* functions
+-  `#3731 <https://github.com/PowerDNS/pdns/pull/3731>`__ Clarify a bit
+   the documentation of load-balancing policies
+
+Bug fixes
+~~~~~~~~~
+
+-  `#3711 <https://github.com/PowerDNS/pdns/pull/3711>`__ Building rpm
+   needs systemd headers (Ruben Kerkhof)
+-  `#3736 <https://github.com/PowerDNS/pdns/pull/3736>`__ Add missing
+   Lua binding for NetmaskGroupRule()
+-  `#3739 <https://github.com/PowerDNS/pdns/pull/3739>`__ Drop
+   privileges after daemonizing and writing our pid
+
+1.0.0-beta1
+-----------
+
+Released April 14th 2016
+
+Changes since 1.0.0-alpha2:
+
+New features
+~~~~~~~~~~~~
+
+-  Per-pool packet cache
+-  Some actions do not stop the processing anymore when they match,
+   allowing more complex setups: Delay, Disable Validation, Log,
+   MacAddr, No Recurse and of course None
+-  The new RE2Rule() is available, using the RE2 regular expression
+   library to match queries, in addition to the existing POSIX-based
+   RegexRule()
+-  SpoofAction() now supports multiple A and AAAA records
+-  Remote logging of questions and answers via Protocol Buffer
+
+Improvements
+~~~~~~~~~~~~
+
+-  `#3405 <https://github.com/PowerDNS/pdns/pull/3405>`__ Add health
+   check logging, ``maxCheckFailures`` to backend
+-  `#3412 <https://github.com/PowerDNS/pdns/pull/3412>`__ Check config
+-  `#3440 <https://github.com/PowerDNS/pdns/pull/3440>`__ Client
+   operation improvements
+-  `#3466 <https://github.com/PowerDNS/pdns/pull/3466>`__ Add dq binding
+   for skipping packet cache in LuaAction (Jan Broer)
+-  `#3499 <https://github.com/PowerDNS/pdns/pull/3499>`__ Add support
+   for multiple carbon servers
+-  `#3504 <https://github.com/PowerDNS/pdns/pull/3504>`__ Allow
+   accessing the API with an optional API key
+-  `#3556 <https://github.com/PowerDNS/pdns/pull/3556>`__ Add an option
+   to limit the number of queued TCP connections
+-  `#3578 <https://github.com/PowerDNS/pdns/pull/3578>`__ Add a
+   ``disable-syslog`` option
+-  `#3608 <https://github.com/PowerDNS/pdns/pull/3608>`__ Export cache
+   stats to carbon
+-  `#3622 <https://github.com/PowerDNS/pdns/pull/3622>`__ Display the
+   ACL content on startup
+-  `#3627 <https://github.com/PowerDNS/pdns/pull/3627>`__ Remove ECS
+   option from response's OPT RR when necessary
+-  `#3633 <https://github.com/PowerDNS/pdns/pull/3633>`__ Count "TTL too
+   short" cache events
+-  `#3677 <https://github.com/PowerDNS/pdns/pull/3677>`__ systemd-notify
+   support
+
+Bug fixes
+~~~~~~~~~
+
+-  `#3388 <https://github.com/PowerDNS/pdns/pull/3388>`__ Lock the Lua
+   context before executing a LuaAction
+-  `#3433 <https://github.com/PowerDNS/pdns/pull/3433>`__ Check that the
+   answer matches the initial query
+-  `#3461 <https://github.com/PowerDNS/pdns/pull/3461>`__ Fix crash when
+   calling rmServer() with an invalid index
+-  `#3550 <https://github.com/PowerDNS/pdns/pull/3550>`__,\ `#3551 <https://github.com/PowerDNS/pdns/pull/3551>`__
+   Fix build failure on FreeBSD (Ruben Kerkhof)
+-  `#3594 <https://github.com/PowerDNS/pdns/pull/3594>`__ Prevent EOF
+   error for empty console response w/o sodium
+-  `#3634 <https://github.com/PowerDNS/pdns/pull/3634>`__ Prevent
+   dangling TCP fd in case setupTCPDownstream() fails
+-  `#3641 <https://github.com/PowerDNS/pdns/pull/3641>`__ Under
+   threshold, QPS action should return None, not Allow
+-  `#3658 <https://github.com/PowerDNS/pdns/pull/3658>`__ Fix a race
+   condition in MaxQPSIPRule
+
+1.0.0-alpha2
+------------
+
+Released February 5th 2016
+
+Changes since 1.0.0-alpha1:
+
+New features
+~~~~~~~~~~~~
+
+-  Lua functions now receive a DNSQuestion ``dq`` object instead of
+   several parameters. This adds a greater compatibility with PowerDNS
+   and allows adding more parameters without breaking the API
+   (`#3198 <https://github.com/PowerDNS/pdns/issues/3198>`__)
+-  Added a ``source`` option to ``newServer()`` to specify the local
+   address or interface used to contact a downstream server
+   (`#3138 <https://github.com/PowerDNS/pdns/issues/3138>`__)
+-  CNAME and IPv6-only support have been added to spoofed responses
+   (`#3064 <https://github.com/PowerDNS/pdns/issues/3064>`__)
+-  ``grepq()`` can be used to search for slow queries, along with
+   ``topSlow()``
+-  New Lua functions: ``addDomainCNAMESpoof()``, ``AllowAction()`` by
+   @bearggg, ``exceedQRate()``, ``MacAddrAction()``, ``makeRule()``,
+   ``NotRule()``, ``OrRule()``, ``QClassRule()``, ``RCodeAction()``,
+   ``SpoofCNAMEAction()``, ``SuffixMatchNodeRule()``, ``TCPRule()``,
+   ``topSlow()``
+-  ``NetmaskGroup`` support have been added in Lua
+   (`#3144 <https://github.com/PowerDNS/pdns/issues/3144>`__)
+-  Added ``MacAddrAction()`` to add the source MAC address to the
+   forwarded query
+   (`#3313 <https://github.com/PowerDNS/pdns/issues/3313>`__)
+
+Bug fixes
+~~~~~~~~~
+
+-  An issue in DelayPipe could make dnsdist crash at startup
+-  ``downstream-timeouts`` metric was not always updated
+-  ``truncateTC`` was unproperly updating the response length
+   (`#3126 <https://github.com/PowerDNS/pdns/issues/3126>`__)
+-  DNSCrypt responses larger than queries were unproperly truncated
+-  An issue prevented info message from being displayed in non-verbose
+   mode, fixed by Jan Broer
+-  Reinstating an expired Dynamic Rule was not correctly logged
+   (`#3323 <https://github.com/PowerDNS/pdns/issues/3323>`__)
+-  Initialized counters in the TCP client thread might have cause FD and
+   memory leak, reported by Martin Pels
+   (`#3300 <https://github.com/PowerDNS/pdns/issues/3300>`__)
+-  We now drop queries containing no question (qdcount == 0)
+   (`#3290 <https://github.com/PowerDNS/pdns/issues/3290>`__)
+-  Outstanding TCP queries count was not always correct
+   (`#3288 <https://github.com/PowerDNS/pdns/issues/3288>`__)
+-  A locking issue in exceedRespGen() might have caused crashs
+   (`#3277 <https://github.com/PowerDNS/pdns/issues/3277>`__)
+-  Useless sockets were created in client mode
+   (`#3257 <https://github.com/PowerDNS/pdns/issues/3257>`__)
+-  ``addAnyTCRule()`` was generating TC=1 responses even over TCP
+   (`#3251 <https://github.com/PowerDNS/pdns/issues/3251>`__)
+
+Web interface
+~~~~~~~~~~~~~
+
+-  Cleanup of the HTML by Sander Hoentjen
+-  Fixed an XSS reported by @janeczku
+   (`#3217 <https://github.com/PowerDNS/pdns/issues/3217>`__)
+-  Removed remote images
+-  Set the charset to UTF-8, added some security-related and CORS HTTP
+   headers
+-  Added server latency by Jan Broer
+   (`#3201 <https://github.com/PowerDNS/pdns/issues/3201>`__)
+-  Switched to official minified versions of JS scripts, by Sander
+   Hoentjen (`#3317 <https://github.com/PowerDNS/pdns/issues/3317>`__)
+-  Don't log unauthenticated HTTP request as an authentication failure
+
+Various documentation updates and minor cleanups:
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+-  Added documentation for Advanced DNS Protection features (Dynamic
+   rules, ``maintenance()``)
+-  Make ``topBandwidth()`` default to the top 10 clients
+-  Replaced readline with libedit
+-  Added GPL2 License
+   (`#3200 <https://github.com/PowerDNS/pdns/issues/3200>`__)
+-  Added incbin License
+   (`#3269 <https://github.com/PowerDNS/pdns/issues/3269>`__)
+-  Updated completion rules
+-  Removed wrong option ``--daemon-no`` by Stefan Schmidt
+
+1.0.0-alpha1
+------------
+
+Released December 24th 2015
+
+Initial release
diff --git a/pdns/dnsdistdist/docs/conf.py b/pdns/dnsdistdist/docs/conf.py
new file mode 100644 (file)
index 0000000..8df5fbe
--- /dev/null
@@ -0,0 +1,194 @@
+#!/usr/bin/env python3
+# -*- coding: utf-8 -*-
+#
+# dnsdist documentation build configuration file, created by
+# sphinx-quickstart on Thu Feb  9 00:08:08 2017.
+#
+# This file is execfile()d with the current directory set to its
+# containing dir.
+#
+# Note that not all possible configuration values are present in this
+# autogenerated file.
+#
+# All configuration values have a default; values that are commented out
+# serve to show the default.
+
+# If extensions (or modules to document with autodoc) are in another directory,
+# add these directories to sys.path here. If the directory is relative to the
+# documentation root, use os.path.abspath to make it absolute, like shown here.
+#
+# import os
+# import sys
+# sys.path.insert(0, os.path.abspath('.'))
+
+# -- General configuration ------------------------------------------------
+
+# If your documentation needs a minimal Sphinx version, state it here.
+#
+# needs_sphinx = '1.0'
+
+# Add any Sphinx extension module names here, as strings. They can be
+# extensions coming with Sphinx (named 'sphinx.ext.*') or your custom
+# ones.
+extensions = ['redjack.sphinx.lua', 'sphinxcontrib.httpdomain', 'sphinxjsondomain',
+              'sphinxcontrib.fulltoc', 'changelog']
+primary_domain = 'lua'
+
+# Add any paths that contain templates here, relative to this directory.
+templates_path = ['_templates']
+
+# The suffix(es) of source filenames.
+# You can specify multiple suffix as a list of string:
+#
+# source_suffix = ['.rst', '.md']
+source_suffix = '.rst'
+
+# The master toctree document.
+master_doc = 'index_TOC'
+
+# General information about the project.
+project = 'dnsdist'
+copyright = '2015-2017, PowerDNS.COM BV and its contributors'
+author = 'PowerDNS.COM BV and its contributors'
+
+# The version info for the project you're documenting, acts as replacement for
+# |version| and |release|, also used in various other places throughout the
+# built documents.
+#
+# The short X.Y version.
+version = '1.2'
+# The full version, including alpha/beta/rc tags.
+release = '1.2.0-alpha1'
+
+# The language for content autogenerated by Sphinx. Refer to documentation
+# for a list of supported languages.
+#
+# This is also used if you do content translation via gettext catalogs.
+# Usually you set "language" from the command line for these cases.
+language = None
+
+# List of patterns, relative to source directory, that match files and
+# directories to ignore when looking for source files.
+# This patterns also effect to html_static_path and html_extra_path
+exclude_patterns = ['_build', 'Thumbs.db', '.DS_Store']
+
+# The name of the Pygments (syntax highlighting) style to use.
+pygments_style = 'sphinx'
+
+# If true, `todo` and `todoList` produce output, else they produce nothing.
+todo_include_todos = False
+
+# -- Changelog Options ----------------------------------------------------
+
+changelog_render_ticket = "https://github.com/PowerDNS/pdns/issue/%s"
+changelog_render_pullreq = "https://github.com/PowerDNS/pdns/pull/%s"
+changelog_render_changeset = "https://github.com/PowerDNS/pdns/commit/%s"
+
+changelog_sections = ['New Features', 'Improvements', 'Bug Fixes', "Removals"]
+changelog_inner_tag_sort = ["Security", 'DNSCrypt', 'Protobuf', "Performance", 'Webserver']
+
+changelog_render_tags = False
+
+# -- Options for HTML output ----------------------------------------------
+
+# The theme to use for HTML and HTML Help pages.  See the documentation for
+# a list of builtin themes.
+#
+html_theme_path = ['_templates']
+html_theme = 'pdns_html'
+
+# Theme options are theme-specific and customize the look and feel of a theme
+# further.  For a list of options available for each theme, see the
+# documentation.
+#
+html_theme_options = {}
+
+# Add any paths that contain custom static files (such as style sheets) here,
+# relative to this directory. They are copied after the builtin static files,
+# so a file named "default.css" will overwrite the builtin "default.css".
+html_static_path = ['_static']
+
+html_favicon = '_static/favicon.ico'
+
+
+# -- Options for HTMLHelp output ------------------------------------------
+
+# Output file base name for HTML help builder.
+htmlhelp_basename = 'dnsdistdoc'
+
+
+# -- Options for LaTeX output ---------------------------------------------
+
+latex_elements = {
+    # The paper size ('letterpaper' or 'a4paper').
+    #
+    'papersize': 'a4paper',
+
+    # The font size ('10pt', '11pt' or '12pt').
+    #
+    # 'pointsize': '10pt',
+
+    # Additional stuff for the LaTeX preamble.
+    #
+    # 'preamble': '',
+
+    # Latex figure (float) alignment
+    #
+    # 'figure_align': 'htbp',
+}
+
+# Grouping the document tree into LaTeX files. List of tuples
+# (source start file, target name, title,
+#  author, documentclass [howto, manual, or own class]).
+latex_documents = [
+    (master_doc, 'dnsdist.tex', 'dnsdist',
+     'PowerDNS.COM BV', 'manual'),
+]
+
+latex_logo = '_static/powerdns-logo-trans.png'
+
+
+# -- Options for manual page output ---------------------------------------
+
+# One entry per manual page. List of tuples
+# (source start file, name, description, authors, manual section).
+man_pages = [
+    ('manpages/dnsdist.1', 'dnsdist', 'dnsdist',
+     [author], 1)
+]
+
+
+# -- Options for Texinfo output -------------------------------------------
+
+# Grouping the document tree into Texinfo files. List of tuples
+# (source start file, target name, title, author,
+#  dir menu entry, description, category)
+texinfo_documents = [
+    (master_doc, 'dnsdist', 'dnsdist',
+     author, 'dnsdist', 'One line description of project.',
+     'Miscellaneous'),
+]
+
+
+
+# -- Options for Epub output ----------------------------------------------
+
+# Bibliographic Dublin Core info.
+epub_title = project
+epub_author = author
+epub_publisher = author
+epub_copyright = copyright
+
+# The unique identifier of the text. This can be a ISBN number
+# or the project homepage.
+#
+# epub_identifier = ''
+
+# A unique identification for the text.
+#
+# epub_uid = ''
+
+# A list of files that should not be packed into the epub file.
+epub_exclude_files = ['search.html']
+
+
diff --git a/pdns/dnsdistdist/docs/glossary.rst b/pdns/dnsdistdist/docs/glossary.rst
new file mode 100644 (file)
index 0000000..367b1fb
--- /dev/null
@@ -0,0 +1,14 @@
+Glossary
+========
+
+.. glossary::
+
+  ACL
+    Access Control List
+
+  Open Resolver
+    A recursive DNS server available for many hosts on the internet.
+    Ususally without adequate rate-limiting, allowing it to be used in reflection attacks.
+
+  QPS
+    Queries Per Second
diff --git a/pdns/dnsdistdist/docs/guides/cache.rst b/pdns/dnsdistdist/docs/guides/cache.rst
new file mode 100644 (file)
index 0000000..e71fd63
--- /dev/null
@@ -0,0 +1,47 @@
+Caching Responses
+=================
+
+:program:`dnsdist` implements a simple but effective packet cache, not enabled by default.
+It is enabled per-pool, but the same cache can be shared between several pools.
+The first step is to define a cache, then to assign that cache to the chosen pool, the default one being represented by the empty string::
+
+  pc = newPacketCache(10000, 86400, 0, 60, 60)
+  getPool(""):setCache(pc)
+
+The first parameter (10000) is the maximum number of entries stored in the cache, and is the only one required.
+All the other parameters are optional and in seconds.
+The second one (86400) is the maximum lifetime of an entry in the cache, the third one (0) is the minimum TTL an entry should have to be considered for insertion in the cache, the fourth one (60) is the TTL used for a Server Failure or a Refused response.
+The last one (60) is the TTL that will be used when a stale cache entry is returned.
+
+For performance reasons the cache will pre-allocate buckets based on the maximum number of entries, so be careful to set the first parameter to a reasonable value.
+Something along the lines of a dozen bytes per pre-allocated entry can be expected on 64-bit.
+That does not mean that the memory is completely allocated up-front, the final memory usage depending mostly on the size of cached responses and therefore varying during the cache's lifetime.
+Assuming an average response size of 512 bytes, a cache size of 10000000 entries on a 64-bit host with 8GB of dedicated RAM would be a safe choice.
+
+The :func:`setStaleCacheEntriesTTL` directive can be used to allow dnsdist to use expired entries from the cache when no backend is available.
+Only entries that have expired for less than n seconds will be used, and the returned TTL can be set when creating a new cache with :func:`newPacketCache`.
+
+A reference to the cache affected to a specific pool can be retrieved with::
+
+  getPool("poolname"):getCache()
+
+And removed with::
+
+  getPool("poolname"):unsetCache()
+
+Cache usage stats (hits, misses, deferred inserts and lookups, collisions) can be displayed by using the :meth:`PacketCache:printStats` method::
+
+  getPool("poolname"):getCache():printStats()
+
+Expired cached entries can be removed from a cache using the :meth:`PacketCache:purgeExpired` method, which will remove expired entries from the cache until at most n entries remain in the cache.
+For example, to remove all expired entries::
+
+  getPool("poolname"):getCache():purgeExpired(0)
+
+Specific entries can also be removed using the :meth:`PacketCache:expungeByName` method::
+
+  getPool("poolname"):getCache():expungeByName(newDNSName("powerdns.com"), dnsdist.A)
+
+Finally, the :meth:`PacketCache:expunge` method will remove all entries until at most n entries remain in the cache::
+
+  getPool("poolname"):getCache():expunge(0)
diff --git a/pdns/dnsdistdist/docs/guides/console.rst b/pdns/dnsdistdist/docs/guides/console.rst
new file mode 100644 (file)
index 0000000..037ce8e
--- /dev/null
@@ -0,0 +1,39 @@
+.. _Console:
+
+Working with the dnsdist Console
+================================
+
+dnsdist can expose a commandline console over an encrypted tcp connection for controlling it, debugging DNS issues and retrieving statistics.
+
+The console can be enabled with :func:`controlSocket`:
+
+.. code-block:: lua
+
+  controlSocket('192.0.2.53:5900')
+
+To enable encryption, first generate a key with :func:`makeKey`::
+
+  $ ./dnsdist -l 127.0.0.1:5300
+  [..]
+  > makeKey()
+  setKey("ENCODED KEY")
+
+Add the generated :func:`setKey` line to you dnsdist configuration file, along with a :func:`controlSocket`:
+
+.. code-block:: lua
+
+  controlSocket('192.0.2.53:5199') -- Listen on this IP and port for client connections
+  setKey("ENCODED KEY")            -- Shared secret for the console
+
+Now you can run ``dnsdist -c`` to connect to the console.
+This makes dnsdist read its configuration file and use the :func:`controlSocket` and :func:`setKey` statements to set up its connection to the server.
+
+If you want to connect over the network, create a configuration file with the same two statements and run ``dnsdist -C /path/to/configfile -c``.
+
+Alternatively, you can specify the address and key on the client commandline::
+
+  dnsdist -K "ENCODED KEY" -c 192.0.2.53:5199
+
+.. warning::
+
+  This will leak the key into your shell's history and is **not** recommended.
diff --git a/pdns/dnsdistdist/docs/guides/dnscrypt.rst b/pdns/dnsdistdist/docs/guides/dnscrypt.rst
new file mode 100644 (file)
index 0000000..00b08d4
--- /dev/null
@@ -0,0 +1,27 @@
+DNSCrypt
+========
+
+:program:`dnsdist`, when compiled with ``--enable-dnscrypt``, can be used as a DNSCrypt server, uncurving queries before forwarding them to downstream servers and curving responses back.
+To make :program:`dnsdist` listen to incoming DNSCrypt queries on 127.0.0.1 port 8443, with a provider name of "2.providername", using a resolver certificate and associated key stored respectively in the resolver.cert and resolver.key files, the :func:`addDNSCryptBind` directive can be used::
+
+  addDNSCryptBind("127.0.0.1:8443", "2.providername", "/path/to/resolver.cert", "/path/to/resolver.key")
+
+To generate the provider and resolver certificates and keys, you can simply do::
+
+  > generateDNSCryptProviderKeys("/path/to/providerPublic.key", "/path/to/providerPrivate.key")
+  Provider fingerprint is: E1D7:2108:9A59:BF8D:F101:16FA:ED5E:EA6A:9F6C:C78F:7F91:AF6B:027E:62F4:69C3:B1AA
+  > generateDNSCryptCertificate("/path/to/providerPrivate.key", "/path/to/resolver.cert", "/path/to/resolver.key", serial, validFrom, validUntil)
+
+Ideally, the certificates and keys should be generated on an offline dedicated hardware and not on the resolver.
+The resolver key should be regularly rotated and should never touch persistent storage, being stored in a tmpfs with no swap configured.
+
+You can display the currently configured DNSCrypt binds with::
+
+  > showDNSCryptBinds()
+  #   Address              Provider Name        Serial   Validity              P. Serial P. Validity
+  0   127.0.0.1:8443       2.name               14       2016-04-10 08:14:15   0         -
+
+If you forgot to write down the provider fingerprint value after generating the provider keys, you can use :func:`printDNSCryptProviderFingerprint` to retrieve it later::
+
+  > printDNSCryptProviderFingerprint("/path/to/providerPublic.key")
+  Provider fingerprint is: E1D7:2108:9A59:BF8D:F101:16FA:ED5E:EA6A:9F6C:C78F:7F91:AF6B:027E:62F4:69C3:B1A
diff --git a/pdns/dnsdistdist/docs/guides/downstreams.rst b/pdns/dnsdistdist/docs/guides/downstreams.rst
new file mode 100644 (file)
index 0000000..4a69a69
--- /dev/null
@@ -0,0 +1,38 @@
+Configuring Downstream Servers
+==============================
+
+As dnsdist is a loadbalancer and does not do any DNS resolving or serving by itself, it needs downstream servers.
+To add downstream servers, either include them on the command line::
+
+    dnsdist -l 130.161.252.29 -a 130.161.0.0/16 8.8.8.8 208.67.222.222 2620:0:ccc::2 2620:0:ccd::2
+
+Or add them to the configuration file:
+
+.. code-block:: lua
+
+    setLocal("130.161.252.29:53")
+    setACL("130.161.0.0/16")
+    newServer("8.8.8.8")
+    newServer("208.67.222.222")
+    newServer("2620:0:ccc::2")
+    newServer("2620:0:0ccd::2")
+
+These two equivalent configurations give you sane load balancing using a very sensible distribution policy.
+Many users will simply be done with this configuration.
+It works as well for authoritative as for recursive servers.
+
+Healthcheck
+-----------
+dnsdist uses a health check, sent once every second, to determine the availability of a backend server.
+
+By default, an A query for "a.root-servers.net." is sent.
+A different query type and target can be specified by passing, respectively, the ``checkType`` and ``checkName`` parameters to :func:`newServer`.
+
+The default behavior is to consider any valid response with an RCODE different from ServFail as valid.
+If the ``mustResolve`` parameter of :func:`newServer` is set to ``true``, a response will only be considered valid if its RCODE differs from NXDomain, ServFail and Refused.
+
+The number of health check failures before a server is considered down is configurable via the ``maxCheckFailures`` parameter, defaulting to 1.
+The CD flag can be set on the query by setting ``setCD`` to true.
+e.g.::
+
+  newServer({address="192.0.2.1", checkType="AAAA", checkName="a.root-servers.net.", mustResolve=true})
diff --git a/pdns/dnsdistdist/docs/guides/dynblocks.rst b/pdns/dnsdistdist/docs/guides/dynblocks.rst
new file mode 100644 (file)
index 0000000..666f236
--- /dev/null
@@ -0,0 +1,24 @@
+Dynamic Rule Generation
+=======================
+
+To set dynamic rules, based on recent traffic, define a function called :func:`maintenance` in Lua.
+It will get called every second, and from this function you can set rules to block traffic based on statistics.
+More exactly, the thread handling the :func:`maintenance` function will sleep for one second between each invocation, so if the function takes several seconds to complete it will not be invoked exactly every second.
+
+As an example::
+
+  function maintenance()
+      addDynBlocks(exceedQRate(20, 10), "Exceeded query rate", 60)
+  end
+
+This will dynamically block all hosts that exceeded 20 queries/s as measured over the past 10 seconds, and the dynamic block will last for 60 seconds.
+
+Dynamic blocks in force are displayed with :func:`showDynBlocks` and can be cleared with :func:`clearDynBlocks`.
+They return a table whose key is a :class:`ComboAddress` object, representing the client's source address, and whose value is an integer representing the number of queries matching the corresponding condition (for example the qtype for :func:`exceedQTypeRate`, rcode for :func:`exceedServFails`).
+
+All exceed-functions are documented in the :ref:`Configuration Reference <exceedfuncs>`.
+
+Dynamic blocks drop matched queries by default, but this behavior can be changed with :func:`setDynBlocksAction`.
+For example, to send a REFUSED code instead of droppping the query::
+
+  setDynBlocksAction(DNSAction.Refused)
diff --git a/pdns/dnsdistdist/docs/guides/index.rst b/pdns/dnsdistdist/docs/guides/index.rst
new file mode 100644 (file)
index 0000000..8654d61
--- /dev/null
@@ -0,0 +1,15 @@
+Guides
+======
+
+These chapters contain several guides and nuggets of information regarding dnsdist operation and accomplishing specific goals.
+
+.. toctree::
+   :maxdepth: 2
+
+   console
+   cache
+   webserver
+   downstreams
+   serverpools
+   serverselection
+
diff --git a/pdns/dnsdistdist/docs/guides/serverpools.rst b/pdns/dnsdistdist/docs/guides/serverpools.rst
new file mode 100644 (file)
index 0000000..c2aa4ac
--- /dev/null
@@ -0,0 +1,46 @@
+Server pools
+------------
+
+dnsdist has the concept to "server pools", any number of servers can belong to a group.
+
+Let's say we know we're getting a whole bunch of traffic for a domain used in DoS attacks, for example 'example.com'.
+We can do two things with this kind of traffic.
+Either we block it outright, like this:
+
+.. code-block:: lua
+
+  addAction("bad-domain.example.", dropAction())
+
+Or we configure a server pool dedicated to receiving the nasty stuff:
+
+.. code-block:: lua
+
+  newServer({address="192.0.2.3", pool="abuse"})         -- Add a backend server with address 192.0.2.3 and assign it to the "abuse" pool
+  addAction({'bad-domain1.example', 'bad-domain2.example.'}, PoolAction("abuse")) -- Send all queries for "bad-domain1.example." and "bad-domain2.example" to the "abuse" pool
+
+The wonderful thing about this last solution is that it can also be used for things where a domain might possibly be legit, but it is still causing load on the system and slowing down the internet for everyone.
+With such an abuse server, 'bad traffic' still gets a chance of an answer, but without impacting the rest of the world (too much).
+
+We can similarly add clients to the abuse server:
+
+.. code-block:: lua
+
+  addPoolRule({"192.168.12.0/24", "192.168.13.14"}, "abuse")
+
+To define a pool that should receive only a :term:`QPS`-limited amount of traffic, do:
+
+.. code-block:: lua
+
+  addQPSPoolRule("com.", 10000, "gtld-cluster")
+
+Traffic exceeding the :term:`QPS` limit will not match that rule, and subsequent rules will apply normally.
+
+Both :func:`addDomainBlock` and addPoolRule end up the list of Rules and Actions (for which see below).
+
+:class:`Servers <Server>` can be added to or removed from pools with the :func:`Server:addPool` and :func:`Server:rmPool` functions respectively:
+
+.. code-block:: lua
+
+  getServer(4):addPool("abuse")
+  getServer(4):rmPool("abuse")
+
diff --git a/pdns/dnsdistdist/docs/guides/serverselection.rst b/pdns/dnsdistdist/docs/guides/serverselection.rst
new file mode 100644 (file)
index 0000000..6cf14be
--- /dev/null
@@ -0,0 +1,137 @@
+Loadbalancing and Server Policies
+=================================
+
+:program:`dnsdist` selects the server (if there are multiple eligable) to send queries to based on the configured policy.
+
+Built-in Policies
+-----------------
+
+``leastOutstanding``
+~~~~~~~~~~~~~~~~~~~~
+
+The default load balancing policy is called ``leastOutstanding``, which means the server with the least queries 'in the air' is picked (and within those, the one with the lowest order, and within those, the one with the lowest latency).
+
+``firstAvailable``
+~~~~~~~~~~~~~~~~~~
+
+The ``firstAvailable`` policy, picks the first server that has not exceeded its QPS limit.
+If all servers are above their QPS limit, a server is selected based on the ``leastOutstanding`` policy.
+For now this is the only policy using the QPS limit.
+
+``wrandom``
+~~~~~~~~~~~
+
+A further policy, ``wrandom`` assigns queries randomly, but based on the weight parameter passed to :func:`newServer`.
+
+``whashed``
+~~~~~~~~~~~
+
+``whashed`` is a similar weighted policy, but assigns questions with identical hash to identical servers, allowing for better cache concentration ('sticky queries').
+
+.. function:: setWHashedPertubation(value)
+
+  Set the hash perturbation value to be used in the whashed policy instead of a random one, allowing to have consistent whashed results on different instances.
+
+``roundrobin``
+~~~~~~~~~~~~~~
+
+The last available policy is ``roundrobin``, which indiscriminately sends each query to the next server that is up.
+
+Lua server policies
+-------------------
+
+If you don't like the default policies you can create your own, like this for example::
+
+  counter=0
+  function luaroundrobin(servers, dq)
+       counter=counter+1
+       return servers[1+(counter % #servers)]
+  end
+
+  setServerPolicyLua("luaroundrobin", luaroundrobin)
+
+Incidentally, this is similar to setting: ``setServerPolicy(roundrobin)`` which uses the C++ based roundrobin policy.
+
+Or::
+
+  newServer("192.168.1.2")
+  newServer({address="8.8.4.4", pool="numbered"})
+
+  function splitSetup(servers, dq)
+    if(string.match(dq.qname:toString(), "%d"))
+    then
+      print("numbered pool")
+      return leastOutstanding.policy(getPoolServers("numbered"), dq)
+    else
+      print("standard pool")
+      return leastOutstanding.policy(servers, dq)
+    end
+  end
+
+  setServerPolicyLua("splitsetup", splitSetup)
+
+ServerPolicy Objects
+--------------------
+
+.. class:: ServerPolicy
+
+  This represents a server policy.
+  The built-in policies are of this type
+
+.. function:: ServerPolicy.policy(servers, dq) -> Server
+
+  Run the policy to receive the server it has selected.
+
+  :param servers: A list of :class:`Server` objects
+  :param DNSQuestion dq: The incoming query
+
+Functions
+---------
+
+.. function:: newServerPolicy(name, function) -> ServerPolicy
+
+  Create a policy object from a Lua function.
+  ``function`` must match the prototype for :func:`ServerPolicy.policy`.
+
+  :param string name: Name of the policy
+  :param string function: The function to call for this policy
+
+.. function:: setServerPolicy(policy)
+
+  Set server selection policy to ``policy``.
+
+  :param ServerPolicy policy: The policy to use
+
+.. function:: setServerPolicyLua(name, function)
+
+  Set server selection policy to one named `name`` and provided by ``function``.
+
+  :param string name: name for this policy
+  :param string function: name of the function
+
+.. function:: setServFailWhenNoServer(value)
+
+  If set, return a ServFail when no servers are available, instead of the default behaviour of dropping the query.
+
+  :param bool value:
+
+.. function:: setPoolServerPolicy(policy, pool)
+
+  Set the server selection policy for ``pool`` to ``policy``.
+
+  :param ServerPolicy policy: The policy to apply
+  :param string pool: Name of the pool
+
+.. function:: setPoolServerPolicyLua(name, function, pool)
+
+  Set the server selection policy for ``pool`` to one named ``name`` and provided by ``function``.
+
+  :param string name: name for this policy
+  :param string function: name of the function
+  :param string pool: Name of the pool
+
+.. function:: showPoolServerPolicy(pool)
+
+  Print server selection policy for ``pool``.
+
+  :param string pool: The pool to print the policy for
diff --git a/pdns/dnsdistdist/docs/guides/webserver.rst b/pdns/dnsdistdist/docs/guides/webserver.rst
new file mode 100644 (file)
index 0000000..0b57abf
--- /dev/null
@@ -0,0 +1,206 @@
+Built-in webserver
+==================
+
+To visually interact with dnsdist, try add :func:`webserver` to the configuration:
+
+.. code-block:: lua
+
+  webserver("127.0.0.1:8083", "supersecretpassword", "supersecretAPIkey")
+
+Now point your browser at http://127.0.0.1:8083 and log in with any username, and that password. Enjoy!
+
+Security of the Webserver
+-------------------------
+
+The built-in webserver serves its content from inside the binary, this means it will not and connot read from disk.
+
+By default, our web server sends some security-related headers::
+
+   X-Content-Type-Options: nosniff
+   X-Frame-Options: deny
+   X-Permitted-Cross-Domain-Policies: none
+   X-XSS-Protection: 1; mode=block
+   Content-Security-Policy: default-src 'self'; style-src 'self' 'unsafe-inline'
+
+You can override those headers, or add custom headers by using the last parameter to :func:`webserver`.
+For example, to remove the X-Frame-Options header and add a X-Custom one:
+
+.. code-block:: lua
+
+  webserver("127.0.0.1:8080", "supersecret", "apikey", {["X-Frame-Options"]= "", ["X-Custom"]="custom"}
+
+dnsdist API
+-----------
+
+To access the API, the `apikey` must be set in the :func:`webserver` function.
+Use the API, this key will need to be sent to dnsdist in the ``X-API-Key`` request header.
+An HTTP 401 response is returned when a wrong or no API key is received.
+A 404 response is generated is the requested endpoint does not exist.
+And a 405 response is returned when the HTTP methos is not allowed.
+
+URL Endpoints
+~~~~~~~~~~~~~
+
+.. http:get:: /jsonstat
+
+  Get statistics from dnsdist in JSON format.
+  The ``Accept`` request header is ignored.
+  This endpoint accepts a ``command`` query for different statistics:
+
+  * ``stats``: Get all :doc:`../statistics` as a JSON dict
+  * ``dynblocklist``: Get all current :doc:`dynamic blocks <dynblocks>`, keyed by netmask
+  * ``ebpfblocklist``: Idem, but for :doc:`eBPF <../advanced/ebpf>` blocks
+
+  **Example request**:
+
+   .. sourcecode:: http
+
+      GET /jsonstat?command=stats HTTP/1.1
+      Host: example.com
+      Accept: application/json, text/javascript
+
+  **Example response**:
+   .. sourcecode:: http
+
+      HTTP/1.1 200 OK
+      Transfer-Encoding: chunked
+      Content-Security-Policy: default-src 'self'; style-src 'self' 'unsafe-inline'
+      Content-Type: application/json
+      X-Content-Type-Options: nosniff
+      X-Frame-Options: deny
+      X-Permitted-Cross-Domain-Policies: none
+      X-Xss-Protection: 1; mode=block
+
+      {"acl-drops": 0, "block-filter": 0, "cache-hits": 0, "cache-misses": 0, "cpu-sys-msec": 633, "cpu-user-msec": 499, "downstream-send-errors": 0, "downstream-timeouts": 0, "dyn-block-nmg-size": 1, "dyn-blocked": 3, "empty-queries": 0, "fd-usage": 17, "latency-avg100": 7651.3982737482893, "latency-avg1000": 860.05142763680249, "latency-avg10000": 87.032142373878372, "latency-avg1000000": 0.87146026426551759, "latency-slow": 0, "latency0-1": 0, "latency1-10": 0, "latency10-50": 22, "latency100-1000": 1, "latency50-100": 0, "no-policy": 0, "noncompliant-queries": 0, "noncompliant-responses": 0, "over-capacity-drops": 0, "packetcache-hits": 0, "packetcache-misses": 0, "queries": 26, "rdqueries": 26, "real-memory-usage": 6078464, "responses": 23, "rule-drop": 0, "rule-nxdomain": 0, "rule-refused": 0, "self-answered": 0, "server-policy": "leastOutstanding", "servfail-responses": 0, "too-old-drops": 0, "trunc-failures": 0, "uptime": 412}
+
+  **Example request**:
+
+   .. sourcecode:: http
+
+      GET /jsonstat?command=dynblocklist HTTP/1.1
+      Host: example.com
+      Accept: application/json, text/javascript
+
+  **Example response**:
+   .. sourcecode:: http
+
+      HTTP/1.1 200 OK
+      Transfer-Encoding: chunked
+      Content-Security-Policy: default-src 'self'; style-src 'self' 'unsafe-inline'
+      Content-Type: application/json
+      X-Content-Type-Options: nosniff
+      X-Frame-Options: deny
+      X-Permitted-Cross-Domain-Policies: none
+      X-Xss-Protection: 1; mode=block
+
+      {"127.0.0.1/32": {"blocks": 3, "reason": "Exceeded query rate", "seconds": 10}}
+
+  :query command: one of ``stats``, ``dynblocklist`` or ``ebpfblocklist``
+
+.. http:get:: /api/v1/servers/localhost
+
+  Get a quick overview of several parameters.
+
+  :>json string acl: A string of comma-separated netmasks currently allowed by the :ref:`ACL <ACL>`.
+  :>json string daemon_type: The type of daemon, always "dnsdist"
+  :>json list frontends: A list of :json:object:`Frontend` objects
+  :>json list response-rules: A list of :json:object:`ResponseRule` objects
+  :>json list rules: A list of :json:object:`Rule` objects
+  :>json list servers: A list of :json:object:`Server` objects
+  :>json string version: The running version of dnsdist
+
+.. http:get:: /api/v1/servers/localhost/statistics
+
+  Returns a list of all statistics as :json:object:`StatisticItem`.
+
+.. http:get:: /api/v1/servers/localhost/config
+
+  Returns a list of :json:object:`ConfigSetting` objects.
+
+.. http:get:: /api/v1/servers/localhost/config/allow-from
+
+  Gets you the ``allow-from`` :json:object:`ConfigSetting`, who's value is a list of strings of all the netmasks in the :ref:`ACL <ACL>`.
+
+.. http:put:: /api/v1/servers/localhost/config/allow-from
+
+  Allows you to add to the ACL. TODO **how**
+
+JSON Objects
+~~~~~~~~~~~~
+
+.. json:object:: ConfigSetting
+
+  An object representing a global configuration element.
+  The following configuration are returned:
+
+  - ``acl`` The currently configured :ref:`ACLs <ACL>`
+  - ``control-socket`` The currently configured :ref:`console address <Console>`
+  - ``ecs-override``
+  - ``ecs-source-prefix-v4`` The currently configured :func:`setECSSourcePrefixV4`
+  - ``ecs-source-prefix-v6`` The currently configured :func:`setECSSourcePrefixV6`
+  - ``fixup-case``
+  - ``max-outstanding``
+  - ``server-policy`` The currently set :doc:`serverselection`
+  - ``stale-cache-entries-ttl``
+  - ``tcp-recv-timeout``
+  - ``tcp-send-timeout``
+  - ``truncate-tc``
+  - ``verbose``
+  - ``verbose-health-checks``
+
+  :property string name: The name of the setting
+  :property string type: "ConfigSetting"
+  :property string value: The value for this setting
+
+.. json:object:: Frontend
+
+  A description of a bind dnsdist is listening on.
+
+  :property string address: IP and port that is listened on
+  :property integer id: Internal identifier
+  :property integer queries: The number of received queries on this bind
+  :property boolean udp: true if this is a UDP bind
+  :property boolean tcp: true if this is a TCP bind
+
+.. json:object:: Rule
+
+  This represents a policy that is applied to queries
+
+  :property string action: The action taken when the rule matches (e.g. "to pool abuse")
+  :property dict action-stats: TODO
+  :property integer id: The identifier (or order) of this rule
+  :property integer matches: How many times this rule was hit
+  :property string rule: The matchers for the packet (e.g. "qname==bad-domain1.example., bad-domain2.example.")
+
+.. json:object:: ResponseRule
+
+  This represents a policy that is applied to responses
+
+  TODO
+
+.. json:object:: Server
+
+  This object represents a backend server.
+
+  :property string address: The remote IP and port
+  :property integer id: Internal identifier
+  :property integer latency: The current latency of this backend server
+  :property string name: The name of this server
+  :property integer order: Order number
+  :property integer outstanding: Number of currently outstanding queries
+  :property [string] pools: The pools this server belongs to
+  :property integer qps: The current number of queries per second to this server
+  :property integer qpsLimit: The configured maximum number of queries per second
+  :property integer queries: Total number of queries sent to this backend
+  :property integer reuseds: TODO
+  :property string state: The state of the server (e.g. "DOWN" or "up")
+  :property integer weight: The weight assigned to this server
+
+.. json:object:: StatisticItem
+
+  This represents a statistics element.
+
+  :property string name: The name of this statistic. See :doc:`../statistics`
+  :property string type: "StatisticItem"
+  :property integer value: The value for this item
+
diff --git a/pdns/dnsdistdist/docs/index.rst b/pdns/dnsdistdist/docs/index.rst
new file mode 100644 (file)
index 0000000..8ad7e08
--- /dev/null
@@ -0,0 +1,42 @@
+dnsdist Overview
+================
+
+dnsdist is a highly DNS-, DoS- and abuse-aware loadbalancer.
+Its goal in life is to route traffic to the best server, delivering top performance to legitimate users while shunting or blocking abusive traffic.
+
+dnsdist is dynamic, its configuration language is `Lua <http://lualang.org>`_ and it can be can be changed at runtime, and its statistics can be queried from a console-like interface or an HTTP API.
+
+A configuration to balance DNS queries to several backend servers:
+
+.. code-block:: lua
+
+   newServer({address="2001:4860:4860::8888", qps=1})
+   newServer({address="2001:4860:4860::8844", qps=1})
+   newServer({address="2620:0:ccc::2", qps=10})
+   newServer({address="2620:0:ccd::2", name="dns1", qps=10})
+   newServer("192.168.1.2")
+   setServerPolicy(firstAvailable) -- first server within its QPS limit
+
+Running dnsdist
+---------------
+
+If you have not worked with dnsdist before, here are some resources to get you going:
+
+* :doc:`Install dnsdist <install>`.
+* To get a feeling for how it works, see the :doc:`Quickstart Guide <quickstart>`.
+* :doc:`running`
+* The :doc:`rules-actions` page covers how to apply policies to traffic
+* There are several :doc:`guides/index` about the different features and options
+* :doc:`advanced/index` describes some of the more advanced features
+* :doc:`reference/index` has all the configuration and object information
+
+Questions, requests or comments?
+--------------------------------
+
+There are several ways to reach us:
+
+* The `dnsdist mailing-list <https://mailman.powerdns.com/mailman/listinfo/dnsdist>`_
+* #powerdns on `irc.oftc.net <irc://irc.oftc.net/#powerdns>`_
+
+If you require commercial support, please see the `PowerDNS.com website <https://powerdns.com>`_ or email us at powerdns.support.sales@powerdns.com.
+
diff --git a/pdns/dnsdistdist/docs/index_TOC.rst b/pdns/dnsdistdist/docs/index_TOC.rst
new file mode 100644 (file)
index 0000000..3adb836
--- /dev/null
@@ -0,0 +1,20 @@
+Table of Contents
+=================
+
+.. toctree::
+   :maxdepth: 3
+   :glob:
+
+   index
+   install
+   quickstart
+   running
+   rules-actions
+   statistics
+   guides/*
+   advanced/index
+   reference/index
+   manpages/*
+   changelog
+   upgrade_guide
+   glossary
diff --git a/pdns/dnsdistdist/docs/install.rst b/pdns/dnsdistdist/docs/install.rst
new file mode 100644 (file)
index 0000000..d81ae48
--- /dev/null
@@ -0,0 +1,91 @@
+Installing dnsdist
+==================
+
+dnsdist only runs on UNIX-like systems and there are several ways to install dnsdist.
+The fastest way is using packages, either from your own operating system vendor or suppied by the PowerDNS project.
+Building from source is also supported.
+
+
+Installing from Packages
+------------------------
+
+If dnsdist is available in your operating system's software repositories, install it from there.
+However, the version of dnsdist in the repositories might be an older version that might not have a feature that was added in a later version.
+Or you might want to be brave and try a development snapshot from the master branch.
+PowerDNS provides software respositories for the most popular distributions.
+Visit https://repo.powerdns.com for more information and installation instructions.
+
+Debian
+~~~~~~
+
+For Debian and its derivatives (like Ubuntu) installing the ``dnsdist`` package should do it:
+
+.. code-block:: sh
+
+  apt-get install -y dnsdist
+
+RedHat
+~~~~~~
+
+For RedHat, CentOS and its derivatives, dnsdist is available in `EPEL <https://fedoraproject.org/wiki/EPEL>`_:
+
+.. code-block:: sh
+
+  yum install -y epel-release
+  yum install -y dnsdist
+
+FreeBSD
+~~~~~~~
+
+dnsdist is also available in `FreeBSD ports <http://www.freshports.org/dns/dnsdist/>`_.
+
+Installing from Source
+----------------------
+
+In order to compile dnsdist, a modern compiler with C++ 2011 support (like GCC 4.8+ or clang 3.5+) and GNU make are required.
+dnsdist depends on the following libraries:
+
+* `Boost <http://boost.org/>`_
+* `Lua <http://www.lua.org/>`_ 5.1+ or `LuaJit <http://luajit.org/>`_
+* `Editline (libedit) <http://thrysoee.dk/editline/>`_
+* `libsodium <https://download.libsodium.org/doc/>`_ (optional)
+* `protobuf <https://developers.google.com/protocol-buffers/>`_ (optional)
+* `re2 <https://github.com/google/re2>`_ (optional)
+
+Should :program:`dnsdist` be run on a system with systemd, it is highly recommended to have
+the systemd header files (``libsystemd-dev`` on Debian and ``systemd-devel`` on CentOS)
+installed to have :program:`dnsdist` support ``systemd-notify``.
+
+From tarball
+~~~~~~~~~~~~
+
+Release tarballs are available `from the downloads site <https://downloads.powerdns.com/releases>`_ and snapshot and pre-release tarballs `can be found as well <https://downloads.powerdns.com/autobuilt/dnsdist/dist/>`_.
+
+* Untar the tarball and ``cd`` into the source directory
+* Run ``./configure``
+* Run ``make`` or ``gmake`` (on BSD)
+
+From git
+~~~~~~~~
+
+To compile from git, these additional dependencies are required:
+
+* GNU `Autoconf <http://www.gnu.org/software/autoconf/autoconf.html>`_
+* GNU `Automake <https://www.gnu.org/software/automake/>`_
+* `Pandoc <http://pandoc.org/>`_
+* `Ragel <http://www.colm.net/open-source/ragel/>`_
+
+dnsdist sourcecode lives in the `PowerDNS git repository <https://github.com/PowerDNS/pdns>`_ but is independent of PowerDNS.
+
+::
+
+  git clone https://github.com/PowerDNS/pdns.git
+  cd pdns/pdns/dnsdistdist
+  autoreconf -i
+  ./configure
+  make
+
+OS Specific Instructions
+~~~~~~~~~~~~~~~~~~~~~~~~
+
+
diff --git a/pdns/dnsdistdist/docs/manpages/dnsdist.1.rst b/pdns/dnsdistdist/docs/manpages/dnsdist.1.rst
new file mode 100644 (file)
index 0000000..7ac1297
--- /dev/null
@@ -0,0 +1,94 @@
+dnsdist manual page
+===================
+
+**dnsdist** - tool to balance DNS queries over downstream servers
+
+Synopsis
+--------
+
+dnsdist [<option>...] [address]...
+
+Description
+-----------
+
+:program:`dnsdist` receives DNS queries and relays them to one or more
+downstream servers. It subsequently sends back responses to the original
+requestor.
+
+:program:`dnsdist` operates over TCP and UDP, and strives to deliver very high
+performance over both.
+
+Currently, queries are sent to the downstream server with the least
+outstanding queries. This effectively implies load balancing, making
+sure that slower servers get less queries.
+
+If a reply has not come in after a few seconds, it is removed from the
+queue, but in the short term, timeouts do cause a server to get less
+traffic.
+
+IPv4 and IPv6 operation can be mixed and matched, in other words,
+queries coming in over IPv6 could be forwarded to IPv4 and vice versa.
+
+:program:`dnsdist` is scriptable in Lua, see the dnsdist documentation for more
+information on this.
+
+Scope
+-----
+
+:program:`dnsdist` does not 'think' about DNS queries, it restricts itself to
+measuring response times and error codes and routing questions
+accordingly. It comes with a very high performance packet-cache.
+
+The goal for dnsdist is to remain simple. If more powerful loadbalancing
+is required, dedicated hardware or software is recommended. Linux
+Virtual Server for example is often mentioned.
+
+Options
+-------
+
+-a <netmask>, --acl <netmask>          Add *netmask* to the ACL.
+-C <file>, --config <file>             Load configuration from *file*.
+--check-config                         Test the configuration file (which may be set with **--config** or **-C**)
+                                       for errors. dnsdist will show the errors and exit with a non-zero
+                                       exit-code when errors are found.
+-c <address>, --client <address>       Operate as a client, connect to dnsdist. This will read the dnsdist
+                                       configuration for the **controlSocket** statement and connect to it.
+                                       When *address* (with an optional port number) is set, dnsdist will connect
+                                       to that instead.
+-k <key>, --setkey <key>               When operating as a client(**-c**, **--client**), use *key* as
+                                       shared secret to connect to dnsdist. This should be the same key
+                                       that is used on the server (set with **setKey()**). Note that this
+                                       will leak the key into your shell's history. Only available when
+                                       dnsdist is compiled with libsodium support.
+-d, --daemon                           Operate as a daemon.
+-e, --execute <command>                Connect to dnsdist and execute *command*.
+-h, --help                             Display a helpful message and exit.
+-l, --local <address>                  Bind to *address*, Supply as many addresses (using multiple
+                                       **--local** statements) to listen on as required. Specify IPv4 as
+                                       0.0.0.0:53 and IPv6 as [::]:53.
+--supervised                           Run in foreground, but do not spawn a console. Use this switch to
+                                       run dnsdist inside a supervisor (use with e.g. systemd and
+                                       daemontools).
+--disable-syslog                       Disable logging to syslog. Use this when running inside a supervisor
+                                       that handles logging (like systemd). Do not use in combination with
+                                       **--daemon**.
+-p, --pidfile <file>                   Write a pidfile to *file*, works only with **--daemon**.
+-u, --uid <uid>                        Change the process user to *uid* after binding sockets. *uid* can be
+                                       a name or number.
+-g, --gid <gid>                        Change the process group to *gid* after binding sockets. *gid* Can
+                                       be a name or number.
+-V, --version                          Show the dnsdist version and exit.
+-v, --verbose                          Be verbose.
+
+**address** are any number of downstream DNS servers, in the same syntax as used
+with **--local**. If the port is not specified, 53 is used.
+
+Bugs
+----
+
+Right now, the TCP support has some rather arbitrary limits.
+
+Resources
+---------
+
+Website: http://dnsdist.org
diff --git a/pdns/dnsdistdist/docs/quickstart.rst b/pdns/dnsdistdist/docs/quickstart.rst
new file mode 100644 (file)
index 0000000..7926318
--- /dev/null
@@ -0,0 +1,126 @@
+Quickstart Guide
+================
+
+This guide gives an overview of dnsdist features and operations.
+
+Running in the Foreground
+-------------------------
+
+After :doc:`installing <install>` dnsdist, the quickest way to start experimenting is lanching it on the foreground with::
+
+   dnsdist -l 127.0.0.1:5300 8.8.8.8 2001:4860:4860::8888
+
+This will make dnsdist listen on IP address 127.0.0.1, port 5300 and forward all queries to the two listed IP addresses, with a sensible balancing policy.
+
+``dnsdist`` Console and Configuration
+-------------------------------------
+
+Here is more complete configuration, save it to ``dnsdist.conf``::
+
+  newServer({address="2001:4860:4860::8888", qps=1})
+  newServer({address="2001:4860:4860::8844", qps=1})
+  newServer({address="2620:0:ccc::2", qps=10})
+  newServer({address="2620:0:ccd::2", name="dns1", qps=10})
+  newServer("192.168.1.2")
+  setServerPolicy(firstAvailable) -- first server within its QPS limit
+
+The :func:`newServer` function is used to add a backend server to the configuration.
+
+Now run dnsdist again, reading this configuration::
+
+  $ dnsdist -C dnsdist.conf --local=0.0.0.0:5300
+  Marking downstream [2001:4860:4860::8888]:53 as 'up'
+  Marking downstream [2001:4860:4860::8844]:53 as 'up'
+  Marking downstream [2620:0:ccc::2]:53 as 'up'
+  Marking downstream [2620:0:ccd::2]:53 as 'up'
+  Marking downstream 192.168.1.2:53 as 'up'
+  Listening on 0.0.0.0:5300
+  >
+
+You can now send queries to port 5300, and get answers::
+
+  $ dig -t aaaa powerdns.com @127.0.0.1 -p 5300 +short
+  2001:888:2000:1d::2
+
+Note that dnsdist dropped us in a prompt above, where we can get some statistics::
+
+  > showServers()
+  #   Address                   State     Qps    Qlim Ord Wt    Queries   Drops Drate   Lat Pools
+  0   [2001:4860:4860::8888]:53    up     0.0       1   1  1          1       0   0.0   0.0
+  1   [2001:4860:4860::8844]:53    up     0.0       1   1  1          0       0   0.0   0.0
+  2   [2620:0:ccc::2]:53           up     0.0      10   1  1          0       0   0.0   0.0
+  3   [2620:0:ccd::2]:53           up     0.0      10   1  1          0       0   0.0   0.0
+  4   192.168.1.2:53               up     0.0       0   1  1          0       0   0.0   0.0
+  All                                     0.0                         1       0
+
+:func:`showServers()` is usually one of the first commands you will use when logging into the console. More advanced topics are covered in :doc:`guides/console`.
+
+Here we also see our configuration. 5 downstream servers have been configured, of which the first 4 have a QPS limit (of 1, 1, 10 and 10 queries per second, respectively).
+
+The final server has no limit, which we can easily test::
+
+  $ for a in {0..1000}; do dig powerdns.com @127.0.0.1 -p 5300 +noall > /dev/null; done
+
+::
+
+  > showServers()
+  #   Address                   State     Qps    Qlim Ord Wt    Queries   Drops Drate   Lat Pools
+  0   [2001:4860:4860::8888]:53    up     1.0       1   1  1          7       0   0.0   1.6
+  1   [2001:4860:4860::8844]:53    up     1.0       1   1  1          6       0   0.0   0.6
+  2   [2620:0:ccc::2]:53           up    10.3      10   1  1         64       0   0.0   2.4
+  3   [2620:0:ccd::2]:53           up    10.3      10   1  1         63       0   0.0   2.4
+  4   192.168.1.2:53               up   125.8       0   1  1        671       0   0.0   0.4
+  All                                   145.0                       811       0
+
+Note that the first 4 servers were all limited to near their configured QPS, and that our final server was taking up most of the traffic.
+No queries were dropped, and all servers remain up.
+
+Changing Server Settings
+~~~~~~~~~~~~~~~~~~~~~~~~
+
+The servers from :func:`showServers` are numbered, :func:`getServer` is used to get this :class:`Server` object to manipulate it.
+
+To force a server down, try :attr:`Server:setDown()`::
+
+  > getServer(0):setDown()
+  > showServers()
+  #   Address                   State     Qps    Qlim Ord Wt    Queries   Drops Drate   Lat Pools
+  0   [2001:4860:4860::8888]:53  DOWN     0.0       1   1  1          8       0   0.0   0.0
+  ...
+
+The ``DOWN`` in all caps means it was forced down.
+A lower case ``down`` would've meant that dnsdist itself had concluded the server was down.
+Similarly, :meth:`Server:setUp()` forces a server to be up, and :meth:`Server:setAuto` returns it to the default availability-probing.
+
+To change the QPS for a server, use :meth:`Server:setQPS`::
+
+  > getServer(0):setQPS(1000)
+
+Restricting Access
+------------------
+
+By default, dnsdist listens on ``127.0.0.1`` (not ``::1``!), port 53.
+
+To listen on a different address, use the ``-l`` command line option (useful for testing in the foreground), or use :func:`setLocal` and :func:`addLocal` in the configuration file:
+
+.. code-block:: lua
+
+  setLocal('192.0.2.53')      -- Listen on 192.0.2.53, port 53
+  addLocal('192.0.2.54:5300') -- Also listen on 192.0.2.54, port 5300
+
+Before packets are processed they have to pass the ACL, which helpfully defaults to :rfc:`1918` private IP space.
+This prevents us from easily becoming an open DNS resolver.
+
+Adding network ranges to the :term:`ACL` is done with the :func:`setACL` and :func:`addACL` functions:
+
+.. code-block:: lua
+
+  setACL({'192.0.2.0/28', '2001:DB8:1::/56'}) -- Set the ACL to only allow these subnets
+  addACL('2001:DB8:2::/56')                   -- Add this subnet to the existing ACL
+
+More Information
+----------------
+
+Following this quickstart guide allowed you to set up a basic balancing dnsdist instance.
+However, dnsdist is much more powerful.
+See the :doc:`guides/index` and/or the :doc:`advanced/index` sections on how to shape, shut and otherwise manipulate DNS traffic.
diff --git a/pdns/dnsdistdist/docs/reference/comboaddress.rst b/pdns/dnsdistdist/docs/reference/comboaddress.rst
new file mode 100644 (file)
index 0000000..6837db8
--- /dev/null
@@ -0,0 +1,55 @@
+.. _ComboAddress:
+
+ComboAddress
+============
+
+.. class:: ComboAddress
+
+  A ``ComboAddress`` represents an IP address with possibly a port number.
+  The object can be an IPv4 or an IPv6 address.
+
+Functions and methods related to ``ComboAddress``
+
+.. function:: newCA(address) -> :class:`ComboAddress`
+
+  Returns a :class:`ComboAddress` based on ``address``
+
+  :param string address: The IP address, with optional port, to represent.
+
+.. classmethod:: ComboAddress:getPort() -> int
+
+  Returns the port number.
+
+.. classmethod:: ComboAddress:isIPv4() -> bool
+
+  Returns true if the address is an IPv4, false otherwise
+
+.. classmethod:: ComboAddress:isIPv6() -> bool
+
+  Returns true if the address is an IPv6, false otherwise
+
+.. classmethod:: ComboAddress:isMappedIPv4() -> bool
+
+  Returns true if the address is an IPv4 mapped into an IPv6, false otherwise
+
+.. classmethod:: ComboAddress:mapToIPv4() -> ComboAddress
+
+  Convert an IPv4 address mapped in a v6 one into an IPv4.
+  Returns a new ComboAddress
+
+.. classmethod:: ComboAddress:tostring() -> string
+                 ComboAddress:toString() -> string
+
+  Returns in human-friendly format
+
+.. classmethod:: ComboAddress:tostringWithPort() -> string
+                 ComboAddress:toStringWithPort() -> string
+
+  Returns in human-friendly format, with port number
+
+.. classmethod:: ComboAddress:truncate(bits)
+
+  Truncate the ComboAddress to the specified number of bits.
+  This essentially zeroes all bits after ``bits``.
+
+  :param int bits: Amount of bits to truncate to
diff --git a/pdns/dnsdistdist/docs/reference/config.rst b/pdns/dnsdistdist/docs/reference/config.rst
new file mode 100644 (file)
index 0000000..07e0ee7
--- /dev/null
@@ -0,0 +1,606 @@
+.. highlight:: lua
+
+Configuration Reference
+=======================
+
+This page lists all configuration options for dnsdist.
+
+.. note::
+
+  When an IPv6 IP:PORT combination is needed, the bracketed syntax from :rfc:`RFC 3986 <3986#section-3.2.2>` should be used.
+  e.g. "[2001:DB8:14::C0FF:FEE]:5300".
+
+Functions and Types
+-------------------
+
+Within dnsdist several core object types exist:
+
+* :class:`Server`: generated with :func:`newServer`, represents a downstream server
+* :class:`ComboAddress`: represents an IP address and port
+* :class:`DNSName`: represents a domain name
+* :class:`NetmaskGroup`: represents a group of netmasks
+* :class:`QPSLimiter`: implements a QPS-based filter
+* :class:`SuffixMatchNode`: represents a group of domain suffixes for rapid testing of membership
+* :class:`DNSHeader`: represents the header of a DNS packet
+
+The existence of most of these objects can mostly be ignored, unless you plan to write your own hooks and policies, but it helps to understand an expressions like:
+
+.. code-block:: lua
+
+  getServer(0).order=12         -- set order of server 0 to 12
+  getServer(0):addPool("abuse") -- add this server to the abuse pool
+
+The ``.`` means ``order`` is a data member, while the ``:`` means ``addPool`` is a member function.
+
+Global configuration
+--------------------
+
+.. function:: includeDirectory(path)
+
+  Include configuration files from ``path``.
+
+  :param str path: The directory to load the configuration from
+
+Listen Sockets
+~~~~~~~~~~~~~~
+
+.. function:: addLocal(address[, options])
+
+  .. versionadded:: 1.2.0
+
+  Add to the list of listen addresses.
+
+  :param str address: The IP Address with an optional port to listen on.
+                      The default port is 53.
+  :param table options: A table with key: value pairs with listen options.
+
+  Options:
+
+  * ``doTCP=true``: bool - Also bind on TCP on ``address``.
+  * ``reusePort=false``: bool - Set the ``SO_REUSEPORT`` socket option.
+  * ``tcpFastOpenSize=0``: int - Set the TCP Fast Open queue size, enabling TCP Fast Open when available and the value is larger than 0
+  * ``interface=""``: str - Sets the network interface to use
+
+  .. code-block:: lua
+
+    addLocal('0.0.0.0:5300', { doTCP=true, reusePort=true })
+
+  This will bind to both UDP and TCP on port 5300 with SO_REUSEPORT enabled.
+
+.. function:: addLocal(address[[[,do_tcp], so_reuseport], tcp_fast_open_qsize])
+
+  .. deprecated:: 1.2.0
+
+  Add to the list of addresses listened on.
+
+  :param str address: The IP Address with an optional port to listen on.
+                      The default port is 53.
+  :param bool do_tcp: Also bind a TCP port on ``address``, defaults to true.
+  :param bool so_reuseport: Use ``SO_REUSEPORT`` if it is available, defaults to false
+  :param int tcp_fast_open_qsize: Set to a number higher than 0 to enable TCP Fast Open
+                                  when available. Default is 0.
+
+.. function:: setLocal(address[, options])
+
+  .. versionadded:: 1.2.0
+
+  Remove the list of listen addresses and add a new one.
+
+  :param str address: The IP Address with an optional port to listen on.
+                      The default port is 53.
+  :param table options: A table with key: value pairs with listen options.
+
+  The options that can be set are the same as :func:`addLocal`.
+
+.. function:: setLocal(address[[[,do_tcp], so_reuseport], tcp_fast_open_qsize])
+
+  .. deprecated:: 1.2.0
+
+  Remove the list of listen addresses and add a new one.
+
+  :param str address: The IP Address with an optional port to listen on.
+                      The default port is 53.
+  :param bool do_tcp: Also bind a TCP port on ``address``, defaults to true.
+  :param bool so_reuseport: Use ``SO_REUSEPORT`` if it is available, defaults to false
+  :param int tcp_fast_open_qsize: Set to a number higher than 0 to enable TCP Fast Open
+                                  when available. Default is 0.
+
+Control Socket, Console and Webserver
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+.. function:: controlSocket(address)
+
+  Bind to ``addr`` and listen for a connection for the console
+
+  :param str address: An IP address with optional port. By default, the port is 5199.
+
+.. function:: makeKey()
+
+  Generate and print an encryption key.
+
+.. function:: setKey(key)
+
+  Use ``key`` as shared secret between the client and the server
+
+  :param str key: An encoded key, as generated by :func:`makeKey`
+
+.. function:: testCrypto()
+
+  Test the crypto code, will report errors when something is not ok.
+
+Webserver
+~~~~~~~~~
+
+.. function:: webServer(listen_address, password[, apikey[, custom_headers]])
+
+  Launch the :doc:`../guides/webserver` with statistics and the API.
+
+  :param str listen_address: The IP address and Port to listen on
+  :param str password: The password required to access the webserver
+  :param str apikey: The key required to access the API
+  :param {[str]=str,...} custom_headers: Allows setting custom headers and removing the defaults
+
+.. function:: setAPIWritable(allow [,dir])
+
+  Allow modifications via the API.
+  Optionally saving these changes to disk.
+  Modifications done via the API will not be written to the configuration by default and will not persist after a reload
+
+  :param bool allow: Set to true to allow modification through the API
+  :param str dir: A valid directory where the configuration files will be written by the API.
+
+Access Control Lists
+~~~~~~~~~~~~~~~~~~~~
+
+.. function:: addACL(netmask)
+
+  Add a netmask to the existing ACL
+
+  :param str netmask: A CIDR netmask, e.g. ``"192.0.2.0/24"``. Without a subnetmask, only the specific address is allowed.
+
+.. function:: setACL(netmasks)
+
+  Remove the existing ACL and add the netmasks from the table.
+
+  :param {str} netmasks: A table of CIDR netmask, e.g. ``{"192.0.2.0/24", "2001:DB8:14::/56"}``. Without a subnetmask, only the specific address is allowed.
+
+EDNS Client Subnet
+~~~~~~~~~~~~~~~~~~
+
+.. function:: setECSSourcePrefixV4(prefix)
+
+  When ``useClientSubnet`` in :func:`newServer` is set and dnsdist adds an EDNS Client Subnet Client option to the query, truncate the requestors IPv4 address to ``prefix`` bits
+
+  :param int prefix: The prefix length
+
+.. function:: setECSSourcePrefixV6(prefix)
+
+  When ``useClientSubnet`` in :func:`newServer` is set and dnsdist adds an EDNS Client Subnet Client option to the query, truncate the requestor's IPv6 address to  bits
+
+  :param int prefix: The prefix length
+
+Ringbuffers
+~~~~~~~~~~~
+
+.. function:: setRingBuffersSize(num)
+
+  Set the capacity of the ringbuffers used for live traffic inspection to ``num``
+
+  :param int num: The maximum amount of queries to keep in the ringbuffer. Defaults to 10000
+
+Servers
+-------
+
+.. function:: newServer(server_string)
+              newServer(server_table)
+
+  Add a new backend server. Call this function with either a string::
+
+    newServer(
+      "IP:PORT" -- IP and PORT of the backend server
+    )
+
+  or a table::
+
+    newServer({
+      address="IP:PORT",     -- IP and PORT of the backend server (mandatory)
+      qps=NUM,               -- Limit the number of queries per second to NUM
+      order=NUM,             -- The order of this server
+      weight=NUM,            -- The weight of this server
+      pool=STRING,           -- The pool this server belongs to (unset or empty string means default pool)
+      retries=NUM,           --
+      tcpConnectTimeout=NUM, --
+      tcpSendTimeout=NUM,    --
+      tcpRecvTimeout=NUM,    --
+      checkName=STRING,      -- Use STRING as QNAME in the health-check query, default: "a.root-servers.net."
+      checkType=STRING,      -- Use STRING as QTYPE in the health-check query, default: "A"
+      setCD=BOOL,            -- Set the CD (Checking Disabled) flag in the health-check query, default: false
+      maxCheckFailures=NUM,  -- Allow NUM check failures before declaring the backend down, default: false
+      mustResolve=BOOL,      -- Set to true when the health check MUST return a NOERROR RCODE and an answer
+      useClientSubnet=BOOL,  -- Add the client's IP address in the EDNS Client Subnet option when forwarding the query to this backend
+      source=STRING          -- The source address or interface to use for queries to this backend, by default this is left to the kernel's address selection
+                             -- The following formats are supported:
+                             --   "address", e.g. "192.0.2.2"
+                             --   "interface name", e.g. "eth0"
+                             --   "address@interface", e.g. "192.0.2.2@eth0"
+    })
+
+  :param str server_string: A simple IP:PORT string.
+  :param table server_table: A table with at least a 'name' key
+
+.. function:: getServer(index) -> Server
+
+  Get a :class:`Server`
+
+  :param int index: The number of the server (as seen in :func:`showServers`).
+  :returns:  The :class:`Server` object or nil
+
+.. function:: getServers()
+
+  Returns a table with all defined servers.
+
+.. function:: rmServer(index)
+              rmServer(server)
+
+  Remove a backend server.
+
+  :param int index: The number of the server (as seen in :func:`showServers`).
+  :param Server server: A :class:`Server` object as returned by e.g. :func:`getServer`.
+
+Server Functions
+~~~~~~~~~~~~~~~~
+A server object returned by :func:`getServer` can be manipulated with these functions.
+
+.. class:: Server
+
+  This object represents a backend server. It has several methods.
+
+.. classmethod:: Server:addPool(pool)
+
+  Add this server to a pool.
+
+  :param str pool: The pool to add the server to
+
+.. classmethod:: Server:getName() -> string
+
+  Get the name of this server.
+
+  :returns: The name of the server, or an empty string if it does not have one
+
+.. classmethod:: Server:getNameWithAddr() -> string
+
+  Get the name plus IP address and port of the server
+
+  :returns: A string containing the server name if any plus the server address and port
+
+.. classmethod:: Server:getOutstanding() -> int
+
+  Get the number of outstanding queries for this server.
+
+  :returns: The number of outstanding queries
+
+.. classmethod:: Server:isUp() -> bool
+
+  Returns the up status of the server
+
+  :returns: true when the server is up, false otherwise
+
+.. classmethod:: Server:rmPool(pool)
+
+  Removes the server from the named pool
+
+  :param str pool: The pool to remove the server from
+
+.. classmethod:: Server:setAuto()
+
+  Set the server in the default auto state.
+  This will enable health check queries that will set the server ``up`` and ``down`` appropriatly.
+
+.. classmethod:: Server:setQPS(limit)
+
+  Limit the queries per second for this server.
+
+  :param int limit: The maximum number of queries per second
+
+.. classmethod:: Server:setDown()
+
+  Set the server in an ``DOWN`` state.
+  The server will not receive queries and the health checks are disabled
+
+.. classmethod:: Server:setUp()
+
+  Set the server in an ``UP`` state.
+  This server will still receive queries and health checks are disabled
+
+Attributes
+~~~~~~~~~~
+
+.. attribute:: Server.name
+
+  The name of the server
+
+.. attribute:: Server.upStatus
+
+  Whether or not this server is up or down
+
+.. attribute:: Server.order
+
+  The order of the server
+
+.. attribute:: Server.weight
+
+  The weight of the server
+
+Pools
+-----
+
+:class:`Server`\ s can be part of any number of pools.
+Pools are automatically created when a server is added to a pool (with :func:`newServer`).
+
+.. function:: getPool(name) -> ServerPool
+
+  Returns a :class:`ServerPool` or nil.
+
+  :param string name: The name of the pool
+
+.. function:: getPoolServers(name) -> [ Server ]
+
+  Returns a list of :class:`Server`\ s or nil.
+
+  :param string name: The name of the pool
+
+.. class:: ServerPool
+
+  This represents the pool where zero or more servers are part of.
+
+.. classmethod:: ServerPool:getCache() -> PacketCache
+
+  Returns the :class:`PacketCache` for this pool or nil.
+
+.. classmethod:: ServerPool:setCache(cache)
+
+  Adds ``cache`` as the pool's cache.
+
+  :param PacketCache cache: The new cache to add to the pool
+
+.. classmethod:: ServerPool:unsetCache()
+
+  Removes the cache from this pool.
+
+PacketCache
+~~~~~~~~~~~
+
+A Pool can have a packet cache to answer queries directly in stead of going to the backend.
+See :doc:`../guides/cache` for a how to.
+
+.. function:: newPacketCache(maxEntries[, maxTTL=86400[, minTTL=0[, temporaryFailureTTL=60[, staleTTL=60[, dontAge=false]]]]]) -> PacketCache
+
+  Creates a new :class:`PacketCache` with the settings specified.
+
+  :param int maxEntries: The maximum number of entries in this cache
+  :param int maxTTL: Cap the TTL for records to his number
+  :param int minTTL: Don't cache entries with a TTL lower than this
+  :param int temporaryFailureTTL: On a SERVFAIL or REFUSED from the backend, cache for this amount of seconds
+  :param int staleTTL: When the backend servers are not reachable, send responses if the cache entry is expired at most this amount of seconds
+  :param bool dontAge: Don't reduce TTLs when serving from the cache. use this when :program:`dnsdist` fronts a cluster of authoritative servers
+
+.. class:: PacketCache
+
+  Represents a cache that can be part of :class:`ServerPool`.
+
+.. classmethod:: PacketCache:expunge(n)
+
+  Remove entries from the cache, leaving at most ``n`` entries
+
+  :param int n: Number of entries to keep
+
+.. classmethod:: PacketCache:expungeByName(name [, qtype=dnsdist.ANY[, suffixMatch=false]])
+
+  .. versionchanged:: 1.2.0
+    ``suffixMatch`` parameter added.
+
+  Remove entries matching ``name`` and type from the cache.
+
+  :param DNSName name: The name to expunge
+  :param int qtype: The type to expunge
+  :param bool suffixMatch: When set to true, remove al entries under ``name``
+
+.. classmethod:: PacketCache:isFull() -> bool
+
+  Return true if the cache has reached the maximum number of entries.
+
+.. classmethod:: PacketCache:printStats()
+
+  Print the cache stats (hits, misses, deferred lookups and deferred inserts).
+
+.. classmethod:: PacketCache:purgeExpired(n)
+
+  Remove expired entries from the cache until there is at most ``n`` entries remaining in the cache.
+
+  :param int n: Number of entries to keep
+
+.. classmethod:: PacketCache:toString() -> string
+
+  Return the number of entries in the Packet Cache, and the maximum number of entries
+
+Status, Statistics and More
+---------------------------
+
+.. function:: dumpStats()
+
+  Print all statistics dnsdist gathers
+
+.. function:: grepq(selector[, num])
+              grepq(selectors[, num])
+
+  Prints the last ``num`` queries matching ``selector`` or ``selectors``.
+
+  The selector can be:
+
+  * a netmask (e.g. '192.0.2.0/24')
+  * a DNS name (e.g. 'dnsdist.org')
+  * a response time (e.g. '100ms')
+
+  :param str selector: Select queries based on this property.
+  :param {str} selectors: A lua table of selectors. Only queries matching all selectors are shown
+  :param int num: Show a maximum of ``num`` recent queries, default is 10.
+
+.. function:: showACL()
+
+  Print a list of all allowed netmasks.
+
+.. function:: showResponseLatency()
+
+  show a plot of the response time latency distribution
+
+.. function:: showServers()
+
+  This function shows all backend servers currently configured and some statistics.
+  These statics have the following fields:
+
+  * ``#`` - The number of the server, can be used as the argument for :func:`getServer`
+  * ``Address`` - The IP address and port of the server
+  * ``State`` - The current state of the server
+  * ``Qps`` - Current number of queries per second
+  * ``Qlim`` - Configured maximum number of queries per second
+  * ``Ord`` - The order number of the server
+  * ``Wt`` - The weight of the server
+  * ``Queries`` - Total amount of queries sent to this server
+  * ``Drops`` - Number of queries that were dropped by this server
+  * ``Drate`` - Number of queries dropped per second by this server
+  * ``Lat`` - The latency of this server in milliseconds
+  * ``Pools`` - The pools this server belongs to
+
+.. function:: showTCPStats()
+
+  show some statistics regarding TCP
+
+.. function:: showVersion()
+
+  Print the version of dnsdist
+
+.. function:: topBandwidth([num])
+
+  Print the top ``num`` clients that consume the most bandwidth.
+
+  :param int num: Number to show, defaults to 10.
+
+.. function:: topClients([num])
+
+  Print the top ``num`` clients sending the most queries over length of ringbuffer
+
+  :param int num: Number to show, defaults to 10.
+
+.. function:: topQueries([num[, labels]])
+
+  Print the ``num`` most popular QNAMEs from queries.
+  Optionally grouped by the rightmost ``labels`` DNS labels.
+
+  :param int num: Number to show, defaults to 10
+  :param int label: Number of labels to cut down to
+
+.. function:: topResponses([num[, rcode[, labels]]])
+
+  Print the ``num`` most seen responses with an RCODE or ``rcode``.
+  Optionally grouped by the rightmost ``labels`` DNS labels.
+
+  :param int num: Number to show, defaults to 10
+  :param int rcode: Response code (e.g. 0=NO Error, 2=ServFail, 3=ServFail), defaults to 0
+  :param int label: Number of labels to cut down to
+
+.. function:: topSlow([num[, limit[, labels]]])
+
+  Print the ``num`` slowest queries that are slower than ``limit`` milliseconds.
+  Optionally grouped by the rightmost ``labels`` DNS labels.
+
+  :param int num: Number to show, defaults to 10
+  :param int limit: Show queries slower than this amount of miliseconds, defaults to 2000
+  :param int label: Number of labels to cut down to
+
+.. _dynblocksref:
+
+Dynamic Blocks
+--------------
+
+.. function:: addDynBlocks(addresses, message[, seconds=10[, action]])
+
+  .. versionchanged:: 1.2.0
+    ``action`` parameter added.
+
+  Block a set of addresses with ``message`` for (optionally) a number of seconds.
+  The default number of seconds to block for is 10.
+
+  :param addresses: set of Addresses as returned by an exceed function
+  :param string message: The message to show next to the blocks
+  :param int seconds: The number of seconds this block to expire
+  :param int action: The action to take when the dynamic block matches, see :ref:`here <DNSAction>`. (default to the one set with :func:`setDynBlocksAction`)
+
+.. function:: clearDynBlocks()
+
+  Remove all current dynamic blocks.
+
+.. function:: showDynBlocks()
+
+  List all dynamic blocks in effect.
+
+.. function:: setDynBlocksAction(action)
+
+  Set which action is performed when a query is blocked.
+  Only DNSAction.Drop (the default) and DNSAction.Refused are supported.
+
+.. function:: addBPFFilterDynBlocks(addresses, filter[, seconds])
+
+  Block the set of addresses using the supplied BPF Filter, for seconds seconds (10 by default)
+
+  :param addresses: A set of addresses as returned by the exceed functions.
+  :param filter: and EBPF filter
+  :param int seconds: Number of seconds to block for
+
+.. _exceedfuncs:
+
+Getting addresses that exceeded parameters
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+.. function:: exceedServFails(rate, seconds)
+
+  Get set of addresses that exceed ``rate`` servfails/s over ``seconds`` seconds
+
+  :param int rate: Number of Servfails per second to exceed
+  :param int seconds: Number of seconds the rate has been exceeded
+
+.. function:: exceedNXDOMAINs(rate, seconds)
+
+  get set of addresses that exceed ``rate`` NXDOMAIN/s over ``seconds`` seconds
+
+  :param int rate: Number of NXDOMAIN per second to exceed
+  :param int seconds: Number of seconds the rate has been exceeded
+
+.. function:: exceedRespByterate(rate, seconds)
+
+  get set of addresses that exceeded ``rate`` bytes/s answers over ``seconds`` seconds
+
+  :param int rate: Number of bytes per second to exceed
+  :param int seconds: Number of seconds the rate has been exceeded
+
+.. function:: exceedQRate(rate, seconds)
+
+  Get set of address that exceed ``rate`` queries/s over ``seconds`` seconds
+
+  :param int rate: Number of queries per second to exceed
+  :param int seconds: Number of seconds the rate has been exceeded
+
+.. function:: exceedQTypeRate(type, rate, seconds)
+
+  Get set of address that exceed ``rate`` queries/s for queries of QType ``type`` over ``seconds`` seconds
+
+  :param int type: QType
+  :param int rate: Number of QType queries per second to exceed
+  :param int seconds: Number of seconds the rate has been exceeded
+
+Other functions
+---------------
+
+.. function:: maintenance()
+
+  If this function exists, it is called every second to so regular tasks.
+  This can be used for e.g. :doc:`Dynamic Blocks <../guides/dynblocks>`.
diff --git a/pdns/dnsdistdist/docs/reference/constants.rst b/pdns/dnsdistdist/docs/reference/constants.rst
new file mode 100644 (file)
index 0000000..b7bdcb1
--- /dev/null
@@ -0,0 +1,69 @@
+Constants
+=========
+
+There are many constants in :program:`dnsdist`.
+
+.. _DNSOpcode:
+
+OPCode
+------
+
+- ``DNSOpcode.Query``
+- ``DNSOpcode.IQuery``
+- ``DNSOpcode.Status``
+- ``DNSOpcode.Notify``
+- ``DNSOpcode.Update``
+
+.. _DNSQClass:
+
+QClass
+------
+
+- ``QClass.IN``
+- ``QClass.CHAOS``
+- ``QClass.NONE``
+- ``QClass.ANY``
+
+.. _DNSRCode:
+
+RCode
+-----
+
+- ``dnsdist.NOERROR``
+- ``dnsdist.FORMERR``
+- ``dnsdist.SERVFAIL``
+- ``dnsdist.NXDOMAIN``
+- ``dnsdist.NOTIMP``
+- ``dnsdist.REFUSED``
+- ``dnsdist.YXDOMAIN``
+- ``dnsdist.YXRRSET``
+- ``dnsdist.NXRRSET``
+- ``dnsdist.NOTAUTH``
+- ``dnsdist.NOTZONE``
+
+.. _DNSSection:
+
+DNS Section
+-----------
+
+- ``DNSSection.Question``
+- ``DNSSection.Answer``
+- ``DNSSection.Authority``
+- ``DNSSection.Additional``
+
+.. _DNSAction:
+
+DNSAction
+---------
+
+These constants represent an Action that can be returned from the functions invoked by :func:`addLuaAction` and :func:`addLuaResponseAction`.
+
+ * ``DNSAction.Allow``: let the query pass, skipping other rules
+ * ``DNSAction.Delay``: delay the response for the specified milliseconds (UDP-only), continue to the next rule
+ * ``DNSAction.Drop``: drop the query
+ * ``DNSAction.HeaderModify``: indicate that the query has been turned into a response
+ * ``DNSAction.None``: continue to the next rule
+ * ``DNSAction.Nxdomain``: return a response with a NXDomain rcode
+ * ``DNSAction.Pool``: use the specified pool to forward this query
+ * ``DNSAction.Refused``: return a response with a Refused rcode
+ * ``DNSAction.Spoof``: spoof the response using the supplied IPv4 (A), IPv6 (AAAA) or string (CNAME) value
diff --git a/pdns/dnsdistdist/docs/reference/dnscrypt.rst b/pdns/dnsdistdist/docs/reference/dnscrypt.rst
new file mode 100644 (file)
index 0000000..84133e2
--- /dev/null
@@ -0,0 +1,133 @@
+DNSCrypt objects and functions
+==============================
+
+.. function:: addDNSCryptBind(address, provider, certificate, keyfile[, options])
+
+  Adds a DNSCrypt listen socket on ``address``.
+
+  :param string address: The address and port to listen on
+  :param string provider: The provider name for this bind
+  :param string certificate: Path to the certificate file
+  :param string keyfile: Path to the key file of the certificate
+  :param table options: A table with key: value pairs with options (see below)
+
+  Options:
+
+  * ``doTCP=true``: bool - Also bind on TCP on ``address``.
+  * ``reusePort=false``: bool - Set the ``SO_REUSEPORT`` socket option.
+  * ``tcpFastOpenSize=0``: int - Set the TCP Fast Open queue size, enabling TCP Fast Open when available and the value is larger than 0
+  * ``interface=""``: str - Sets the network interface to use
+
+.. function:: generateDNSCryptProviderKeys(publicKey, privateKey)
+
+  Generate a new provider keypair and write them to ``publicKey`` and ``privateKey``.
+
+  :param string publicKey: path to write the public key to
+  :param string privateKey: path to write the private key to
+
+.. function:: generateDNSCryptCertificate(privatekey, certificate, keyfile, serial, validFrom, validUntil)
+
+  generate a new resolver private key and related certificate, valid from the ``validFrom`` UNIX timestamp until the ``validUntil`` one, signed with the provider private key.
+
+  :param string privatekey: Path to the private key of the provider.
+  :param string certificate: Path where to write the certificate file.
+  :param string keyfile: Path where to write the private key for the certificate.
+  :param int serial: The certificate's serial number.
+  :param int validFrom: Unix timestamp from when the certificate will be valid.
+  :param int validUntil: Unix timestamp until when the certificate will be valid.
+
+.. function:: printDNSCryptProviderFingerprint(keyfile)
+
+  Display the fingerprint of the provided resolver public key
+
+  :param string keyfile: Path to the key file
+
+.. function:: showDNSCryptBinds()
+
+  Display the currently configured DNSCrypt binds
+
+.. function:: getDNSCryptBind(n) -> DNSCryptContext
+
+  Return the :class:`DNSCryptContext` object corresponding to the bind ``n``.
+
+Certificates
+------------
+
+.. class:: DNSCryptCert
+
+  Represents a DNSCrypt certificate.
+
+.. classmethod:: DNSCryptCert:getClientMagic() -> string
+
+  Return this certificate's client magic value.
+
+.. classmethod:: DNSCryptCert:getEsVersion() -> string
+
+  Return the cryptographic construction to use with this certificate,.
+
+.. classmethod:: DNSCryptCert:getMagic() -> string
+
+  Return the certificate magic number.
+
+.. classmethod:: DNSCryptCert:getProtocolMinorVersion() -> string
+
+  Return this certificate's minor version.
+
+.. classmethod:: DNSCryptCert:getResolverPublicKey() -> string
+
+  Return the public key corresponding to this certificate.
+
+.. classmethod:: DNSCryptCert:getSerial() -> int
+
+  Return the certificate serial number.
+
+.. classmethod:: DNSCryptCert:getSignature() -> string
+
+  Return this certificate's signature.
+
+.. classmethod:: DNSCryptCert:getTSEnd() -> int
+
+  Return the date the certificate is valid from, as a Unix timestamp.
+
+.. classmethod:: DNSCryptCert:getTSStart() -> int
+
+  Return the date the certificate is valid until (inclusive), as a Unix timestamp
+
+Context
+-------
+
+.. class:: DNSCryptContext
+
+  Represents a DNSCrypt content. Can be used to rotate certs.
+
+.. classmethod:: DNSCryptContext:generateAndLoadInMemoryCertificate(keyfile, serial, begin, end)
+
+  Generate a new resolver key and the associated certificate in-memory, sign it with the provided provider key, and use the new certificate
+
+  :param string keyfile: Path to the key file to use
+  :param int serial: The serial number of the certificate
+  :param int begin: Unix timestamp from when the certificate is valid
+  :param int end: Unix timestamp from until the certificate is valid
+
+.. classmethod:: DNSCryptContext:getCurrentCertificate() -> DNSCryptCert
+
+  Return the current certificate.
+
+.. classmethod:: DNSCryptContext:getOldCertificate() -> DNSCryptCert
+
+  Return the previous certificate.
+
+.. classmethod:: DNSCryptContext:getProviderName() -> string
+
+  Return the provider name
+
+.. classmethod:: DNSCryptContext:hasOldCertificate() -> bool
+
+  Whether or not the context has a previous certificate, from a certificate rotation.
+
+.. classmethod:: DNSCryptContext:loadNewCertificate(certificate, keyfile)
+
+  Load a new certificate and the corresponding private key, and use it
+
+  :param string certificate: Path to a certificate file
+  :param string keyfile: Path to a the corresponding key file
diff --git a/pdns/dnsdistdist/docs/reference/dnsname.rst b/pdns/dnsdistdist/docs/reference/dnsname.rst
new file mode 100644 (file)
index 0000000..e769ad5
--- /dev/null
@@ -0,0 +1,62 @@
+.. _DNSName:
+
+DNSName objects
+===============
+
+.. class:: DNSName
+
+  A ``DNSName`` object represents a name in the DNS.
+  It is returned by several functions and has several functions to programmatically interact with it.
+
+Creating a ``DNSName`` is done with the :func:`newDNSName`::
+
+  myname = newDNSName("www.example.com")
+
+dnsdist will complain loudly if the name is invalid (e.g. too long, dot in the wrong place).
+
+The ``myname`` variable has several functions to get information from it
+
+.. code-block:: lua
+
+  print(myname:countLabels()) -- prints "3"
+  print(myname:wirelength()) -- prints "17"
+  name2 = newDNSName("example.com")
+  if myname:isPartOf(name2) then -- prints "it is"
+    print('it is')
+  end
+
+
+Functions and methods of a ``DNSName``
+--------------------------------------
+
+.. function:: newDNSName(name) -> DNSName
+
+  Returns the :class:`DNSName` object of ``name``.
+
+  :param string name: The name to create a DNSName for
+
+.. classmethod:: DNSName::chopoff() -> bool
+
+  .. versionadded:: 1.2.0
+
+  Removes the left-most label and returns ``true``.
+  ``false`` is returned if no label was removed
+
+.. classmethod:: DNSName:countLabels() -> int
+
+  Returns the number of DNSLabels in the name
+
+.. classmethod:: DNSName:isPartOf(name) -> bool
+
+  Returns true if the DNSName is part of the DNS tree of ``name``.
+
+  :param DNSName name: The name to check against
+
+.. classmethod:: DNSName:toString() -> string
+                 DNSName:tostring() -> string
+
+  Returns a human-readable form of the DNSName.
+
+.. classmethod:: DNSName:wirelength -> int
+
+  Returns the length in bytes of the DNSName as it would be on the wire.
diff --git a/pdns/dnsdistdist/docs/reference/dq.rst b/pdns/dnsdistdist/docs/reference/dq.rst
new file mode 100644 (file)
index 0000000..868eeb4
--- /dev/null
@@ -0,0 +1,154 @@
+.. _DNSQuestion:
+
+The DNSQuestion (``dq``) object
+===============================
+
+A DNSQuestion or ``dq`` object is available in several hooks and Lua actions.
+This object contains details about the current state of the question.
+This state can be modified from the various hooks.
+
+The DNSQuestion object has several attributes, many of them read-only:
+
+.. class:: DNSQuestion
+
+.. attribute:: DNSQuestion.dh
+
+  The :ref:`DNSHeader` of this query.
+
+.. attribute:: DNSQuestion.ecsOverride
+
+  Whether an existing ECS value should be overridden, settable.
+
+.. attribute:: DNSQuestion.ecsPrefixLength
+
+   The ECS prefix length to use, settable.
+
+.. attribute:: DNSQuestion.len
+
+  The length of the :attr:`qname <DNSQuestion.qname>`.
+
+.. attribute:: DNSQuestion.localaddr
+
+  :ref:`ComboAddress` of the local bind this question was received on.
+
+.. attribute:: DNSQuestion.opcode
+
+  Integer describing the OPCODE of the packet. Can be matched against :ref:`DNSOpcode`.
+
+.. attribute:: DNSQuestion.qclass
+
+  QClass (as an unsigned integer) of this question.
+  Can be compared against :ref:`DNSQClass`.
+
+.. attribute:: DNSQuestion.qname
+
+  :class:`DNSName` of this question.
+
+.. attribute:: DNSQuestion.qtype
+
+  QType (as an unsigned integer) of this question.
+  Can be compared against ``dnsdist.A``, ``dnsdist.AAAA`` etc.
+
+.. attribute:: DNSQuestion.remoteaddr
+
+  :ref:`ComboAddress` of the remote client.
+
+.. attribute:: DNSQuestion.rcode
+
+  RCode (as an unsigned integer) of this question.
+  Can be compared against :ref:`DNSRCode`
+
+.. attribute:: DNSQuestion.size
+
+  The total size of the buffer starting at :attr:`DNSQuestion.dh`.
+
+.. attribute:: DNSQuestion.skipCache
+
+  Whether to skip cache lookup / storing the answer for this question, settable.
+
+.. attribute:: DNSQuestion.tcp
+
+  Whether the query have been received over TCP.
+
+.. attribute:: DNSQuestion.useECS
+
+  Whether to send ECS to the backend, settable.
+
+It also supports the following methods:
+
+.. classmethod:: DNSQuestion.getDO() -> bool
+
+  .. versionadded:: 1.2.0
+
+  Get the value of the DNSSEC OK bit.
+
+  :returns: true if the DO bit was set, false otherwise
+
+.. _DNSResponse:
+
+DNSResponse object
+==================
+
+.. class:: DNSResponse
+
+  This object has all the functions and members of a :ref:`DNSQuestion <DNSQuestion>` and some more
+
+.. classmethod:: DNSResponse:editTTLs(func)
+
+  The function ``func`` is invoked for every entry in the answer, authority and additional section.
+
+  ``func`` points to a function with the following prototype: ``myFunc(section, qclass, qtype, ttl)``
+
+  All parameters to ``func`` are integers:
+
+  - ``section`` is the section in the packet and can be compared to :ref:`DNSSection`
+  - ``qclass`` is the QClass of the record. Can be compared to :ref:`DNSQClass`
+  - ``qtype`` is the QType of the record. Can be e.g. compared to ``dnsdist.A``, ``dnsdist.AAAA`` and the like.
+  - ``ttl`` is the current TTL
+
+  This function must return an integer with the new TTL.
+  Setting this TTL to 0 to leaves it unchanged
+
+  :param string func: The function to call to edit TTLs.
+
+.. _DNSHeader:
+
+DNSHeader (``dh``) object
+=========================
+
+.. class:: DNSHeader
+
+  This object holds a representation of a DNS packet's header.
+
+.. classmethod:: DNSHeader:getRD() -> bool
+
+  Get recursion desired flag.
+
+.. classmethod:: DNSHeader:setRD(rd)
+
+  Set recursion desired flag.
+
+  :param bool rd: State of the RD flag
+
+.. classmethod:: DNSHeader:setTC(tc)
+
+  Set truncation flag (TC).
+
+  :param bool tc: State of the TC flag
+
+.. classmethod:: DNSHeader:setQR(qr)
+
+  Set Query/Response flag.
+  Setting QR to true means "This is an answer packet".
+
+  :param bool qr: State of the QR flag
+
+.. classmethod:: DNSHeader:getCD() -> bool
+
+  Get checking disabled flag.
+
+.. classmethod:: DNSHeader:setCD(cd)
+
+  Set checking disabled flag.
+
+  :param bool cd: State of the CD flag
diff --git a/pdns/dnsdistdist/docs/reference/ebpf.rst b/pdns/dnsdistdist/docs/reference/ebpf.rst
new file mode 100644 (file)
index 0000000..6e7de06
--- /dev/null
@@ -0,0 +1,57 @@
+eBPF functions and objects
+==========================
+
+These are all the functions, objects and methods related to the :doc:`../advanced/ebpf`.
+
+.. function:: newBPFFilter(maxV4, maxV6, maxQNames) -> BPFFilter
+
+  Return a new eBPF socket filter with a maximum of maxV4 IPv4, maxV6 IPv6 and maxQNames qname entries in the block table.
+
+  :param int maxV4: Maximum number of IPv4 entries in this filter
+  :param int maxV6: Maximum number of IPv6 entries in this filter
+  :param int maxQNames: Maximum number of QName entries in this filter
+
+.. function:: setDefaultBPFFilter(filter)
+
+  When used at configuration time, the corresponding BPFFilter will be attached to every bind.
+
+  :param BPFFilter filter: The filter ro attach
+
+.. class:: BPFFilter
+
+  Represents an eBPF filter
+
+.. classmethod:: BPFFilter:attachToAllBinds()
+
+  Attach this filter to every bind already defined.
+  This is the run-time equivalent of :func:`setDefaultBPFFilter`
+
+.. classmethod:: BPFFilter:block(address)
+
+  Block this address
+
+  :param ComboAddress address: The address to block
+
+.. classmethod:: BPFFilter:blockQName(name [, qtype=255])
+
+  Block queries for this exact qname. An optional qtype can be used, defaults to 255.
+
+  :param DNSName name: The name to block
+  :param int qtype: QType to block
+
+.. classmethod:: BPFFilter:getStats()
+
+  Print the block tables.
+
+.. classmethod:: BPFFilter:unblock(address)
+
+  Unblock this address.
+
+  :param ComboAddress address: The address to unblock
+
+.. classmethod:: BPFFilter:unblockQName(name [, qtype=255])
+
+  Remove this qname from the block list.
+
+  :param DNSName name: the name to unblock
+  :param int qtype: The qtype to unblock
diff --git a/pdns/dnsdistdist/docs/reference/index.rst b/pdns/dnsdistdist/docs/reference/index.rst
new file mode 100644 (file)
index 0000000..c751c9d
--- /dev/null
@@ -0,0 +1,19 @@
+Reference Guides
+================
+
+These chapters contain extensive information on all functions and object available in dnsdist.
+
+.. toctree::
+  :maxdepth: 3
+
+  config
+  constants
+  comboaddress
+  netmaskgroup
+  dnsname
+  dq
+  ebpf
+  dnscrypt
+  protobuf
+  snmp
+  tuning
diff --git a/pdns/dnsdistdist/docs/reference/netmaskgroup.rst b/pdns/dnsdistdist/docs/reference/netmaskgroup.rst
new file mode 100644 (file)
index 0000000..bdcc038
--- /dev/null
@@ -0,0 +1,32 @@
+NetmaskGroup
+============
+
+.. class:: NetmaskGroup
+
+   Represents a group of netmasks that can be used to match :class:`ComboAddress`\ es against.
+
+.. function:: newNGM() -> NetmaskGroup
+
+  Returns a NetmaskGroup
+
+.. classmethod:: NetmaskGroup:addMask(mask)
+                 NetmaskGroup:addMask(masks)
+
+  Add one or more masks to the NGM.
+
+  :param string mask: Add this mask, prefix with `!` to exclude this mask from matching.
+  :param table masks: Adds the keys of the table to the :class:`NetmaskGroup`. It should be a table whose keys are :class:`ComboAddress` objects and values are integers, as returned by `exceed*` functions.
+
+.. classmethod:: NetmaskGroup:match(address) -> bool
+
+  Checks if ``address`` is matched by this NetmaskGroup.
+
+  :param ComboAddress address: The address to match.
+
+.. classmethod:: NetmaskGroup:clear()
+
+  Clears the NetmaskGroup.
+
+.. classmethod:: NetmaskGroup:size() -> int
+
+  Returns number of netmasks in this NetmaskGroup.
diff --git a/pdns/dnsdistdist/docs/reference/protobuf.rst b/pdns/dnsdistdist/docs/reference/protobuf.rst
new file mode 100644 (file)
index 0000000..3a5fcc1
--- /dev/null
@@ -0,0 +1,74 @@
+Protobuf Logging Reference
+==========================
+
+.. class:: DNSDistProtoBufMessage
+
+  This object represents a single protobuf message as emitted by :program:`dnsdist`.
+
+.. classmethod:: DNSDistProtoBufMessage:setBytes(bytes)
+
+  Set the size of the query
+
+  :param int bytes: Number of bytes in the query.
+
+.. classmethod:: DNSDistProtoBufMessage:setEDNSSubnet(netmask)
+
+  Set the EDNS Subnet to ``netmask``.
+
+  :param string netmask: The netmask to set to.
+
+.. classmethod:: DNSDistProtoBufMessage:setQueryTime(sec, usec)
+
+  In a response message, set the time at which the query has been received.
+
+  :param int sec: Unix timestamp when the query was received.
+  :param int usec: The microsecond the query was received.
+
+.. classmethod:: DNSDistProtoBufMessage:setQuestion(name, qtype, qclass)
+
+  Set the question in the protobuf message.
+
+  :param DNSName name: The qname of the question
+  :param int qtype: The qtype of the question
+  :param int qclass: The qclass of the question
+
+.. classmethod:: DNSDistProtoBufMessage:setRequestor(address)
+
+  Set the requestor's address.
+
+  :param ComboAddress address: The address to set to
+
+.. classmethod:: DNSDistProtoBufMessage:setRequestorFromString(address)
+
+  Set the requestor's address from a string.
+
+  :param string address: The address to set to
+
+.. classmethod:: DNSDistProtoBufMessage:setResponder(address)
+
+  Set the responder's address.
+
+  :param ComboAddress address: The address to set to
+
+.. classmethod:: DNSDistProtoBufMessage:setResponderFromString(string)
+
+  Set the responder's address.
+
+  :param string address: The address to set to
+
+.. classmethod:: DNSDistProtoBufMessage:setResponseCode(rcode)
+
+  Set the response code of the query.
+
+  :param int rcode: The response code of the answer
+
+.. classmethod:: DNSDistProtoBufMessage:setTime(sec, usec)
+
+  Set the time at which the query or response has been received.
+
+  :param int sec: Unix timestamp when the query was received.
+  :param int usec: The microsecond the query was received.
+
+.. classmethod:: DNSDistProtoBufMessage:toDebugString() -> string
+
+  Return an string containing the content of the message
diff --git a/pdns/dnsdistdist/docs/reference/snmp.rst b/pdns/dnsdistdist/docs/reference/snmp.rst
new file mode 100644 (file)
index 0000000..3f9247f
--- /dev/null
@@ -0,0 +1,19 @@
+SNMP reporting
+==============
+
+.. versionadded:: 1.2.0
+
+
+.. function:: snmpAgent(enableTraps [, masterSocket])
+
+  Enable SNMP support.
+
+  :param bool enableTraps: Indicates whether traps should be sent
+  :param string masterSocket: A string specifying how to connect to the master agent. This is a file path to a unix socket, but e.g. ``tcp:localhost:705`` can be used as well. By default, SNMP agent's default socket is used.
+
+.. function:: sendCustomTrap(message)
+
+  Send a custom SNMP trap from Lua.
+
+  :param string message: The message to include in the sent trap
+
diff --git a/pdns/dnsdistdist/docs/reference/tuning.rst b/pdns/dnsdistdist/docs/reference/tuning.rst
new file mode 100644 (file)
index 0000000..5471e4d
--- /dev/null
@@ -0,0 +1,80 @@
+Tuning related functions
+========================
+
+.. function:: setMaxTCPClientThreads(num)
+
+  Set the maximum of TCP client threads, handling TCP connections
+
+  :param int num:
+
+.. function:: setMaxTCPConnectionDuration(num)
+
+  Set the maximum duration of an incoming TCP connection, in seconds. 0 (the default) means unlimited
+
+  :param int num:
+
+.. function:: setMaxTCPConnectionsPerClient(num)
+
+  Set the maximum number of TCP connections per client. 0 (the default) means unlimited
+
+  :param int num:
+
+.. function:: setMaxTCPQueriesPerConnection(num)
+
+  Set the maximum number of queries in an incoming TCP connection. 0 (the default) means unlimited
+
+  :param int num:
+
+.. function:: setMaxTCPQueuedConnections(num)
+
+  Set the maximum number of TCP connections queued (waiting to be picked up by a client thread), defaults to 1000. 0 means unlimited
+
+  :param int num:
+
+.. function:: setMaxUDPOutstanding(num)
+
+  Set the maximum number of outstanding UDP queries to a given backend server. This can only be set at configuration time and defaults to 10240
+
+  :param int num:
+
+.. function:: setCacheCleaningDelay(num)
+
+  Set the interval in seconds between two runs of the cache cleaning algorithm, removing expired entries
+
+  :param int num:
+
+.. function:: setCacheCleaningPercentage(num)
+
+  Set the percentage of the cache that the cache cleaning algorithm will try to free by removing expired entries. By default (100), all expired entries are removed
+
+  :param int num:
+
+.. function:: setStaleCacheEntriesTTL(num)
+
+  Allows using cache entries expired for at most n seconds when no backend available to answer for a query
+
+  :param int num:
+
+.. function:: setTCPUseSinglePipe(val)
+
+  Whether the incoming TCP connections should be put into a single queue instead of using per-thread queues. Defaults to false
+
+  :param bool val:
+
+.. function:: setTCPRecvTimeout(num)
+
+  Set the read timeout on TCP connections from the client, in seconds
+
+  :param int num:
+
+.. function:: setTCPSendTimeout(num)
+
+  Set the write timeout on TCP connections from the client, in seconds
+
+  :param int num:
+
+.. function:: setUDPTimeout(num)
+
+  set the maximum time dnsdist will wait for a response from a backend over UDP, in seconds. Defaults to 2
+
+  :param int num:
diff --git a/pdns/dnsdistdist/docs/requirements.txt b/pdns/dnsdistdist/docs/requirements.txt
new file mode 100644 (file)
index 0000000..168c2f1
--- /dev/null
@@ -0,0 +1,6 @@
+Sphinx>=1.5.0
+git+https://github.com/pieterlexis/sphinx-lua@pdns
+git+https://github.com/pieterlexis/sphinx-jsondomain@no-type-links
+git+https://github.com/pieterlexis/sphinx-changelog@render-tags
+sphinxcontrib-httpdomain
+sphinxcontrib-fulltoc
diff --git a/pdns/dnsdistdist/docs/rules-actions.rst b/pdns/dnsdistdist/docs/rules-actions.rst
new file mode 100644 (file)
index 0000000..eda68aa
--- /dev/null
@@ -0,0 +1,701 @@
+Packet Policies
+===============
+
+dnsdist works in essence like any other loadbalancer:
+
+It receives packets on one or several addresses it listens on, and determines whether it will process this packet based on the :doc:`advanced/acl`. Should the packet be processed, dnsdist attempts to match any of the configured rules in order and when one matches, the associated action is performed.
+
+These rule and action combinations are considered policies.
+
+Packet Actions
+--------------
+
+Each packet can be:
+
+- Dropped
+- Turned into an answer directly
+- Forwarded to a downstream server
+- Modified and forwarded to a downstream and be modified back
+- Be delayed
+
+This decision can be taken at different times during the forwarding process.
+
+Examples
+~~~~~~~~
+
+Rules for traffic exceeding QPS limits
+^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+Traffic that exceeds a QPS limit, in total or per IP (subnet) can be matched by a rule.
+
+For example::
+
+  addDelay(MaxQPSIPRule(5, 32, 48), 100)
+
+This measures traffic per IPv4 address and per /48 of IPv6, and if traffic for such an address (range) exceeds 5 qps, it gets delayed by 100ms.
+
+As another example::
+
+  addAction(MaxQPSIPRule(5), NoRecurseAction())
+
+This strips the Recursion Desired (RD) bit from any traffic per IPv4 or IPv6 /64 that exceeds 5 qps.
+This means any those traffic bins is allowed to make a recursor do 'work' for only 5 qps.
+
+If this is not enough, try::
+
+  addAction(MaxQPSIPRule(5), DropAction())
+
+or::
+
+  addAction(MaxQPSIPRule(5), TCAction())
+
+This will respectively drop traffic exceeding that 5 QPS limit per IP or range, or return it with TC=1, forcing clients to fall back to TCP.
+
+To turn this per IP or range limit into a global limit, use ``NotRule(MaxQPSRule(5000))`` instead of :func:`MaxQPSIPRule`.
+
+Regular Expressions
+^^^^^^^^^^^^^^^^^^^
+
+:func:`RegexRule` matches a regular expression on the query name, and it works like this::
+
+  addAction(RegexRule("[0-9]{5,}"), DelayAction(750)) -- milliseconds
+  addAction(RegexRule("[0-9]{4,}\\.example$"), DropAction())
+
+This delays any query for a domain name with 5 or more consecutive digits in it.
+The second rule drops anything with more than 4 consecutive digits within a .example domain.
+
+Note that the query name is presented without a trailing dot to the regex.
+The regex is applied case insensitively.
+
+Alternatively, if compiled in, :func:`RE2Rule` provides similar functionality, but against libre2.
+
+Rule Generators
+---------------
+
+:program:`dnsdist` contains several functions that make it easier to add actions and rules.
+
+.. function:: addAnyTCRule()
+
+  Set the TC-bit (truncate) on all queries received over UDP.
+  Forcing a retry over TCP.
+  This is equivalent to doing::
+
+    addAction(AndRule(AllRule(), TCPRule(false)), TCAction())
+
+.. function:: addDelay(DNSrule, delay)
+
+  Delay the query for ``delay`` milliseconds before sending to a backend.
+
+  :param DNSRule: The DNSRule to match traffic
+  :param int delay: The delay time in milliseconds.
+
+.. function:: addDisableValidationRule(DNSrule)
+
+  Set the CD (Checking Disabled) flag to 1 for all queries matching the DNSRule.
+  Using this function is equal to using the :func:`DisableValidationAction`.
+
+.. function:: addDomainBlock(domain)
+
+  Drop all queries for ``domain`` and all names below it.
+
+  :param string domain: The domain name to block
+
+.. function:: addDomainSpoof(domain, IPv4[, IPv6])
+              addDomainSpoof(domain, {IP[,...]})
+
+  Generate answers for A/AAAA/ANY queries.
+
+  :param string domain: Domain name to spoof for
+  :param string IPv4: IPv4 address to spoof in the reply
+  :param string IPv6: IPv6 address to spoof in the reply
+  :param string IP: IP address to spoof in the reply
+
+.. function:: addDomainCNAMESpoof(domain, cname)
+
+  Generate CNAME answers for queries.
+
+  :param string domain: Domain name to spoof for
+  :param string cname: Domain name to add CNAME to
+
+.. function:: addLuaAction(DNSrule, function)
+
+  Invoke a Lua function that accepts a :class:`DNSQuestion`.
+  This function works similar to using :func:`LuaAction`.
+
+  The ``function`` should return a :ref:`DNSAction`.
+
+  :param DNSRule: match queries based on this rule
+  :param string function: the name of a Lua function
+
+.. function:: addLuaResponseAction(DNSrule, function)
+
+  Invoke a Lua function that accepts a :class:`DNSQuestion` on the response.
+  This function works similar to using :func:`LuaAction`.
+
+  The ``function`` should return a :ref:`DNSAction`.
+
+  :param DNSRule: match queries based on this rule
+  :param string function: the name of a Lua function
+
+.. function:: addNoRecurseRule(DNSrule)
+
+  Clear the RD flag for all queries matching the rule.
+
+  :param DNSRule: match queries based on this rule
+
+.. function:: addPoolRule(DNSRule, pool)
+
+  Send queries matching the first argument to the pool ``pool``.
+  e.g.::
+
+    addPoolRule("example.com", "myPool")
+
+  This is equivalent to::
+
+    addAction("example.com", PoolAction("myPool"))
+
+  :param DNSRule: match queries based on this rule
+  :param string pool: The name of the pool to send the queries to
+
+.. function:: addQPSLimit(DNSrule, limit)
+
+  Limit queries matching the DNSRule to ``limit`` queries per second.
+  All queries over the limit are dropped.
+
+  :param DNSRule: match queries based on this rule
+  :param int limit: QPS limit for this rule
+
+.. function:: addQPSPoolRule(DNSRule, limit, pool)
+
+  Send at most ``limit`` queries/s for this pool, letting the subsequent rules apply otherwise.
+  This is a convience function for the following syntax::
+
+    addAction("192.0.2.0/24", QPSPoolAction(15, "myPool")
+
+  :param DNSRule: match queries based on this rule
+  :param int limit: QPS limit for this rule
+  :param string pool: The name of the pool to send the queries to
+
+
+Managing Rules
+--------------
+
+Active Rules can be shown with :func:`showRules` and removed with :func:`rmRule`::
+
+  > addQPSLimit("h4xorbooter.xyz.", 10)
+  > addQPSLimit({"130.161.0.0/16", "145.14.0.0/16"} , 20)
+  > addQPSLimit({"nl.", "be."}, 1)
+  > showRules()
+  #     Matches Rule                                               Action
+  0           0 h4xorbooter.xyz.                                   qps limit to 10
+  1           0 130.161.0.0/16, 145.14.0.0/16                      qps limit to 20
+  2           0 nl., be.                                           qps limit to 1
+
+For Rules related to the incoming query:
+
+.. function:: addAction(DNSrule, action)
+
+  Add a Rule and Action to the existing rules.
+
+  :param DNSrule rule: A DNSRule, e.g. an :func:`allRule` or a compounded bunch of rules using e.g. :func:`AndRule`
+  :param action: The action to take
+
+.. function:: clearRules()
+
+  Remove all current rules.
+
+.. function:: getAction(n) -> Action
+
+  Returns the Action associated with rule ``n``.
+
+  :param int n: The rule number
+
+.. function:: mvRule(from, to)
+
+  Move rule ``from`` to a position where it is in front of ``to``.
+  ``to`` can be one larger than the largest rule, in which case the rule will be moved to the last position.
+
+  :param int from: Rule number to move
+  :param int to: Location to more the Rule to
+
+.. function:: newRuleAction(rule, action)
+
+  Return a pair of DNS Rule and DNS Action, to be used with :func:`setRules`.
+
+  :param Rule rule: A `Rule <#traffic-matching>`_
+  :param Action action: The `Action <#actions>`_ to apply to the matched traffic
+
+.. function:: setRules(rules)
+
+  Replace the current rules with the supplied list of pairs of DNS Rules and DNS Actions (see :func:`newRuleAction`)
+
+  :param [RuleAction] rules: A list of RuleActions
+
+.. function:: showRules()
+
+  Show all defined rules for queries.
+
+.. function:: topRule()
+
+  Move the last rule to the first position.
+
+.. function:: rmRule(n)
+
+  Remove rule ``n``.
+
+  :param int n: Rule number to remove
+
+For Rules related to responses:
+
+.. function:: addResponseAction(DNSRule, action)
+
+  Add a Rule and Action for responses to the existing rules.
+
+  :param DNSRule: A DNSRule, e.g. an :func:`allRule` or a compounded bunch of rules using e.g. :func:`AndRule`
+  :param action: The action to take
+
+.. function:: mvResponseRule(from, to)
+
+  Move response rule ``from`` to a position where it is in front of ``to``.
+  ``to`` can be one larger than the largest rule, in which case the rule will be moved to the last position.
+
+  :param int from: Rule number to move
+  :param int to: Location to more the Rule to
+
+.. function:: rmResponseRule(n)
+
+  Remove response rule ``n``.
+
+  :param int n: Rule number to remove
+
+.. function:: showResponseRules()
+
+  Show all defined response rules.
+
+.. function:: topResponseRule()
+
+  Move the last response rule to the first position.
+
+Functions for manipulation Cache Hit Rules:
+
+.. function:: addCacheHitAction(DNSRule, action)
+
+  .. versionadded:: 1.2.0
+
+  Add a Rule and Action for Cache Hits to the existing rules.
+
+  :param DNSRule: A DNSRule, e.g. an :func:`allRule` or a compounded bunch of rules using e.g. :func:`AndRule`
+  :param action: The action to take
+
+.. function:: mvCacheHitResponseRule(from, to)
+
+  .. versionadded:: 1.2.0
+
+  Move cache hit response rule ``from`` to a position where it is in front of ``to``.
+  ``to`` can be one larger than the largest rule, in which case the rule will be moved to the last position.
+
+  :param int from: Rule number to move
+  :param int to: Location to more the Rule to
+
+.. function:: rmCacheHitResponseRule(n)
+
+  .. versionadded:: 1.2.0
+
+  Remove cache hit response rule ``n``.
+
+  :param int n: Rule number to remove
+
+.. function:: showCacheHitResponseRules()
+
+  .. versionadded:: 1.2.0
+
+  Show all defined cache hit response rules.
+
+.. function:: topCacheHitResponseRule()
+
+  .. versionadded:: 1.2.0
+
+  Move the last cache hit response rule to the first position.
+
+.. _RulesIntro:
+
+Matching Packets (Selectors)
+----------------------------
+
+Packets can be matched by selectors, called a ``DNSRule``.
+These ``DNSRule``\ s be one of the following items:
+
+  * A string that is either a domain name or netmask
+  * A list of strings that are either domain names or netmasks
+  * A :class:`DNSName`
+  * A list of :class:`DNSName`\ s
+  * A (compounded) ``Rule``
+
+.. versionadded:: 1.2.0
+   A DNSRule can also be a :class:`DNSName` or a list of these
+
+.. function:: AllRule()
+
+  Matches all traffic
+
+.. function:: DNSSECRule()
+
+  Matches queries with the DO flag set
+
+.. function:: MaxQPSIPRule(qps[, v4Mask[, v6Mask]])
+
+  Matches traffic for a subnet specified by ``v4Mask`` or ``v6Mask`` exceeding ``qps`` queries per second
+
+  :param int qps: The number of queries per second allowed, above this number traffic is matched
+  :param int v4Mask: The IPv4 netmask to match on. Default is 32 (the whole address)
+  :param int v6Mask: The IPv6 netmask to match on. Default is 64
+
+.. function:: MaxQPSRule(qps)
+
+  Matches traffic exceeding this qps limit. If e.g. this is set to 50, starting at the 51st query of the current second traffic is matched.
+  This can be used to enforce a global QPS limit.
+
+  :param int qps: The number of queries per second allowed, above this number traffic is matched
+
+.. function:: NetmaskGroupRule(nmg[, src])
+
+  Matches traffic from/to the network range specified in ``nmg``.
+
+  Set the ``src`` parameter to false to match ``nmg`` against destination address instead of source address.
+  This can be used to differentiate between clients 
+
+  :param NetMaskGroup nmg: The NetMaskGroup to match on
+  :param bool src: Whether to match source or destination address of the packet. Defaults to true (matches source)
+
+.. function:: OpcodeRule(code)
+
+  Matches queries with opcode ``code``.
+  ``code`` can be directly specified as an integer, or one of the `built-in DNSOpcode <#opcode>`_.
+
+  :param int code: The opcode to match
+
+.. function:: QClassRule(qclass)
+
+  Matches queries with the specified ``qclass``.
+  ``class`` can be specified as an integer or as one of the built-in `QClass <#qclass>`_.
+
+  :param int qclass: The Query Class to match on
+
+.. function:: QnameRule(qname)
+
+  .. versionadded:: 1.2.0
+
+   Matches queries with the specified qname exactly.
+
+   :param string qname: Qname to match
+
+.. function:: QNameLabelsCountRule(min, max)
+
+  Matches if the qname has less than ``min`` or more than ``max`` labels.
+
+  :param int min: Minimum number of labels
+  :param int max: Maximum nimber of labels
+
+.. function:: QNameWireLengthRule(min, max)
+
+  Matches if the qname's length on the wire is less than ``min`` or more than ``max`` bytes.
+
+  :param int min: Minimum number of bytes
+  :param int max: Maximum nimber of bytes
+
+.. function:: QTypeRule(qtype)
+
+  Matches queries with the specified ``qtype``
+  ``qtype`` may be specified as an integer or as one of the built-in QTypes.
+  For instance ``dnsdist.A``, ``dnsdist.TXT`` and ``dnsdist.ANY``.
+
+  :param int qtype: The QType to match on
+
+.. function:: RCodeRule(rcode)
+
+  Matches queries or responses the specified ``rcode``.
+  ``rcode`` can be specified as an integer or as one of the built-in `RCode <#rcode>`_.
+
+  :param int rcode: The RCODE to match on
+
+.. function:: RDRule()
+
+  .. versionadded:: 1.2.0
+
+  Matches queries with the RD flag set.
+
+.. function:: RegexRule(regex)
+
+  Matches the query name against the ``regex``.
+
+  .. code-block:: Lua
+
+    addAction(RegexRule("[0-9]{5,}"), DelayAction(750)) -- milliseconds
+    addAction(RegexRule("[0-9]{4,}\\.example$"), DropAction())
+
+  This delays any query for a domain name with 5 or more consecutive digits in it.
+  The second rule drops anything with more than 4 consecutive digits within a .EXAMPLE domain.
+
+  Note that the query name is presented without a trailing dot to the regex.
+  The regex is applied case insensitively.
+
+  :param string regex: A regular expression to match the traffic on
+
+.. function:: RecordsCountRule(section, minCount, maxCount)
+
+  Matches if there is at least ``minCount`` and at most ``maxCount`` records in the section ``section``.
+  ``section`` can be specified as an integer or as a :ref:`DNSSection`.
+
+  :param int section: The section to match on
+  :param int minCount: The minimum number of entries
+  :param int maxCount: The maximum number of entries
+
+.. function:: RecordsTypeCountRule(section, qtype, minCount, maxCount)
+
+  Matches if there is at least ``minCount`` and at most ``maxCount`` records of type ``type`` in the section ``section``.
+  ``section`` can be specified as an integer or as a ref:`DNSSection`.
+  ``qtype`` may be specified as an integer or as one of the built-in QTypes, for instance ``dnsdist.A`` or ``dnsdist.TXT``.
+
+  :param int section: The section to match on
+  :param int qtype: The QTYPE to match on
+  :param int minCount: The minimum number of entries
+  :param int maxCount: The maximum number of entries
+
+.. function:: RE2Rule(regex)
+
+  Matches the query name against the supplied regex using the RE2 engine.
+
+  For an example of usage, see :func:`RegexRule`.
+
+  :note: Only available when dnsdist was built with libre2 support.
+
+  :param str regex: The regular expression to match the QNAME.
+
+.. function:: SuffixMatchNodeRule(smn[, quiet])
+
+  Matches based on a group of domain suffixes for rapid testing of membership.
+  Pass true as second parameter to prevent listing of all domains matched.
+
+  :param SuffixMatchNode smb: The SuffixMatchNode to match on
+  :param bool quiet: Do not return the list of matched domains. Default is false.
+
+.. function:: TCPRule([tcp])
+
+  Matches question received over TCP if ``tcp`` is true, over UDP otherwise.
+
+  :param bool tcp: Match TCP traffic. Default is true.
+
+.. function:: TrailingDataRule()
+
+  Matches if the query has trailing data.
+
+Combining Rules
+~~~~~~~~~~~~~~~
+
+.. function:: andRule(selectors)
+
+  Matches traffic if all ``selectors`` match.
+
+  :param {Rule} selectors: A table of Rules
+
+.. function:: NotRule(selector)
+
+  Matches the traffic if the ``selector`` rule does not match;
+
+  :param Rule selector: A Rule
+
+.. function:: OrRule(selectors)
+
+  Matches the traffic if one or more of the the ``selectors`` Rules does match.
+
+  :param {Rule} selector: A table of Rules
+
+Convience Functions
+~~~~~~~~~~~~~~~~~~~
+
+.. function:: makeRule(rule)
+
+  Make a :func:`NetmaskGroupRule` or a :func:`SuffixMatchNodeRule`, depending on it is called.
+  ``makeRule("0.0.0.0/0")`` will for example match all IPv4 traffic, ``makeRule({"be","nl","lu"})`` will match all Benelux DNS traffic.
+
+  :param string rule: A string to convert to a rule.
+
+
+Actions
+-------
+
+:ref:`RulesIntro` need to be combined with an action for them to actually do something with the matched packets.
+Some actions allow further processing of rules, this is noted in their description.
+The following actions exist.
+
+.. function:: AllowAction()
+
+  Let these packets go through.
+
+.. function:: AllowResponseAction()
+
+  Let these packets go through.
+
+.. function:: DelayAction(milliseconds)
+
+  Delay the response by the specified amount of milliseconds (UDP-only).
+  Subsequent rules are processed after this rule.
+
+  :param int milliseconds: The amount of milliseconds to delay the response
+
+.. function:: DelayResponseAction(milliseconds)
+
+  Delay the response by the specified amount of milliseconds (UDP-only).
+  Subsequent rules are processed after this rule.
+
+  :param int milliseconds: The amount of milliseconds to delay the response
+
+.. function:: DisableECSAction()
+
+  Disable the sending of ECS to the backend.
+  Subsequent rules are processed after this rule.
+
+.. function:: DisableValidationAction()
+
+  Set the CD bit in the query and let it go through.
+
+.. function:: DropAction()
+
+  Drop the packet.
+
+.. function:: DropResponseAction()
+
+  Drop the packet.
+
+.. function:: ECSOverrideAction(override)
+
+  Whether an existing EDNS Client Subnet value should be overridden (true) or not (false).
+  Subsequent rules are processed after this rule.
+
+  :param bool override: Whether or not to override ECS value
+
+.. function:: ECSPrefixLengthAction(v4, v6)
+
+  Set the ECS prefix length.
+  Subsequent rules are processed after this rule.
+
+  :param int v4: The IPv4 netmask length
+  :param int v6: The IPv6 netmask length
+
+.. function:: LogAction([filename[, binary[, append[, buffered]]]])
+
+  Log a line for each query, to the specified ``file`` if any, to the console (require verbose) otherwise.
+  When logging to a file, the ``binary`` optional parameter specifies whether we log in binary form (default) or in textual form.
+  The ``append`` optional parameter specifies whether we open the file for appending or truncate each time (default).
+  The ``buffered`` optional parameter specifies whether writes to the file are buffered (default) or not.
+  Subsequent rules are processed after this rule.
+
+  :param string filename: File to log to
+  :param bool binary: Do binary logging. Default true
+  :param bool append: Append to the log. Default false
+  :param bool buffered: Use buffered I/O. default true
+
+.. function:: MacAddrAction(option)
+
+  Add the source MAC address to the query as EDNS0 option ``option``.
+  This action is currently only supported on Linux.
+  Subsequent rules are processed after this rule.
+
+  :param int option: The EDNS0 option number
+
+.. function:: NoneAction()
+
+  Does nothing.
+  Subsequent rules are processed after this rule.
+
+.. function:: NoRecurseAction()
+
+  Strip RD bit from the question, let it go through.
+  Subsequent rules are processed after this rule.
+
+.. function:: PoolAction(poolname)
+
+  Send the packet into the specified pool.
+
+  :param string poolname: The name of the pool
+
+.. function:: QPSPoolAction(maxqps, poolname)
+
+  Send the packet into the specified pool only if it does not exceed the ``maxqps`` queries per second limits.
+  Letting the subsequent rules apply otherwise.
+
+  :param int maxqps: The QPS limit for that pool
+  :param string poolname: The name of the pool
+
+.. function:: RCodeAction(rcode)
+
+  Reply immediatly by turning the query into a response with the specified ``rcode``.
+  ``rcode`` can be specified as an integer or as one of the built-in `RCode <#rcode>`_.
+
+  :param int rcode: The RCODE to respond with.
+
+.. function:: RemoteLogAction(remoteLogger[, alterFunction])
+
+  Send the content of this query to a remote logger via Protocol Buffer.
+  ``alterFunction`` is a callback, receiving a :class:`DNSQuestion` and a :class:`DNSDistProtoBufMessage`, that can be used to modify the Protocol Buffer content, for example for anonymization purposes
+
+  :param string remoteLogger: An IP:PORT combo to send the remote log to
+  :param string alterFunction: Name of a function to modify the contents of the logs before sending
+
+.. function:: RemoteLogResponseAction(remoteLogger[, alterFunction[, includeCNAME]])
+
+  Send the content of this response to a remote logger via Protocol Buffer.
+  ``alterFunction`` is the same callback that receiving a :class:`DNSQuestion` and a :class:`DNSDistProtoBufMessage`, that can be used to modify the Protocol Buffer content, for example for anonymization purposes
+  ``includeCNAME`` indicates whether CNAME records inside the response should be parsed and exported.
+  The default is to only exports A and AAAA records
+
+  :param string remoteLogger: An IP:PORT combo to send the remote log to
+  :param string alterFunction: Name of a function to modify the contents of the logs before sending
+  :param bool includeCNAME: Whether or not to parse and export CNAMEs. Default false
+
+.. function:: SkipCacheAction()
+
+  Don't lookup the cache for this query, don't store the answer.
+
+.. function:: SNMPTrapAction([message])
+
+  Send an SNMP trap, adding the optional ``message`` string as the query description.
+  Subsequent rules are processed after this rule.
+
+  :param string message: The message to include
+
+.. function:: SNMPTrapResponseAction([message])
+
+  Send an SNMP trap, adding the optional ``message`` string as the query description.
+  Subsequent rules are processed after this rule.
+
+  :param string message: The message to include
+
+.. function:: SpoofAction(ip[, ip[...]])
+              SpoofAction(ips)
+
+  Forge a response with the specified IPv4 (for an A query) or IPv6 (for an AAAA) addresses.
+  If you specify multiple addresses, all that match the query type (A, AAAA or ANY) will get spoofed in.
+
+  :param string ip: An IPv4 and/or IPv6 address to spoof
+  :param {string} ips: A table of IPv4 and/or IPv6 addresses to spoof
+
+.. function:: SpoofCNAMEAction(cname)
+
+  Forge a response with the specified CNAME value.
+
+  :param string cname: The name to respond with
+
+.. function:: TCAction()
+
+  Create answer to query with TC and RD bits set, to force the client to TCP.
+
+.. function:: TeeAction(remote[, addECS])
+
+  Send copy of query to ``remote``, keep stats on responses.
+  If ``addECS`` is set to true, EDNS Client Subnet information will be added to the query.
+
+  :param string remote: An IP:PORT conbination to send the copied queries to
+  :param bool addECS: Whether or not to add ECS information. Default false
+
+
diff --git a/pdns/dnsdistdist/docs/running.rst b/pdns/dnsdistdist/docs/running.rst
new file mode 100644 (file)
index 0000000..915882a
--- /dev/null
@@ -0,0 +1,37 @@
+Running and Configuring dnsdist
+===============================
+
+dnsdist is meant to run as a daemon.
+As such, distribution native packages know how to stop/start themselves using operating system services.
+
+It is configured with a configuration file called ``dnsdist.conf``
+The default path to this file is determined by the ``SYSCONFDIR`` variable during compilation.
+Most likely this path is ``/etc/dnsdist``,  ``/etc`` or ``/usr/local/etc/``, dnsdist will tell you on startup which file it reads.
+
+dnsdist is designed to (re)start almost instantly.
+But to prevent downtime when changing configuration, the console (see :ref:`Console`) can be used for live configuration.
+
+Issueing :func:`delta` on the console will print the changes to the configuration that have been made since startup::
+
+  > delta()
+  -- Wed Feb 22 2017 11:31:44 CET
+  addLocal('127.0.0.1:5301', false)
+  -- Wed Feb 22 2017 12:03:48 CET
+  addACL('2.0.0.0/8')
+  -- Wed Feb 22 2017 12:03:50 CET
+  addACL('2.0.0.0/8')
+  -- Wed Feb 22 2017 12:03:51 CET
+  addACL('2.0.0.0/8')
+  -- Wed Feb 22 2017 12:05:51 CET
+  addACL('2001:db8::1')
+
+These commands can be copied to the configuration file, should they need to persist after a restart.
+
+Running as unprivileged user
+----------------------------
+
+:program:`dnsdist` can drop privileges using the ``--uid`` and ``--gid`` command line switches
+to ensure it does not run with root privileges after binding its listening sockets.
+It is highly recommended to create a system user and group for :program:`dnsdist`. Note that
+most packaged versions of :program:`dnsdist` already create this user.
+
diff --git a/pdns/dnsdistdist/docs/statistics.rst b/pdns/dnsdistdist/docs/statistics.rst
new file mode 100644 (file)
index 0000000..53d18a1
--- /dev/null
@@ -0,0 +1,121 @@
+Statistics
+==========
+
+dnsdist keeps statistics on the queries is receives and send out.
+
+acl-drops
+---------
+The number of packets dropped bacause of the :doc:`ACL <advanced/acl>`.
+
+cache-hits
+----------
+Number of times an answer was retrieved from :doc:`cache <guides/cache>`.
+
+cache-misses
+------------
+Number of times an answer was not found in the :doc:`cache <guides/cache>`.
+
+cpu-sys-msec
+------------
+Miliseconds spent by :program:`dnsdist` in the "system" state.
+
+cpu-user-msec
+-------------
+Miliseconds spent by :program:`dnsdist` in the "user" state.
+
+downstream-send-errors
+----------------------
+
+downstream-timeouts
+-------------------
+
+dyn-block-nmg-size
+------------------
+
+dyn-blocked
+-----------
+
+empty-queries
+-------------
+
+fd-usage
+--------
+
+latency-avg100
+--------------
+Average response latency of the last 100 packets.
+
+latency-avg1000
+---------------
+Average response latency of the last 1000 packets.
+
+latency-avg10000
+----------------
+Average response latency of the last 10000 packets.
+
+latency-avg1000000
+------------------
+Average response latency of the last 1000000 packets.
+
+latency-slow
+------------
+
+latency0-1
+----------
+
+latency1-10
+-----------
+
+latency10-50
+------------
+
+latency50-100
+-------------
+
+latency100-1000
+---------------
+
+no-policy
+---------
+
+noncompliant-queries
+--------------------
+
+noncompliant-responses
+----------------------
+
+queries
+-------
+Number of received queries.
+
+rdqueries
+---------
+Number of received queries with the recursion desired bit set.
+
+real-memory-usage
+-----------------
+
+responses
+---------
+
+rule-drop
+---------
+
+rule-nxdomain
+-------------
+
+rule-refused
+------------
+
+self-answered
+-------------
+
+servfail-responses
+------------------
+
+trunc-failures
+--------------
+
+uptime
+------
+
diff --git a/pdns/dnsdistdist/docs/upgrade_guide.rst b/pdns/dnsdistdist/docs/upgrade_guide.rst
new file mode 100644 (file)
index 0000000..bf2b96e
--- /dev/null
@@ -0,0 +1,12 @@
+Upgrade Guide
+=============
+
+1.1.0 to 1.2.0
+--------------
+
+In 1.2.0, several configuration options have been changed:
+
+As the amount of possible settings for listen sockets is growing, all listen-related options must now be passed as a table as the second argument to both :func:`addLocal` and :func:`setLocal`.
+See the function's reference for more information.
+
+The ``BlockFilter`` function is removed, as :func:`addRule` combined with a :func:`DropAction` can do the same.
diff --git a/pdns/dnsdistdist/introduction.md b/pdns/dnsdistdist/introduction.md
deleted file mode 100644 (file)
index c1876fb..0000000
+++ /dev/null
@@ -1,95 +0,0 @@
-dnsdist introduction
---------------------
-`dnsdist` is a highly DNS-, DoS- and abuse-aware loadbalancer. Its goal in
-life is to route traffic to the best server, delivering top performance
-to legitimate users while shunting or blocking abusive traffic.
-
-`dnsdist` is dynamic, in the sense that its configuration can be changed at
-runtime, and that its statistics can be queried from a console-like
-interface.
-
-Concepts
---------
-dnsdist receives packets in one or several addresses it listens on. These
-addresses can of course be IPv4 or IPv6 (dnsdist internally does not know
-the difference). If you listen on the magic 0.0.0.0 or :: interfaces,
-dnsdist does the right thing to set the return address of queries. So feel
-free to listen on the ANY addresses.
-
-By default, the program listens on 127.0.0.1 (not ::1!), port 53.
-
-Before packets are processed they have to pass the ACL, which helpfully
-defaults to RFC1918 private IP space. This prevents us from easily becoming
-an open DNS resolver.
-
-To add to the ACL, use one or more lines like: `addACL("130.161.0.0/16")`.
-To change the listen address, pass `-l 130.161.252.29` on the command line,
-or use one or more `addLocal("130.161.252.29")` lines.
-
-Packet actions
---------------
-Each packet can be:
-
- * Dropped
- * Turned into an answer directly
- * Forwarded to a downstream server
- * Modified and forwarded to a downstream and be modified back
-
-To add downstream servers, either include them on the command line, like
-this:
-
-```
-# dnsdist -l 130.161.252.29 -a 130.161.0.0/16 8.8.8.8 208.67.222.222 2620:0:ccc::2 2620:0:ccd::2
-```
-
-Or add them to the configuration file like this:
-```
-setLocal("130.161.252.29:53")
-setACL("130.161.0.0/16") 
-newServer("8.8.8.8")
-newServer("208.67.222.222")
-newServer("2620:0:ccc::2")
-newServer("2620:0:0ccd::2")
-```
-
-In the default environment, put this file in `/etc/dnsdist/dnsdist.conf` (or
-`/usr/local/etc/`, dnsdist will tell you on startup), and start dnsdist. 
-
-These two equivalent configurations give you sane load balancing using a
-very sensible distribution policy. Many users will simply be done with this
-configuration. It works as well for authoritative as for recursive servers.
-
-By default it will run on the foreground, add `--daemon` to make it go into
-the background. Our distribution native packages know how to stop/start
-themselves using operating system services.
-
-Console, statistics, webserver
-------------------------------
-To fully benefit from the statistics, metrics and dynamic control, first
-generate an access key:
-
-```
-$ dnsdist
-> makeKey()
-setKey(...)
-```
-
-Then paste that `setKey()` line, next with the following, into your
-dnsdist.conf file:
-
-```
--- paste the setKey() line from above here!
-controlSocket("127.0.0.1") -- for the console
-webserver("127.0.0.1:8083", "geheim2") --  instant webserve
-carbonServer("2001:888:2000:1d::2") -- send our statistics to PowerDNS
-```
-
-Now restart `dnsdist`. Three things have changed now:
-
-1. You can login to a running `dnsdist` daemon with `dnsdist -c`
-2. If you connect to http://127.0.0.1:8083 and enter the password, you get
-live stats
-3. Your metrics will be reported to the public PowerDNS Metronome server
-
-
-
diff --git a/pdns/dnsdistdist/m4/pdns_check_pandoc.m4 b/pdns/dnsdistdist/m4/pdns_check_pandoc.m4
deleted file mode 100644 (file)
index d5069f8..0000000
+++ /dev/null
@@ -1,11 +0,0 @@
-AC_DEFUN([PDNS_CHECK_PANDOC], [
-  AC_CHECK_PROG([PANDOC], [pandoc], [pandoc], [no])
-
-  AS_IF([test "x$PANDOC" = "xno"], [
-    AS_IF([test ! -f "$srcdir/dnsdist.1"],
-      [AC_MSG_WARN([pandoc is missing, unable to build documentation and manpages.])]
-    )
-  ])
-  AM_CONDITIONAL([HAVE_PANDOC], [test "x$PANDOC" != "xno"])
-  AM_CONDITIONAL([HAVE_MANPAGES], [test -e "$srcdir/dnsdist.1"])
-])
diff --git a/pdns/dnsdistdist/m4/pdns_check_virtualenv.m4 b/pdns/dnsdistdist/m4/pdns_check_virtualenv.m4
new file mode 100644 (file)
index 0000000..214d450
--- /dev/null
@@ -0,0 +1,12 @@
+AC_DEFUN([PDNS_CHECK_VIRTUALENV], [
+  AC_CHECK_PROG([VIRTUALENV], [virtualenv], [virtualenv], [no])
+
+  AS_IF([test "x$VIRTUALENV" = "xno"], [
+    AS_IF([test ! -f "$srcdir/dnsdist.1"],
+      [AC_MSG_WARN([virtualenv is missing, unable to build manpages.])]
+    )
+  ])
+  AM_CONDITIONAL([HAVE_VIRTUALENV], [test "x$VIRTUALENV" != "xno"])
+  AM_CONDITIONAL([HAVE_MANPAGES], [test -e "$srcdir/dnsdist.1"])
+])
+
diff --git a/pdns/dnsdistdist/website/.gitignore b/pdns/dnsdistdist/website/.gitignore
deleted file mode 100644 (file)
index 5ccff1a..0000000
+++ /dev/null
@@ -1 +0,0 @@
-html/
diff --git a/pdns/dnsdistdist/website/Makefile b/pdns/dnsdistdist/website/Makefile
deleted file mode 100644 (file)
index 67a91cc..0000000
+++ /dev/null
@@ -1,7 +0,0 @@
-all: html/index.html
-
-html/index.html: markdown/*
-       mkdocs build --clean
-
-upload: html/index.html
-       rsync -cvr --no-p --chmod=g=rwX --exclude '*~' --delete html/* web1.powerdns.com:/srv/www/dnsdist.org/
diff --git a/pdns/dnsdistdist/website/markdown/README.md b/pdns/dnsdistdist/website/markdown/README.md
deleted file mode 120000 (symlink)
index fe84005..0000000
+++ /dev/null
@@ -1 +0,0 @@
-../../README.md
\ No newline at end of file
diff --git a/pdns/dnsdistdist/website/markdown/changelog.md b/pdns/dnsdistdist/website/markdown/changelog.md
deleted file mode 100644 (file)
index f493f7e..0000000
+++ /dev/null
@@ -1,229 +0,0 @@
-# 1.1.0
-Released December 29th 2016
-
-Changes since 1.1.0-beta2:
-
-## Improvements
-
- * [#4783](https://github.com/PowerDNS/pdns/pull/4783): Add -latomic on powerpc 
- * [#4812](https://github.com/PowerDNS/pdns/pull/4812): Handle header-only responses, handle Refused as Servfail in the cache
-
-## Bug fixes
-
- * [#4762](https://github.com/PowerDNS/pdns/pull/4762): SuffixMatchNode: Fix an insertion issue for an existing node 
- * [#4772](https://github.com/PowerDNS/pdns/pull/4772): Fix dnsdist initscript config check 
-
-# 1.1.0-beta2
-Released December 14th 2016
-
-Changes since 1.1.0-beta1:
-
-## New features
-
- * [#4518](https://github.com/PowerDNS/pdns/pull/4518): Fix dynblocks over TCP, allow refusing dyn blocked queries
- * [#4519](https://github.com/PowerDNS/pdns/pull/4519): Allow altering the ECS behavior via rules and Lua
- * [#4535](https://github.com/PowerDNS/pdns/pull/4535): Add `DNSQuestion:getDO()`
- * [#4653](https://github.com/PowerDNS/pdns/pull/4653): `getStatisticsCounters()` to access counters from Lua
- * [#4657](https://github.com/PowerDNS/pdns/pull/4657): Add `includeDirectory(dir)`
- * [#4658](https://github.com/PowerDNS/pdns/pull/4658): Allow editing the ACL via the API
- * [#4702](https://github.com/PowerDNS/pdns/pull/4702): Add `setUDPTimeout(n)`
- * [#4726](https://github.com/PowerDNS/pdns/pull/4726): Add an option to return ServFail when no server is available
- * [#4748](https://github.com/PowerDNS/pdns/pull/4748): Add `setCacheCleaningPercentage()`
-
-## Improvements
-
- * [#4533](https://github.com/PowerDNS/pdns/pull/4533): Fix building with clang on OS X and FreeBSD
- * [#4537](https://github.com/PowerDNS/pdns/pull/4537): Replace luawrapper's std::forward/std::make_tuple combo with std::forward_as_tuple (Sangwhan "fish" Moon)
- * [#4596](https://github.com/PowerDNS/pdns/pull/4596): Change the default max number of queued TCP conns to 1000
- * [#4632](https://github.com/PowerDNS/pdns/pull/4632): Improve dnsdist error message on a common typo/config mistake
- * [#4694](https://github.com/PowerDNS/pdns/pull/4694): Don't use a const_iterator for erasing (fix compilation with some versions of gcc)
- * [#4715](https://github.com/PowerDNS/pdns/pull/4715): Specify that dnsmessage.proto uses protobuf version 2
- * [#4765](https://github.com/PowerDNS/pdns/pull/4765): Some service improvements
-
-## Bug fixes
-
- * [#4425](https://github.com/PowerDNS/pdns/pull/4425): Fix a protobuf regression (requestor/responder mix-up) caused by a94673e
- * [#4541](https://github.com/PowerDNS/pdns/pull/4541): Fix insertion issues in SuffixMatchTree, move it to dnsname.hh
- * [#4553](https://github.com/PowerDNS/pdns/pull/4553): Flush output in single command client mode
- * [#4578](https://github.com/PowerDNS/pdns/pull/4578): Fix destination address reporting
- * [#4640](https://github.com/PowerDNS/pdns/pull/4640): Don't exit dnsdist on an exception in maintenance
- * [#4721](https://github.com/PowerDNS/pdns/pull/4721): Handle exceptions in the UDP responder thread
- * [#4734](https://github.com/PowerDNS/pdns/pull/4734): Add the TCP socket to the map only if the connection succeeds. Closes #4733
- * [#4742](https://github.com/PowerDNS/pdns/pull/4742): Decrement the queued TCP conn count if writing to the pipe fails
- * [#4743](https://github.com/PowerDNS/pdns/pull/4743): Ignore newBPFFilter() and newDynBPFFilter() in client mode
- * [#4753](https://github.com/PowerDNS/pdns/pull/4753): Fix FD leak on TCP connection failure, handle TCP worker creation failure
- * [#4764](https://github.com/PowerDNS/pdns/pull/4764): Prevent race while creating new TCP worker threads
-
-# 1.1.0-beta1
-Released September 1st 2016
-
-Changes since 1.0.0:
-
-## New features
-
- * [#3762](https://github.com/PowerDNS/pdns/pull/3762) Teeaction: send copy of query to second nameserver, sponge responses
- * [#3876](https://github.com/PowerDNS/pdns/pull/3876) Add `showResponseRules()`, `{mv,rm,top}ResponseRule()`
- * [#3936](https://github.com/PowerDNS/pdns/pull/3936) Filter on opcode, records count/type, trailing data
- * [#3975](https://github.com/PowerDNS/pdns/pull/3975) Make dnsdist {A,I}XFR aware, document possible issues
- * [#4006](https://github.com/PowerDNS/pdns/pull/4006) Add eBPF source address and qname/qtype filtering
- * [#4008](https://github.com/PowerDNS/pdns/pull/4008) Node infrastructure for querying recent traffic
- * [#4042](https://github.com/PowerDNS/pdns/pull/4042) Add server-side TCP Fast Open support
- * [#4050](https://github.com/PowerDNS/pdns/pull/4050) Add `clearRules()` and `setRules()`
- * [#4114](https://github.com/PowerDNS/pdns/pull/4114) Add `QNameLabelsCountRule()` and `QNameWireLengthRule()`
- * [#4116](https://github.com/PowerDNS/pdns/pull/4116) Added src boolean to NetmaskGroupRule to match destination address (Reinier Schoof)
- * [#4175](https://github.com/PowerDNS/pdns/pull/4175) Implemented query counting (Reinier Schoof)
- * [#4244](https://github.com/PowerDNS/pdns/pull/4244) Add a `setCD` parameter to set cd=1 on health check queries
- * [#4284](https://github.com/PowerDNS/pdns/pull/4284) Add RCodeRule(), Allow, Delay and Drop response actions
- * [#4305](https://github.com/PowerDNS/pdns/pull/4305) Add an optional Lua callback for altering a Protobuf message
- * [#4309](https://github.com/PowerDNS/pdns/pull/4309) Add showTCPStats function (RobinGeuze)
- * [#4329](https://github.com/PowerDNS/pdns/pull/4329) Add options to LogAction() so it can append (instead of truncate) (Duane Wessels)
-
-## Improvements
-
- * [#3714](https://github.com/PowerDNS/pdns/pull/3714) Add documentation links to dnsdist.service (Ruben Kerkhof)
- * [#3754](https://github.com/PowerDNS/pdns/pull/3754) Allow the use of custom headers in the web server
- * [#3826](https://github.com/PowerDNS/pdns/pull/3826) Implement a 'quiet' mode for SuffixMatchNodeRule()
- * [#3836](https://github.com/PowerDNS/pdns/pull/3836) Log the content of webserver's exceptions
- * [#3858](https://github.com/PowerDNS/pdns/pull/3858) Only log YaHTTP's parser exceptions in verbose mode
- * [#3877](https://github.com/PowerDNS/pdns/pull/3877) Increase max FDs in systemd unit, warn if clearly too low
- * [#4019](https://github.com/PowerDNS/pdns/pull/4019) Add an optional `addECS` option to `TeeAction()`
- * [#4029](https://github.com/PowerDNS/pdns/pull/4029) Add version and feature information to version output
- * [#4079](https://github.com/PowerDNS/pdns/pull/4079) Return an error on RemoteLog{,Response}Action() w/o protobuf
- * [#4246](https://github.com/PowerDNS/pdns/pull/4246) API now sends pools as a JSON array instead of a string
- * [#4302](https://github.com/PowerDNS/pdns/pull/4302) Add `help()` and `showVersion()`
- * [#4286](https://github.com/PowerDNS/pdns/pull/4286) Add response rules to the API and Web status page
- * [#4068](https://github.com/PowerDNS/pdns/pull/4068) Display the dyn eBPF filters stats in the web interface
-
-## Bug fixes
-
- * [#3755](https://github.com/PowerDNS/pdns/pull/3755) Fix RegexRule example in dnsdistconf.lua
- * [#3773](https://github.com/PowerDNS/pdns/pull/3773) Stop copying the HTTP request headers to the response
- * [#3837](https://github.com/PowerDNS/pdns/pull/3837) Remove dnsdist service file on trusty
- * [#3840](https://github.com/PowerDNS/pdns/pull/3840) Catch WrongTypeException in client mode
- * [#3906](https://github.com/PowerDNS/pdns/pull/3906) Keep the servers ordered inside pools
- * [#3988](https://github.com/PowerDNS/pdns/pull/3988) Fix `grepq()` output in the README
- * [#3992](https://github.com/PowerDNS/pdns/pull/3992) Fix some typos in the AXFR/IXFR documentation
- * [#3995](https://github.com/PowerDNS/pdns/pull/3995) Fix comparison between signed and unsigned integer
- * [#4049](https://github.com/PowerDNS/pdns/pull/4049) Fix dnsdist rpm building script #4048 (Daniel Stirnimann)
- * [#4065](https://github.com/PowerDNS/pdns/pull/4065) Include editline/readline.h instead of readline.h/history.h
- * [#4067](https://github.com/PowerDNS/pdns/pull/4067) Disable eBPF support when BPF_FUNC_tail_call is not found
- * [#4069](https://github.com/PowerDNS/pdns/pull/4069) Fix a buffer overflow when displaying an OpcodeRule
- * [#4101](https://github.com/PowerDNS/pdns/pull/4101) Fix $ expansion in build-dnsdist-rpm
- * [#4198](https://github.com/PowerDNS/pdns/pull/4198) newServer setting maxCheckFailures makes no sense (stutiredboy)
- * [#4205](https://github.com/PowerDNS/pdns/pull/4205) Prevent the use of "any" addresses for downstream server
- * [#4220](https://github.com/PowerDNS/pdns/pull/4220) Don't log an error when parsing an invalid UDP query
- * [#4348](https://github.com/PowerDNS/pdns/pull/4348) Fix invalid outstanding count for {A,I}XFR over TCP
- * [#4365](https://github.com/PowerDNS/pdns/pull/4365) Reset origFD asap to keep the outstanding count correct
- * [#4375](https://github.com/PowerDNS/pdns/pull/4375) Tuple requires make_tuple to initialize
- * [#4380](https://github.com/PowerDNS/pdns/pull/4380) Fix compilation with clang when eBPF support is enabled
-
-# dnsdist 1.0.0
-Released April 21st 2016
-
-Changes since 1.0.0-beta1:
-
-## Improvements
-
- * [#3700](https://github.com/PowerDNS/pdns/pull/3700) Create user from the RPM package to drop privs
- * [#3712](https://github.com/PowerDNS/pdns/pull/3712) Make check should run testrunner
- * [#3713](https://github.com/PowerDNS/pdns/pull/3713) Remove contrib/dnsdist.service (Ruben Kerkhof)
- * [#3722](https://github.com/PowerDNS/pdns/pull/3722) Use LT_INIT and disable static objects (Ruben Kerkhof)
- * [#3724](https://github.com/PowerDNS/pdns/pull/3724) Include PDNS_CHECK_OS in configure (Christian Hofstaedtler)
- * [#3728](https://github.com/PowerDNS/pdns/pull/3728) Document libedit Ctrl-R workaround for CentOS 6
- * [#3730](https://github.com/PowerDNS/pdns/pull/3730) Make `topBandwidth()` behave like other top* functions
- * [#3731](https://github.com/PowerDNS/pdns/pull/3731) Clarify a bit the documentation of load-balancing policies
-
-## Bug fixes
-
- * [#3711](https://github.com/PowerDNS/pdns/pull/3711) Building rpm needs systemd headers (Ruben Kerkhof)
- * [#3736](https://github.com/PowerDNS/pdns/pull/3736) Add missing Lua binding for NetmaskGroupRule()
- * [#3739](https://github.com/PowerDNS/pdns/pull/3739) Drop privileges after daemonizing and writing our pid
-
-# dnsdist 1.0.0-beta1
-Released April 14th 2016
-
-Changes since 1.0.0-alpha2:
-
-## New features
-
- * Per-pool packet cache
- * Some actions do not stop the processing anymore when they match, allowing more complex setups: Delay, Disable Validation, Log, MacAddr, No Recurse and of course None
- * The new RE2Rule() is available, using the RE2 regular expression library to match queries, in addition to the existing POSIX-based RegexRule()
- * SpoofAction() now supports multiple A and AAAA records
- * Remote logging of questions and answers via Protocol Buffer
-
-## Improvements
-
- * [#3405](https://github.com/PowerDNS/pdns/pull/3405) Add health check logging, `maxCheckFailures` to backend
- * [#3412](https://github.com/PowerDNS/pdns/pull/3412) Check config
- * [#3440](https://github.com/PowerDNS/pdns/pull/3440) Client operation improvements
- * [#3466](https://github.com/PowerDNS/pdns/pull/3466) Add dq binding for skipping packet cache in LuaAction (Jan Broer)
- * [#3499](https://github.com/PowerDNS/pdns/pull/3499) Add support for multiple carbon servers
- * [#3504](https://github.com/PowerDNS/pdns/pull/3504) Allow accessing the API with an optional API key
- * [#3556](https://github.com/PowerDNS/pdns/pull/3556) Add an option to limit the number of queued TCP connections
- * [#3578](https://github.com/PowerDNS/pdns/pull/3578) Add a `disable-syslog` option
- * [#3608](https://github.com/PowerDNS/pdns/pull/3608) Export cache stats to carbon
- * [#3622](https://github.com/PowerDNS/pdns/pull/3622) Display the ACL content on startup
- * [#3627](https://github.com/PowerDNS/pdns/pull/3627) Remove ECS option from response's OPT RR when necessary
- * [#3633](https://github.com/PowerDNS/pdns/pull/3633) Count "TTL too short" cache events
- * [#3677](https://github.com/PowerDNS/pdns/pull/3677) systemd-notify support
-
-## Bug fixes
-
- * [#3388](https://github.com/PowerDNS/pdns/pull/3388) Lock the Lua context before executing a LuaAction
- * [#3433](https://github.com/PowerDNS/pdns/pull/3433) Check that the answer matches the initial query
- * [#3461](https://github.com/PowerDNS/pdns/pull/3461) Fix crash when calling rmServer() with an invalid index
- * [#3550](https://github.com/PowerDNS/pdns/pull/3550),[#3551](https://github.com/PowerDNS/pdns/pull/3551) Fix build failure on FreeBSD (Ruben Kerkhof)
- * [#3594](https://github.com/PowerDNS/pdns/pull/3594) Prevent EOF error for empty console response w/o sodium
- * [#3634](https://github.com/PowerDNS/pdns/pull/3634) Prevent dangling TCP fd in case setupTCPDownstream() fails
- * [#3641](https://github.com/PowerDNS/pdns/pull/3641) Under threshold, QPS action should return None, not Allow
- * [#3658](https://github.com/PowerDNS/pdns/pull/3658) Fix a race condition in MaxQPSIPRule
-
-
-# dnsdist 1.0.0-alpha2
-Released February 5th 2016
-
-Changes since 1.0.0-alpha1:
-
-## New features
-
- * Lua functions now receive a DNSQuestion `dq` object instead of several parameters. This adds a greater compatibility with PowerDNS and allows adding more parameters without breaking the API ([#3198](https://github.com/PowerDNS/pdns/issues/3198))
- * Added a `source` option to `newServer()` to specify the local address or interface used to contact a downstream server ([#3138](https://github.com/PowerDNS/pdns/issues/3138))
- * CNAME and IPv6-only support have been added to spoofed responses ([#3064](https://github.com/PowerDNS/pdns/issues/3064))
- * `grepq()` can be used to search for slow queries, along with `topSlow()`
- * New Lua functions: `addDomainCNAMESpoof()`, `AllowAction()` by @bearggg, `exceedQRate()`, `MacAddrAction()`, `makeRule()`, `NotRule()`, `OrRule()`, `QClassRule()`, `RCodeAction()`, `SpoofCNAMEAction()`, `SuffixMatchNodeRule()`, `TCPRule()`, `topSlow()`
- * `NetmaskGroup` support have been added in Lua ([#3144](https://github.com/PowerDNS/pdns/issues/3144))
- * Added `MacAddrAction()` to add the source MAC address to the forwarded query ([#3313](https://github.com/PowerDNS/pdns/issues/3313))
-
-## Bug fixes
-
- * An issue in DelayPipe could make dnsdist crash at startup
- * `downstream-timeouts` metric was not always updated
- * `truncateTC` was unproperly updating the response length ([#3126](https://github.com/PowerDNS/pdns/issues/3126))
- * DNSCrypt responses larger than queries were unproperly truncated
- * An issue prevented info message from being displayed in non-verbose mode, fixed by Jan Broer
- * Reinstating an expired Dynamic Rule was not correctly logged ([#3323](https://github.com/PowerDNS/pdns/issues/3323))
- * Initialized counters in the TCP client thread might have cause FD and memory leak, reported by Martin Pels ([#3300](https://github.com/PowerDNS/pdns/issues/3300))
- * We now drop queries containing no question (qdcount == 0) ([#3290](https://github.com/PowerDNS/pdns/issues/3290))
- * Outstanding TCP queries count was not always correct ([#3288](https://github.com/PowerDNS/pdns/issues/3288))
- * A locking issue in exceedRespGen() might have caused crashs ([#3277](https://github.com/PowerDNS/pdns/issues/3277))
- * Useless sockets were created in client mode ([#3257](https://github.com/PowerDNS/pdns/issues/3257))
- * `addAnyTCRule()` was generating TC=1 responses even over TCP ([#3251](https://github.com/PowerDNS/pdns/issues/3251))
-
-## Web interface
- * Cleanup of the HTML by Sander Hoentjen
- * Fixed an XSS reported by @janeczku ([#3217](https://github.com/PowerDNS/pdns/issues/3217))
- * Removed remote images
- * Set the charset to UTF-8, added some security-related and CORS HTTP headers
- * Added server latency by Jan Broer ([#3201](https://github.com/PowerDNS/pdns/issues/3201))
- * Switched to official minified versions of JS scripts, by Sander Hoentjen ([#3317](https://github.com/PowerDNS/pdns/issues/3317))
- * Don't log unauthenticated HTTP request as an authentication failure 
-
-## Various documentation updates and minor cleanups:
- * Added documentation for Advanced DNS Protection features (Dynamic rules, `maintenance()`)
- * Make `topBandwidth()` default to the top 10 clients
- * Replaced readline with libedit
- * Added GPL2 License ([#3200](https://github.com/PowerDNS/pdns/issues/3200))
- * Added incbin License ([#3269](https://github.com/PowerDNS/pdns/issues/3269))
- * Updated completion rules
- * Removed wrong option `--daemon-no` by Stefan Schmidt
diff --git a/pdns/dnsdistdist/website/markdown/dnsdist.1.md b/pdns/dnsdistdist/website/markdown/dnsdist.1.md
deleted file mode 120000 (symlink)
index 5c0729d..0000000
+++ /dev/null
@@ -1 +0,0 @@
-../../dnsdist.1.md
\ No newline at end of file
diff --git a/pdns/dnsdistdist/website/markdown/download.md b/pdns/dnsdistdist/website/markdown/download.md
deleted file mode 100644 (file)
index 045223a..0000000
+++ /dev/null
@@ -1,43 +0,0 @@
-# Download dnsdist
-dnsdist is distributed in several forms, pick the method best suited for your environment.
-
-## Packages
-dnsdist is not (yet) widely available as a package for your operating system
-distribution. However, several packages are available in [our repository](https://repo.powerdns.com/).
-dnsdist is known to be available on FreeBSD ports (dns/dnsdist).
-Freshports link: http://www.freshports.org/dns/dnsdist/ 
-
-## From Source
-To build dnsdist, you'll need a modern C++ compiler with C++ 2011 support (like
-GCC 4.8+ or clang 3.5+), GNU Make and the following libraries:
-
-* [Boost](http://boost.org)
-* [Lua](http://www.lua.org/) 5.1+ or [LuaJit](http://luajit.org/)
-* Optionally: [libsodium](https://download.libsodium.org/doc/)
-* Optionally: [protobuf](https://developers.google.com/protocol-buffers/)
-* Optionally: [re2](https://github.com/google/re2)
-
-To compile from git, these additional dependencies are required:
-
- * GNU [Autoconf](http://www.gnu.org/software/autoconf/autoconf.html)
- * GNU [Automake](https://www.gnu.org/software/automake/)
- * [Pandoc](http://pandoc.org/)
- * [Ragel](http://www.colm.net/open-source/ragel/)
-
-### Tarballs
-Release tarballs are available [here](https://downloads.powerdns.com/releases) and
-snapshot tarballs are available [here](https://downloads.powerdns.com/autobuilt/dnsdist/dist/).
-
- * Untar the tarball
- * `./configure`
- * `make`
-
-## From git
-dnsdist can be built from the [PowerDNS repository](https://github.com/PowerDNS/pdns/)
-(but is independent of PowerDNS)
-
- * `git clone https://github.com/PowerDNS/pdns.git`
- * `cd pdns/pdns/dnsdistdist`
- * `autoreconf -i`
- * `./configure`
- * `make`
diff --git a/pdns/dnsdistdist/website/markdown/extra.css b/pdns/dnsdistdist/website/markdown/extra.css
deleted file mode 100644 (file)
index ffcefb7..0000000
+++ /dev/null
@@ -1,5 +0,0 @@
-/* Allow scrolling of H1...n sidebar */
-.bs-sidebar {
-  overflow: scroll;
-  max-height: 80%;
-}
diff --git a/pdns/dnsdistdist/website/markdown/img/powerdns-dnsdist-live.gif b/pdns/dnsdistdist/website/markdown/img/powerdns-dnsdist-live.gif
deleted file mode 100644 (file)
index 8b1cfd8..0000000
Binary files a/pdns/dnsdistdist/website/markdown/img/powerdns-dnsdist-live.gif and /dev/null differ
diff --git a/pdns/dnsdistdist/website/markdown/index.md b/pdns/dnsdistdist/website/markdown/index.md
deleted file mode 100644 (file)
index fa1f595..0000000
+++ /dev/null
@@ -1,37 +0,0 @@
-<center>
-![PowerDNS Logo](img/powerdns-logo-500px.png)
-<br/>
-
-# dnsdist
-</center>
-<blockquote>
-"dnsdist is a highly DNS-, DoS- and abuse-aware loadbalancer. Its goal in life is to route traffic to the best server, delivering top performance to legitimate users while shunting or blocking abusive traffic."
-</blockquote>
-
-<iframe width="640" height="360" src="https://www.youtube.com/embed/5abqhVfJFhg?list=PLjzK5ZtLlc91r5YZVNiebhcq0W5aB5Zu6" frameborder="0" allowfullscreen></iframe>
-
-See [here](http://blog.powerdns.com/2015/03/11/introducing-dnsdist-dns-abuse-and-dos-aware-query-distribution-for-optimal-performance/)
-for an introduction to dnsdist. Or view the sample [configuration file](https://github.com/PowerDNS/pdns/blob/master/pdns/dnsdistconf.lua).
-The [documentation](README.md) may also be interesting.
-Finally, the DNS-OARC presentation is [here](https://indico.dns-oarc.net/event/21/contribution/20/material/slides/0.pdf)
-([VIDEO!](https://www.youtube.com/watch?feature=player_embedded&v=PX3YYmBER7E#t=6403)).
-
-# Getting dnsdist
-Grab the latest 1.1 release or development packages from [our
-repositories](https://repo.powerdns.com).  The announcement of 1.1.0 is
-[here](https://blog.powerdns.com/2016/12/29/dnsdist-1-1-0-released/).
-
-## Compiling dnsdist
-Prefer to compile yourself? Checkout the instructions on [the download page](download.md).
-
-# License
-dnsdist is licensed under the GNU General Public License, version 2
-
-# Questions, requests or comments?
-There are several ways to reach us:
-
- * The [dnsdist mailing-list](https://mailman.powerdns.com/mailman/listinfo/dnsdist)
- * \#powerdns on [irc.oftc.net](irc://irc.oftc.net/#powerdns)
-
-If you require commercial support, please see the [PowerDNS.com website](https://powerdns.com)
-or email us at [powerdns.support.sales@powerdns.com](mailto:powerdns.support.sales@powerdns.com).
diff --git a/pdns/dnsdistdist/website/markdown/introduction.md b/pdns/dnsdistdist/website/markdown/introduction.md
deleted file mode 120000 (symlink)
index d8e1b60..0000000
+++ /dev/null
@@ -1 +0,0 @@
-../../introduction.md
\ No newline at end of file
diff --git a/pdns/dnsdistdist/website/markdown/screenshots.md b/pdns/dnsdistdist/website/markdown/screenshots.md
deleted file mode 100644 (file)
index 40254ef..0000000
+++ /dev/null
@@ -1,5 +0,0 @@
-# Screenshots
-## The built-in webserver
-With live statistics
-
-![dnsdist webserver](img/powerdns-dnsdist-live.gif)
diff --git a/pdns/dnsdistdist/website/mkdocs.yml b/pdns/dnsdistdist/website/mkdocs.yml
deleted file mode 100644 (file)
index 38416c7..0000000
+++ /dev/null
@@ -1,16 +0,0 @@
-site_name: dnsdist
-repo_url: https://github.com/PowerDNS/pdns
-docs_dir: markdown
-site_dir: html
-theme: bootstrap
-extra_css: [extra.css]
-pages:
-  - dnsdist:
-    - Homepage: index.md
-    - Introduction: introduction.md
-    - Screenshots: screenshots.md
-  - Download: download.md
-  - Changelog: changelog.md
-  - Documentation:
-    - All documentation: README.md
-    - dnsdist.1 manpage: dnsdist.1.md