]> granicus.if.org Git - pdns/commitdiff
rec: Add SNMP support
authorRemi Gacogne <remi.gacogne@powerdns.com>
Mon, 5 Dec 2016 15:01:00 +0000 (16:01 +0100)
committerRemi Gacogne <remi.gacogne@powerdns.com>
Mon, 6 Feb 2017 13:52:19 +0000 (14:52 +0100)
16 files changed:
docs/MIBS/RECURSOR-MIB.txt [new file with mode: 0644]
docs/markdown/recursor/scripting.md
docs/markdown/recursor/settings.md
pdns/lua-recursor4.cc
pdns/pdns_recursor.cc
pdns/rec-snmp.cc [new file with mode: 0644]
pdns/rec-snmp.hh [new file with mode: 0644]
pdns/rec_channel.hh
pdns/rec_channel_rec.cc
pdns/recursordist/Makefile.am
pdns/recursordist/configure.ac
pdns/recursordist/m4/pdns_with_net_snmp.m4 [new symlink]
pdns/recursordist/rec-snmp.cc [new symlink]
pdns/recursordist/rec-snmp.hh [new symlink]
pdns/recursordist/snmp-agent.cc [new symlink]
pdns/recursordist/snmp-agent.hh [new symlink]

diff --git a/docs/MIBS/RECURSOR-MIB.txt b/docs/MIBS/RECURSOR-MIB.txt
new file mode 100644 (file)
index 0000000..ccbacf8
--- /dev/null
@@ -0,0 +1,908 @@
+-- -*- snmpv2 -*-
+-- ----------------------------------------------------------------------
+-- MIB file for PowerDNS Recursor
+-- ----------------------------------------------------------------------
+
+PDNSRECURSOR-MIB DEFINITIONS ::= BEGIN
+
+IMPORTS
+    OBJECT-TYPE, MODULE-IDENTITY, enterprises,
+    Counter64, NOTIFICATION-TYPE
+        FROM SNMPv2-SMI
+    CounterBasedGauge64
+        FROM HCNUM-TC
+    OBJECT-GROUP, MODULE-COMPLIANCE, NOTIFICATION-GROUP
+        FROM SNMPv2-CONF;
+
+rec MODULE-IDENTITY
+    LAST-UPDATED "201611290000Z"
+    ORGANIZATION "PowerDNS BV"
+    CONTACT-INFO "support@powerdns.com"
+    DESCRIPTION
+       "This MIB module describes information gathered through PowerDNS Recursor."
+
+    REVISION "201611290000Z"
+    DESCRIPTION "Initial revision."
+
+    ::= { powerdns 2 }
+
+powerdns               OBJECT IDENTIFIER ::= { enterprises 43315 }
+
+stats OBJECT IDENTIFIER ::= { rec 1 }
+
+questions OBJECT-TYPE
+    SYNTAX Counter64
+    MAX-ACCESS read-only
+    STATUS current
+    DESCRIPTION
+        "Number of questions"
+    ::= { stats 1 }
+
+ipv6Questions OBJECT-TYPE
+    SYNTAX Counter64
+    MAX-ACCESS read-only
+    STATUS current
+    DESCRIPTION
+        "Number of IPv6 questions"
+    ::= { stats 2 }
+
+tcpQuestions OBJECT-TYPE
+    SYNTAX Counter64
+    MAX-ACCESS read-only
+    STATUS current
+    DESCRIPTION
+        "Number of TCP questions"
+    ::= { stats 3 }
+
+cacheHits OBJECT-TYPE
+    SYNTAX Counter64
+    MAX-ACCESS read-only
+    STATUS current
+    DESCRIPTION
+        "Number of cache hits"
+    ::= { stats 4 }
+
+cacheMisses OBJECT-TYPE
+    SYNTAX Counter64
+    MAX-ACCESS read-only
+    STATUS current
+    DESCRIPTION
+        "Number of cache misses"
+    ::= { stats 5 }
+
+cacheEntries OBJECT-TYPE
+    SYNTAX CounterBasedGauge64
+    MAX-ACCESS read-only
+    STATUS current
+    DESCRIPTION
+        "Number of cache entries"
+    ::= { stats 6 }
+
+cacheBytes OBJECT-TYPE
+    SYNTAX CounterBasedGauge64
+    MAX-ACCESS read-only
+    STATUS current
+    DESCRIPTION
+        "Size of the cache in bytes"
+    ::= { stats 7 }
+
+packetcacheHits OBJECT-TYPE
+    SYNTAX Counter64
+    MAX-ACCESS read-only
+    STATUS current
+    DESCRIPTION
+        "Number of packetcache hits"
+    ::= { stats 8 }
+
+packetcacheMisses OBJECT-TYPE
+    SYNTAX Counter64
+    MAX-ACCESS read-only
+    STATUS current
+    DESCRIPTION
+        "Number of packetcache misses"
+    ::= { stats 9 }
+
+packetcacheEntries OBJECT-TYPE
+    SYNTAX CounterBasedGauge64
+    MAX-ACCESS read-only
+    STATUS current
+    DESCRIPTION
+        "Number of packetcache entries"
+    ::= { stats 10 }
+
+packetcacheBytes OBJECT-TYPE
+    SYNTAX CounterBasedGauge64
+    MAX-ACCESS read-only
+    STATUS current
+    DESCRIPTION
+        "Size of the packetcache in bytes"
+    ::= { stats 11 }
+
+mallocBytes OBJECT-TYPE
+    SYNTAX CounterBasedGauge64
+    MAX-ACCESS read-only
+    STATUS current
+    DESCRIPTION
+        "Number of bytes allocated by malloc"
+    ::= { stats 12 }
+
+servfailAnswers OBJECT-TYPE
+    SYNTAX Counter64
+    MAX-ACCESS read-only
+    STATUS current
+    DESCRIPTION
+        "Number of servfail answers"
+    ::= { stats 13 }
+
+nxdomainAnswers OBJECT-TYPE
+    SYNTAX Counter64
+    MAX-ACCESS read-only
+    STATUS current
+    DESCRIPTION
+        "Number of nxdomain answers"
+    ::= { stats 14 }
+
+noerrorAnswers OBJECT-TYPE
+    SYNTAX Counter64
+    MAX-ACCESS read-only
+    STATUS current
+    DESCRIPTION
+        "Number of noerror answers"
+    ::= { stats 15 }
+
+unauthorizedUdp OBJECT-TYPE
+    SYNTAX Counter64
+    MAX-ACCESS read-only
+    STATUS current
+    DESCRIPTION
+        "Number of unauthorized UDP queries"
+    ::= { stats 16 }
+
+unauthorizedTcp OBJECT-TYPE
+    SYNTAX Counter64
+    MAX-ACCESS read-only
+    STATUS current
+    DESCRIPTION
+        "Number of unauthorized TCP queries"
+    ::= { stats 17 }
+
+tcpClientOverflow OBJECT-TYPE
+    SYNTAX Counter64
+    MAX-ACCESS read-only
+    STATUS current
+    DESCRIPTION
+        "Number of TCP client connections refused because of too many connections"
+    ::= { stats 18 }
+
+clientParseErrors OBJECT-TYPE
+    SYNTAX Counter64
+    MAX-ACCESS read-only
+    STATUS current
+    DESCRIPTION
+        "Number of client parse errors"
+    ::= { stats 19 }
+
+serverParseErrors OBJECT-TYPE
+    SYNTAX Counter64
+    MAX-ACCESS read-only
+    STATUS current
+    DESCRIPTION
+        "Number of server parse errors"
+    ::= { stats 20 }
+
+tooOldDrops OBJECT-TYPE
+    SYNTAX Counter64
+    MAX-ACCESS read-only
+    STATUS current
+    DESCRIPTION
+        "Number of responses dropped because of a timeout"
+    ::= { stats 21 }
+
+answers01 OBJECT-TYPE
+    SYNTAX Counter64
+    MAX-ACCESS read-only
+    STATUS current
+    DESCRIPTION
+        "Number of queries answered in less than 1 ms"
+    ::= { stats 22 }
+
+answers110 OBJECT-TYPE
+    SYNTAX Counter64
+    MAX-ACCESS read-only
+    STATUS current
+    DESCRIPTION
+        "Number of queries answered in 1-10 ms"
+    ::= { stats 23 }
+
+answers10100 OBJECT-TYPE
+    SYNTAX Counter64
+    MAX-ACCESS read-only
+    STATUS current
+    DESCRIPTION
+        "Number of queries answered in 10-100 ms"
+    ::= { stats 24 }
+
+answers1001000 OBJECT-TYPE
+    SYNTAX Counter64
+    MAX-ACCESS read-only
+    STATUS current
+    DESCRIPTION
+        "Number of queries answered in 100-1000 ms"
+    ::= { stats 25 }
+
+answersSlow OBJECT-TYPE
+    SYNTAX Counter64
+    MAX-ACCESS read-only
+    STATUS current
+    DESCRIPTION
+        "Number of queries answered in more than 1000 ms"
+    ::= { stats 26 }
+
+auth4Answers01 OBJECT-TYPE
+    SYNTAX Counter64
+    MAX-ACCESS read-only
+    STATUS current
+    DESCRIPTION
+        "Number of IPv4 queries answered in less than 1 ms"
+    ::= { stats 27 }
+
+auth4Answers110 OBJECT-TYPE
+    SYNTAX Counter64
+    MAX-ACCESS read-only
+    STATUS current
+    DESCRIPTION
+        "Number of IPv4 queries answered in 1-10 ms"
+    ::= { stats 28 }
+
+auth4Answers10100 OBJECT-TYPE
+    SYNTAX Counter64
+    MAX-ACCESS read-only
+    STATUS current
+    DESCRIPTION
+        "Number of IPv4 queries answered in 10-100 ms"
+    ::= { stats 29 }
+
+auth4Answers1001000 OBJECT-TYPE
+    SYNTAX Counter64
+    MAX-ACCESS read-only
+    STATUS current
+    DESCRIPTION
+        "Number of IPv4 queries answered in 100-1000 ms"
+    ::= { stats 30 }
+
+auth4Answersslow OBJECT-TYPE
+    SYNTAX Counter64
+    MAX-ACCESS read-only
+    STATUS current
+    DESCRIPTION
+        "Number of IPv4 queries answered in more than 1000 ms"
+    ::= { stats 31 }
+
+auth6Answers01 OBJECT-TYPE
+    SYNTAX Counter64
+    MAX-ACCESS read-only
+    STATUS current
+    DESCRIPTION
+        "Number of IPv6 queries answered in less than 1 ms"
+    ::= { stats 32 }
+
+auth6Answers110 OBJECT-TYPE
+    SYNTAX Counter64
+    MAX-ACCESS read-only
+    STATUS current
+    DESCRIPTION
+        "Number of IPv6 queries answered in 1-10 ms"
+    ::= { stats 33 }
+
+auth6Answers10100 OBJECT-TYPE
+    SYNTAX Counter64
+    MAX-ACCESS read-only
+    STATUS current
+    DESCRIPTION
+        "Number of IPv6 queries answered in 10-100 ms"
+    ::= { stats 34 }
+
+auth6Answers1001000 OBJECT-TYPE
+    SYNTAX Counter64
+    MAX-ACCESS read-only
+    STATUS current
+    DESCRIPTION
+        "Number of IPv6 queries answered in 100-1000 ms"
+    ::= { stats 35 }
+
+auth6AnswersSlow OBJECT-TYPE
+    SYNTAX Counter64
+    MAX-ACCESS read-only
+    STATUS current
+    DESCRIPTION
+        "Number of IPv6 queries answered in more than 1000 ms"
+    ::= { stats 36 }
+
+qaLatency OBJECT-TYPE
+    SYNTAX CounterBasedGauge64
+    MAX-ACCESS read-only
+    STATUS current
+    DESCRIPTION
+        "Average latency in microseconds"
+    ::= { stats 37 }
+
+unexpectedPackets OBJECT-TYPE
+    SYNTAX Counter64
+    MAX-ACCESS read-only
+    STATUS current
+    DESCRIPTION
+        "Number of unexpected packets"
+    ::= { stats 38 }
+
+caseMismatches OBJECT-TYPE
+    SYNTAX Counter64
+    MAX-ACCESS read-only
+    STATUS current
+    DESCRIPTION
+        "Number of case mismatches"
+    ::= { stats 39 }
+
+spoofPrevents OBJECT-TYPE
+    SYNTAX Counter64
+    MAX-ACCESS read-only
+    STATUS current
+    DESCRIPTION
+        "Number of spoof prevents"
+    ::= { stats 40 }
+
+nssetInvalidations OBJECT-TYPE
+    SYNTAX Counter64
+    MAX-ACCESS read-only
+    STATUS current
+    DESCRIPTION
+        "Number of nsset invalidations"
+    ::= { stats 41 }
+
+resourceLimits OBJECT-TYPE
+    SYNTAX Counter64
+    MAX-ACCESS read-only
+    STATUS current
+    DESCRIPTION
+        "Number of resolution aborted because of a local resource limit"
+    ::= { stats 42 }
+
+overCapacityDrops OBJECT-TYPE
+    SYNTAX Counter64
+    MAX-ACCESS read-only
+    STATUS current
+    DESCRIPTION
+        "Number of queries dropped because the threads limit was reached"
+    ::= { stats 43 }
+
+policyDrops OBJECT-TYPE
+    SYNTAX Counter64
+    MAX-ACCESS read-only
+    STATUS current
+    DESCRIPTION
+        "Number of queries dropped because of a policy"
+    ::= { stats 44 }
+
+noPacketError OBJECT-TYPE
+    SYNTAX Counter64
+    MAX-ACCESS read-only
+    STATUS current
+    DESCRIPTION
+        "Number of noPacketError"
+    ::= { stats 45 }
+
+dlgOnlyDrops OBJECT-TYPE
+    SYNTAX Counter64
+    MAX-ACCESS read-only
+    STATUS current
+    DESCRIPTION
+        "Number of records dropped because of they belonged to a delegation-only zone"
+    ::= { stats 46 }
+
+ignoredPackets OBJECT-TYPE
+    SYNTAX Counter64
+    MAX-ACCESS read-only
+    STATUS current
+    DESCRIPTION
+        "Number of ignored packets"
+    ::= { stats 47 }
+
+maxMthreadStack OBJECT-TYPE
+    SYNTAX CounterBasedGauge64
+    MAX-ACCESS read-only
+    STATUS current
+    DESCRIPTION
+        "Maximum size of the Mthread stack"
+    ::= { stats 48 }
+
+negcacheEntries OBJECT-TYPE
+    SYNTAX CounterBasedGauge64
+    MAX-ACCESS read-only
+    STATUS current
+    DESCRIPTION
+        "Number of negcache entries"
+    ::= { stats 49 }
+
+throttleEntries OBJECT-TYPE
+    SYNTAX CounterBasedGauge64
+    MAX-ACCESS read-only
+    STATUS current
+    DESCRIPTION
+        "Number of throttle entries"
+    ::= { stats 50 }
+
+nsspeedsEntries OBJECT-TYPE
+    SYNTAX CounterBasedGauge64
+    MAX-ACCESS read-only
+    STATUS current
+    DESCRIPTION
+        "Number of nsspeeds entries"
+    ::= { stats 51 }
+
+failedHostEntries OBJECT-TYPE
+    SYNTAX CounterBasedGauge64
+    MAX-ACCESS read-only
+    STATUS current
+    DESCRIPTION
+        "Number of failed host entries"
+    ::= { stats 52 }
+
+concurrentQueries OBJECT-TYPE
+    SYNTAX CounterBasedGauge64
+    MAX-ACCESS read-only
+    STATUS current
+    DESCRIPTION
+        "Number of concurrent queries"
+    ::= { stats 53 }
+
+securityStatus OBJECT-TYPE
+    SYNTAX CounterBasedGauge64
+    MAX-ACCESS read-only
+    STATUS current
+    DESCRIPTION
+        "Current security status"
+    ::= { stats 54 }
+
+outgoingTimeouts OBJECT-TYPE
+    SYNTAX Counter64
+    MAX-ACCESS read-only
+    STATUS current
+    DESCRIPTION
+        "Number of outgoing timeouts"
+    ::= { stats 55 }
+
+outgoing4Timeouts OBJECT-TYPE
+    SYNTAX Counter64
+    MAX-ACCESS read-only
+    STATUS current
+    DESCRIPTION
+        "Number of IPv4 outgoing timeouts"
+    ::= { stats 56 }
+
+outgoing6Timeouts OBJECT-TYPE
+    SYNTAX Counter64
+    MAX-ACCESS read-only
+    STATUS current
+    DESCRIPTION
+        "Number of IPv6 outgoing timeouts"
+    ::= { stats 57 }
+
+tcpOutqueries OBJECT-TYPE
+    SYNTAX Counter64
+    MAX-ACCESS read-only
+    STATUS current
+    DESCRIPTION
+        "Number of outgoing TCP queries sent"
+    ::= { stats 58 }
+
+allOutqueries OBJECT-TYPE
+    SYNTAX Counter64
+    MAX-ACCESS read-only
+    STATUS current
+    DESCRIPTION
+        "Number of outgoing queries sent"
+    ::= { stats 59 }
+
+ipv6Outqueries OBJECT-TYPE
+    SYNTAX Counter64
+    MAX-ACCESS read-only
+    STATUS current
+    DESCRIPTION
+        "Number of IPv6 outgoing queries sent"
+    ::= { stats 60 }
+
+throttledOutqueries OBJECT-TYPE
+    SYNTAX Counter64
+    MAX-ACCESS read-only
+    STATUS current
+    DESCRIPTION
+        "Number of throttled outgoing queries"
+    ::= { stats 61 }
+
+dontOutqueries OBJECT-TYPE
+    SYNTAX Counter64
+    MAX-ACCESS read-only
+    STATUS current
+    DESCRIPTION
+        "Number of outgoing queries not sent because of a 'dont-query' setting"
+    ::= { stats 62 }
+
+unreachables OBJECT-TYPE
+    SYNTAX Counter64
+    MAX-ACCESS read-only
+    STATUS current
+    DESCRIPTION
+        "Number of errors due to an unreachable server"
+    ::= { stats 63 }
+
+chainResends OBJECT-TYPE
+    SYNTAX Counter64
+    MAX-ACCESS read-only
+    STATUS current
+    DESCRIPTION
+        "Number of chain resends"
+    ::= { stats 64 }
+
+tcpClients OBJECT-TYPE
+    SYNTAX CounterBasedGauge64
+    MAX-ACCESS read-only
+    STATUS current
+    DESCRIPTION
+        "Number of TCP clients"
+    ::= { stats 65 }
+
+udpRecvbufErrors OBJECT-TYPE
+    SYNTAX Counter64
+    MAX-ACCESS read-only
+    STATUS current
+    DESCRIPTION
+        "Number of UDP recvbuf errors (Linux only)"
+    ::= { stats 66 }
+
+udpSndbufErrors OBJECT-TYPE
+    SYNTAX Counter64
+    MAX-ACCESS read-only
+    STATUS current
+    DESCRIPTION
+        "Number of UDP sndbuf errors (Linux only)"
+    ::= { stats 67 }
+
+udpNoportErrors OBJECT-TYPE
+    SYNTAX Counter64
+    MAX-ACCESS read-only
+    STATUS current
+    DESCRIPTION
+        "Number of UDP noport errors (Linux only)"
+    ::= { stats 68 }
+
+udpinErrors OBJECT-TYPE
+    SYNTAX Counter64
+    MAX-ACCESS read-only
+    STATUS current
+    DESCRIPTION
+        "Number of UDP in errors (Linux only)"
+    ::= { stats 69 }
+
+ednsPingMatches OBJECT-TYPE
+    SYNTAX Counter64
+    MAX-ACCESS read-only
+    STATUS current
+    DESCRIPTION
+        "Number of EDNS Ping matches"
+    ::= { stats 70 }
+
+ednsPingMismatches OBJECT-TYPE
+    SYNTAX Counter64
+    MAX-ACCESS read-only
+    STATUS current
+    DESCRIPTION
+        "Number of EDNS Ping mismatches"
+    ::= { stats 71 }
+
+dnssecQueries OBJECT-TYPE
+    SYNTAX Counter64
+    MAX-ACCESS read-only
+    STATUS current
+    DESCRIPTION
+        "Number of DNSSEC queries"
+    ::= { stats 72 }
+
+nopingOutqueries OBJECT-TYPE
+    SYNTAX Counter64
+    MAX-ACCESS read-only
+    STATUS current
+    DESCRIPTION
+        "Number of outgoing queries w/o ping"
+    ::= { stats 73 }
+
+noednsOutqueries OBJECT-TYPE
+    SYNTAX Counter64
+    MAX-ACCESS read-only
+    STATUS current
+    DESCRIPTION
+        "Number of outgoing queries w/o EDNS"
+    ::= { stats 74 }
+
+uptime OBJECT-TYPE
+    SYNTAX Counter64
+    MAX-ACCESS read-only
+    STATUS current
+    DESCRIPTION
+        "Process uptime in seconds"
+    ::= { stats 75 }
+
+realMemoryUsage OBJECT-TYPE
+    SYNTAX CounterBasedGauge64
+    MAX-ACCESS read-only
+    STATUS current
+    DESCRIPTION
+        "Memory usage"
+    ::= { stats 76 }
+
+fdUsage OBJECT-TYPE
+    SYNTAX CounterBasedGauge64
+    MAX-ACCESS read-only
+    STATUS current
+    DESCRIPTION
+        "File descriptors usage"
+    ::= { stats 77 }
+
+userMsec OBJECT-TYPE
+    SYNTAX CounterBasedGauge64
+    MAX-ACCESS read-only
+    STATUS current
+    DESCRIPTION
+        "CPU usage (user) in ms"
+    ::= { stats 78 }
+
+sysMsec OBJECT-TYPE
+    SYNTAX CounterBasedGauge64
+    MAX-ACCESS read-only
+    STATUS current
+    DESCRIPTION
+        "CPU usage (system) in ms"
+    ::= { stats 79 }
+
+dnssecValidations OBJECT-TYPE
+    SYNTAX Counter64
+    MAX-ACCESS read-only
+    STATUS current
+    DESCRIPTION
+        "Number of DNSSEC validations"
+    ::= { stats 80 }
+
+dnssecResultInsecure OBJECT-TYPE
+    SYNTAX Counter64
+    MAX-ACCESS read-only
+    STATUS current
+    DESCRIPTION
+        "Number of DNSSEC insecure results"
+    ::= { stats 81 }
+
+dnssecResultSecure OBJECT-TYPE
+    SYNTAX Counter64
+    MAX-ACCESS read-only
+    STATUS current
+    DESCRIPTION
+        "Number of DNSSEC secure results"
+    ::= { stats 82 }
+
+dnssecResultBogus OBJECT-TYPE
+    SYNTAX Counter64
+    MAX-ACCESS read-only
+    STATUS current
+    DESCRIPTION
+        "Number of DNSSEC bogus results"
+    ::= { stats 83 }
+
+dnssecResultIndeterminate OBJECT-TYPE
+    SYNTAX Counter64
+    MAX-ACCESS read-only
+    STATUS current
+    DESCRIPTION
+        "Number of DNSSEC indeterminate results"
+    ::= { stats 84 }
+
+dnssecResultNta OBJECT-TYPE
+    SYNTAX Counter64
+    MAX-ACCESS read-only
+    STATUS current
+    DESCRIPTION
+        "Number of DNSSEC NTA results"
+    ::= { stats 85 }
+
+policyResultNoaction OBJECT-TYPE
+    SYNTAX Counter64
+    MAX-ACCESS read-only
+    STATUS current
+    DESCRIPTION
+        "Number of policy-mandated no-action results"
+    ::= { stats 86 }
+
+policyResultDrop OBJECT-TYPE
+    SYNTAX Counter64
+    MAX-ACCESS read-only
+    STATUS current
+    DESCRIPTION
+        "Number of policy-mandated drops"
+    ::= { stats 87 }
+
+policyResultNxdomain OBJECT-TYPE
+    SYNTAX Counter64
+    MAX-ACCESS read-only
+    STATUS current
+    DESCRIPTION
+        "Number of policy-mandated NXdomain results"
+    ::= { stats 88 }
+
+policyResultNodata OBJECT-TYPE
+    SYNTAX Counter64
+    MAX-ACCESS read-only
+    STATUS current
+    DESCRIPTION
+        "Number of policy-mandated nodata results"
+    ::= { stats 89 }
+
+policyResultTruncate OBJECT-TYPE
+    SYNTAX Counter64
+    MAX-ACCESS read-only
+    STATUS current
+    DESCRIPTION
+        "Number of policy-mandated truncate results"
+    ::= { stats 90 }
+
+policyResultCustom OBJECT-TYPE
+    SYNTAX Counter64
+    MAX-ACCESS read-only
+    STATUS current
+    DESCRIPTION
+        "Number of policy-mandated custom results"
+    ::= { stats 91 }
+
+---
+--- Traps / Notifications
+---
+
+trap OBJECT IDENTIFIER ::= { rec 10 }
+traps OBJECT IDENTIFIER ::= { trap 0 } --- reverse-mappable
+trapObjects OBJECT IDENTIFIER ::= { rec 11 }
+
+trapReason OBJECT-TYPE
+    SYNTAX OCTET STRING
+    MAX-ACCESS read-only
+    STATUS current
+    DESCRIPTION
+        "Reason for this trap"
+    ::= { trapObjects 1 }
+
+customTrap NOTIFICATION-TYPE
+    OBJECTS {
+        trapReason
+    }
+    STATUS current
+    DESCRIPTION "Trap sent by sendCustomTrap"
+    ::= { traps 1 }
+
+---
+--- Conformance
+---
+
+recConformance OBJECT IDENTIFIER ::= { rec 100 }
+
+recCompliances MODULE-COMPLIANCE
+    STATUS current
+    DESCRIPTION "PowerDNS Recursor compliance statement"
+    MODULE
+    MANDATORY-GROUPS {
+        recGroup,
+        recTrapsGroup
+    }
+    ::= { recConformance 1 }
+
+recGroup OBJECT-GROUP
+    OBJECTS {
+        questions,
+        ipv6Questions,
+        tcpQuestions,
+        cacheHits,
+        cacheMisses,
+        cacheEntries,
+        cacheBytes,
+        packetcacheHits,
+        packetcacheMisses,
+        packetcacheEntries,
+        packetcacheBytes,
+        mallocBytes,
+        servfailAnswers,
+        nxdomainAnswers,
+        noerrorAnswers,
+        unauthorizedUdp,
+        unauthorizedTcp,
+        tcpClientOverflow,
+        clientParseErrors,
+        serverParseErrors,
+        tooOldDrops,
+        answers01,
+        answers110,
+        answers10100,
+        answers1001000,
+        answersSlow,
+        auth4Answers01,
+        auth4Answers110,
+        auth4Answers10100,
+        auth4Answers1001000,
+        auth4Answersslow,
+        auth6Answers01,
+        auth6Answers110,
+        auth6Answers10100,
+        auth6Answers1001000,
+        auth6AnswersSlow,
+        qaLatency,
+        unexpectedPackets,
+        caseMismatches,
+        spoofPrevents,
+        nssetInvalidations,
+        resourceLimits,
+        overCapacityDrops,
+        policyDrops,
+        noPacketError,
+        dlgOnlyDrops,
+        ignoredPackets,
+        maxMthreadStack,
+        negcacheEntries,
+        throttleEntries,
+        nsspeedsEntries,
+        failedHostEntries,
+        concurrentQueries,
+        securityStatus,
+        outgoingTimeouts,
+        outgoing4Timeouts,
+        outgoing6Timeouts,
+        tcpOutqueries,
+        allOutqueries,
+        ipv6Outqueries,
+        throttledOutqueries,
+        dontOutqueries,
+        unreachables,
+        chainResends,
+        tcpClients,
+        udpRecvbufErrors,
+        udpSndbufErrors,
+        udpNoportErrors,
+        udpinErrors,
+        ednsPingMatches,
+        ednsPingMismatches,
+        dnssecQueries,
+        nopingOutqueries,
+        noednsOutqueries,
+        uptime,
+        realMemoryUsage,
+        fdUsage,
+        userMsec,
+        sysMsec,
+        dnssecValidations,
+        dnssecResultInsecure,
+        dnssecResultSecure,
+        dnssecResultBogus,
+        dnssecResultIndeterminate,
+        dnssecResultNta,
+        policyResultNoaction,
+        policyResultDrop,
+        policyResultNxdomain,
+        policyResultNodata,
+        policyResultTruncate,
+        policyResultCustom,
+        trapReason
+    }
+    STATUS current
+    DESCRIPTION "Objects conformance group for PowerDNS Recursor"
+    ::= { recConformance 2 }
+
+recTrapsGroup NOTIFICATION-GROUP
+    NOTIFICATIONS {
+        customTrap
+    }
+    STATUS current
+    DESCRIPTION "Traps conformance group for PowerDNS Recursor"
+    ::= { recConformance 3 }
+
+END
index 086f7f1c124bbb8dc6ff80085908c0d2c6f5eee6..bc8927a87c68610d593407de3323dd53f401fde7 100644 (file)
@@ -525,3 +525,16 @@ The kind of policy response, there are several policy kinds:
 These fields are only used when `dq.appliedPolicy.policyKind` is set to `pdns.policykinds.Custom`.
 `dq.appliedPolicy.policyCustom` contains the name for the CNAME target as a string.
 And `dq.appliedPolicy.policyTTL` is the TTL field (in seconds) for the CNAME response.
+
+## SNMP Traps
+PowerDNS Recursor, when compiled with SNMP support, has the ability to act as a
+SNMP agent to provide SNMP statistics and to be able to send traps from Lua.
+
+For example, to send a custom SNMP trap containing the qname from the `preresolve` hook:
+
+```
+function preresolve(dq)
+  sendCustomSNMPTrap('Trap from preresolve, qname is '..dq.qname:toString())
+  return false
+end
+```
index c55c4fba1ccd813817f76b5054f2d2a5bea31f99..8f0c685eef1c188dae3301b552e459ea118138ac 100644 (file)
@@ -796,6 +796,20 @@ used for better [security](security.md).
 
 Use only a single socket for outgoing queries.
 
+## `snmp-agent`
+* Boolean
+* Default: no
+
+If set to true and PowerDNS has been compiled with SNMP support, it will register
+as an SNMP agent to provide statistics and be able to send traps.
+
+## `snmp-master-socket`
+* String
+* Default: empty
+
+If not empty and `snmp-agent` is set to true, indicates how PowerDNS should contact
+the SNMP master to register as an SNMP agent.
+
 ## `socket-dir`
 * Path
 
index 850a97d17995c0a6f03ca276106195b0f4bfed41..e8a9d0b9fa9bad1101473913032a8da748591b70 100644 (file)
@@ -28,6 +28,7 @@
 #include "rec_channel.hh" 
 #include "ednssubnet.hh"
 #include "filterpo.hh"
+#include "rec-snmp.hh"
 #include <unordered_set>
 
 #if !defined(HAVE_LUA)
@@ -568,6 +569,11 @@ RecursorLua4::RecursorLua4(const std::string& fname)
       return getRecursorThreadId();
     });
 
+  d_lw->writeFunction("sendCustomSNMPTrap", [](const std::string& str) {
+      if (g_snmpAgent) {
+        g_snmpAgent->sendCustomTrap(str);
+      }
+    });
   
   ifstream ifs(fname);
   if(!ifs) {
index 7be428fa9af677fe232e0ca807aa1168a77bd531..3445b5d572e6b5e50e7768c082c0fad48e8a4cc1 100644 (file)
@@ -85,6 +85,7 @@ extern SortList g_sortlist;
 #include "gettime.hh"
 
 #include "rec-protobuf.hh"
+#include "rec-snmp.hh"
 
 #ifdef HAVE_SYSTEMD
 #include <systemd/sd-daemon.h>
@@ -2812,6 +2813,11 @@ int serviceMain(int argc, char*argv[])
   g_maxTCPPerClient=::arg().asNum("max-tcp-per-client");
   g_tcpMaxQueriesPerConn=::arg().asNum("max-tcp-queries-per-connection");
 
+  if (::arg().mustDo("snmp-agent")) {
+    g_snmpAgent = std::make_shared<RecursorSNMPAgent>("recursor", ::arg()["snmp-master-socket"]);
+    g_snmpAgent->run();
+  }
+
   if(g_numThreads == 1) {
     L<<Logger::Warning<<"Operating unthreaded"<<endl;
 #ifdef HAVE_SYSTEMD
@@ -3098,6 +3104,9 @@ int main(int argc, char **argv)
     
     ::arg().setSwitch("reuseport","Enable SO_REUSEPORT allowing multiple recursors processes to listen to 1 address")="no";
 
+    ::arg().setSwitch("snmp-agent", "If set, register as an SNMP agent")="no";
+    ::arg().setSwitch("snmp-master-socket", "If set and snmp-agent is set, the socket to use to register to the SNMP master")="";
+
     ::arg().setCmd("help","Provide a helpful message");
     ::arg().setCmd("version","Print version string");
     ::arg().setCmd("config","Output blank configuration");
diff --git a/pdns/rec-snmp.cc b/pdns/rec-snmp.cc
new file mode 100644 (file)
index 0000000..3e39ffd
--- /dev/null
@@ -0,0 +1,295 @@
+
+#include <unordered_map>
+
+#include "rec-snmp.hh"
+#include "rec_channel.hh"
+
+#include "logger.hh"
+
+#ifdef HAVE_NET_SNMP
+
+#define RECURSOR_OID 1, 3, 6, 1, 4, 1, 43315, 2
+#define RECURSOR_STATS_OID RECURSOR_OID, 1
+#define RECURSOR_TRAPS_OID RECURSOR_OID, 10, 0
+#define RECURSOR_TRAP_OBJECTS_OID RECURSOR_OID, 11
+
+static const oid trapReasonOID[] = { RECURSOR_TRAP_OBJECTS_OID, 1, 0 };
+static const oid customTrapOID[] = { RECURSOR_TRAPS_OID, 1 };
+
+static const oid questionsOID[] = { RECURSOR_STATS_OID, 1 };
+static const oid ipv6QuestionsOID[] = { RECURSOR_STATS_OID, 2 };
+static const oid tcpQuestionsOID[] = { RECURSOR_STATS_OID, 3 };
+static const oid cacheHitsOID[] = { RECURSOR_STATS_OID, 4 };
+static const oid cacheMissesOID[] = { RECURSOR_STATS_OID, 5 };
+static const oid cacheEntriesOID[] = { RECURSOR_STATS_OID, 6 };
+static const oid cacheBytesOID[] = { RECURSOR_STATS_OID, 7 };
+static const oid packetcacheHitsOID[] = { RECURSOR_STATS_OID, 8 };
+static const oid packetcacheMissesOID[] = { RECURSOR_STATS_OID, 9 };
+static const oid packetcacheEntriesOID[] = { RECURSOR_STATS_OID, 10 };
+static const oid packetcacheBytesOID[] = { RECURSOR_STATS_OID, 11 };
+static const oid mallocBytesOID[] = { RECURSOR_STATS_OID, 12 };
+static const oid servfailAnswersOID[] = { RECURSOR_STATS_OID, 13 };
+static const oid nxdomainAnswersOID[] = { RECURSOR_STATS_OID, 14 };
+static const oid noerrorAnswersOID[] = { RECURSOR_STATS_OID, 15 };
+static const oid unauthorizedUdpOID[] = { RECURSOR_STATS_OID, 16 };
+static const oid unauthorizedTcpOID[] = { RECURSOR_STATS_OID, 17 };
+static const oid tcpClientOverflowOID[] = { RECURSOR_STATS_OID, 18 };
+static const oid clientParseErrorsOID[] = { RECURSOR_STATS_OID, 19 };
+static const oid serverParseErrorsOID[] = { RECURSOR_STATS_OID, 20 };
+static const oid tooOldDropsOID[] = { RECURSOR_STATS_OID, 21 };
+static const oid answers01OID[] = { RECURSOR_STATS_OID, 22 };
+static const oid answers110OID[] = { RECURSOR_STATS_OID, 23 };
+static const oid answers10100OID[] = { RECURSOR_STATS_OID, 24 };
+static const oid answers1001000OID[] = { RECURSOR_STATS_OID, 25 };
+static const oid answersSlowOID[] = { RECURSOR_STATS_OID, 26 };
+static const oid auth4Answers01OID[] = { RECURSOR_STATS_OID, 27 };
+static const oid auth4Answers110OID[] = { RECURSOR_STATS_OID, 28 };
+static const oid auth4Answers10100OID[] = { RECURSOR_STATS_OID, 29 };
+static const oid auth4Answers1001000OID[] = { RECURSOR_STATS_OID, 30 };
+static const oid auth4AnswersslowOID[] = { RECURSOR_STATS_OID, 31 };
+static const oid auth6Answers01OID[] = { RECURSOR_STATS_OID, 32 };
+static const oid auth6Answers110OID[] = { RECURSOR_STATS_OID, 33 };
+static const oid auth6Answers10100OID[] = { RECURSOR_STATS_OID, 34 };
+static const oid auth6Answers1001000OID[] = { RECURSOR_STATS_OID, 35 };
+static const oid auth6AnswersSlowOID[] = { RECURSOR_STATS_OID, 36 };
+static const oid qaLatencyOID[] = { RECURSOR_STATS_OID, 37 };
+static const oid unexpectedPacketsOID[] = { RECURSOR_STATS_OID, 38 };
+static const oid caseMismatchesOID[] = { RECURSOR_STATS_OID, 39 };
+static const oid spoofPreventsOID[] = { RECURSOR_STATS_OID, 40 };
+static const oid nssetInvalidationsOID[] = { RECURSOR_STATS_OID, 41 };
+static const oid resourceLimitsOID[] = { RECURSOR_STATS_OID, 42 };
+static const oid overCapacityDropsOID[] = { RECURSOR_STATS_OID, 43 };
+static const oid policyDropsOID[] = { RECURSOR_STATS_OID, 44 };
+static const oid noPacketErrorOID[] = { RECURSOR_STATS_OID, 45 };
+static const oid dlgOnlyDropsOID[] = { RECURSOR_STATS_OID, 46 };
+static const oid ignoredPacketsOID[] = { RECURSOR_STATS_OID, 47 };
+static const oid maxMthreadStackOID[] = { RECURSOR_STATS_OID, 48 };
+static const oid negcacheEntriesOID[] = { RECURSOR_STATS_OID, 49 };
+static const oid throttleEntriesOID[] = { RECURSOR_STATS_OID, 50 };
+static const oid nsspeedsEntriesOID[] = { RECURSOR_STATS_OID, 51 };
+static const oid failedHostEntriesOID[] = { RECURSOR_STATS_OID, 52 };
+static const oid concurrentQueriesOID[] = { RECURSOR_STATS_OID, 53 };
+static const oid securityStatusOID[] = { RECURSOR_STATS_OID, 54 };
+static const oid outgoingTimeoutsOID[] = { RECURSOR_STATS_OID, 55 };
+static const oid outgoing4TimeoutsOID[] = { RECURSOR_STATS_OID, 56 };
+static const oid outgoing6TimeoutsOID[] = { RECURSOR_STATS_OID, 57 };
+static const oid tcpOutqueriesOID[] = { RECURSOR_STATS_OID, 58 };
+static const oid allOutqueriesOID[] = { RECURSOR_STATS_OID, 59 };
+static const oid ipv6OutqueriesOID[] = { RECURSOR_STATS_OID, 60 };
+static const oid throttledOutqueriesOID[] = { RECURSOR_STATS_OID, 61 };
+static const oid dontOutqueriesOID[] = { RECURSOR_STATS_OID, 62 };
+static const oid unreachablesOID[] = { RECURSOR_STATS_OID, 63 };
+static const oid chainResendsOID[] = { RECURSOR_STATS_OID, 64 };
+static const oid tcpClientsOID[] = { RECURSOR_STATS_OID, 65 };
+static const oid udpRecvbufErrorsOID[] = { RECURSOR_STATS_OID, 66 };
+static const oid udpSndbufErrorsOID[] = { RECURSOR_STATS_OID, 67 };
+static const oid udpNoportErrorsOID[] = { RECURSOR_STATS_OID, 68 };
+static const oid udpinErrorsOID[] = { RECURSOR_STATS_OID, 69 };
+static const oid ednsPingMatchesOID[] = { RECURSOR_STATS_OID, 70 };
+static const oid ednsPingMismatchesOID[] = { RECURSOR_STATS_OID, 71 };
+static const oid dnssecQueriesOID[] = { RECURSOR_STATS_OID, 72 };
+static const oid nopingOutqueriesOID[] = { RECURSOR_STATS_OID, 73 };
+static const oid noednsOutqueriesOID[] = { RECURSOR_STATS_OID, 74 };
+static const oid uptimeOID[] = { RECURSOR_STATS_OID, 75 };
+static const oid realMemoryUsageOID[] = { RECURSOR_STATS_OID, 76 };
+static const oid fdUsageOID[] = { RECURSOR_STATS_OID, 77 };
+static const oid userMsecOID[] = { RECURSOR_STATS_OID, 78 };
+static const oid sysMsecOID[] = { RECURSOR_STATS_OID, 79 };
+static const oid dnssecValidationsOID[] = { RECURSOR_STATS_OID, 80 };
+static const oid dnssecResultInsecureOID[] = { RECURSOR_STATS_OID, 81 };
+static const oid dnssecResultSecureOID[] = { RECURSOR_STATS_OID, 82 };
+static const oid dnssecResultBogusOID[] = { RECURSOR_STATS_OID, 83 };
+static const oid dnssecResultIndeterminateOID[] = { RECURSOR_STATS_OID, 84 };
+static const oid dnssecResultNtaOID[] = { RECURSOR_STATS_OID, 85 };
+static const oid policyResultNoactionOID[] = { RECURSOR_STATS_OID, 86 };
+static const oid policyResultDropOID[] = { RECURSOR_STATS_OID, 87 };
+static const oid policyResultNxdomainOID[] = { RECURSOR_STATS_OID, 88 };
+static const oid policyResultNodataOID[] = { RECURSOR_STATS_OID, 89 };
+static const oid policyResultTruncateOID[] = { RECURSOR_STATS_OID, 90 };
+static const oid policyResultCustomOID[] = { RECURSOR_STATS_OID, 91 };
+
+static std::unordered_map<oid, std::string> s_statsMap;
+
+/* We are never called for a GETNEXT if it's registered as a
+   "instance", as it's "magically" handled for us.  */
+/* a instance handler also only hands us one request at a time, so
+   we don't need to loop over a list of requests; we'll only get one. */
+
+static int handleCounter64Stats(netsnmp_mib_handler* handler,
+                                netsnmp_handler_registration* reginfo,
+                                netsnmp_agent_request_info* reqinfo,
+                                netsnmp_request_info* requests)
+{
+  if (reqinfo->mode != MODE_GET) {
+    return SNMP_ERR_GENERR;
+  }
+
+  if (reginfo->rootoid_len != OID_LENGTH(questionsOID) + 1) {
+    return SNMP_ERR_GENERR;
+  }
+
+  const auto& it = s_statsMap.find(reginfo->rootoid[reginfo->rootoid_len - 2]);
+  if (it == s_statsMap.end()) {
+    return SNMP_ERR_GENERR;
+  }
+
+  optional<uint64_t> value = getStatByName(it->second);
+  if (value) {
+    return RecursorSNMPAgent::setCounter64Value(requests, *value);
+  } else {
+    return RecursorSNMPAgent::setCounter64Value(requests, 0);
+  }
+}
+
+static void registerCounter64Stat(const char* name, const oid statOID[], size_t statOIDLength)
+{
+  if (statOIDLength != OID_LENGTH(questionsOID)) {
+    L<<Logger::Error<<"Invalid OID for SNMP Counter64 statistic "<<std::string(name)<<endl;
+    return;
+  }
+
+  if (s_statsMap.find(statOID[statOIDLength - 1]) != s_statsMap.end()) {
+    L<<Logger::Error<<"OID for SNMP Counter64 statistic "<<std::string(name)<<" has already been registered"<<endl;
+    return;
+  }
+
+  s_statsMap[statOID[statOIDLength - 1]] = name;
+  netsnmp_register_scalar(netsnmp_create_handler_registration(name,
+                                                              handleCounter64Stats,
+                                                              statOID,
+                                                              statOIDLength,
+                                                              HANDLER_CAN_RONLY));
+}
+
+#endif /* HAVE_NET_SNMP */
+
+std::shared_ptr<RecursorSNMPAgent> g_snmpAgent{nullptr};
+
+bool RecursorSNMPAgent::sendCustomTrap(const std::string& reason)
+{
+#ifdef HAVE_NET_SNMP
+  netsnmp_variable_list* varList = nullptr;
+
+  snmp_varlist_add_variable(&varList,
+                            snmpTrapOID,
+                            snmpTrapOIDLen,
+                            ASN_OBJECT_ID,
+                            customTrapOID,
+                            OID_LENGTH(customTrapOID)  * sizeof(oid));
+
+  snmp_varlist_add_variable(&varList,
+                            trapReasonOID,
+                            OID_LENGTH(trapReasonOID),
+                            ASN_OCTET_STR,
+                            reason.c_str(),
+                            reason.size());
+
+  return sendTrap(d_trapPipe[1], varList);
+#endif /* HAVE_NET_SNMP */
+  return true;
+}
+
+
+RecursorSNMPAgent::RecursorSNMPAgent(const std::string& name, const std::string& masterSocket): SNMPAgent(name, masterSocket)
+{
+#ifdef HAVE_NET_SNMP
+  /* This is done so that the statistics maps are
+     initialized. */
+  RecursorControlParser rcp;
+
+  registerCounter64Stat("questions", questionsOID, OID_LENGTH(questionsOID));
+  registerCounter64Stat("ipv6-questions", ipv6QuestionsOID, OID_LENGTH(ipv6QuestionsOID));
+  registerCounter64Stat("tcp-questions", tcpQuestionsOID, OID_LENGTH(tcpQuestionsOID));
+  registerCounter64Stat("cache-hits", cacheHitsOID, OID_LENGTH(cacheHitsOID));
+  registerCounter64Stat("cache-misses", cacheMissesOID, OID_LENGTH(cacheMissesOID));
+  registerCounter64Stat("cache-entries", cacheEntriesOID, OID_LENGTH(cacheEntriesOID));
+  registerCounter64Stat("cache-bytes", cacheBytesOID, OID_LENGTH(cacheBytesOID));
+  registerCounter64Stat("packetcache-hits", packetcacheHitsOID, OID_LENGTH(packetcacheHitsOID));
+  registerCounter64Stat("packetcache-misses", packetcacheMissesOID, OID_LENGTH(packetcacheMissesOID));
+  registerCounter64Stat("packetcache-entries", packetcacheEntriesOID, OID_LENGTH(packetcacheEntriesOID));
+  registerCounter64Stat("packetcache-bytes", packetcacheBytesOID, OID_LENGTH(packetcacheBytesOID));
+  registerCounter64Stat("malloc-bytes", mallocBytesOID, OID_LENGTH(mallocBytesOID));
+  registerCounter64Stat("servfail-answers", servfailAnswersOID, OID_LENGTH(servfailAnswersOID));
+  registerCounter64Stat("nxdomain-answers", nxdomainAnswersOID, OID_LENGTH(nxdomainAnswersOID));
+  registerCounter64Stat("noerror-answers", noerrorAnswersOID, OID_LENGTH(noerrorAnswersOID));
+  registerCounter64Stat("unauthorized-udp", unauthorizedUdpOID, OID_LENGTH(unauthorizedUdpOID));
+  registerCounter64Stat("unauthorized-tcp", unauthorizedTcpOID, OID_LENGTH(unauthorizedTcpOID));
+  registerCounter64Stat("tcp-client-overflow", tcpClientOverflowOID, OID_LENGTH(tcpClientOverflowOID));
+  registerCounter64Stat("client-parse-errors", clientParseErrorsOID, OID_LENGTH(clientParseErrorsOID));
+  registerCounter64Stat("server-parse-errors", serverParseErrorsOID, OID_LENGTH(serverParseErrorsOID));
+  registerCounter64Stat("too-old-drops", tooOldDropsOID, OID_LENGTH(tooOldDropsOID));
+  registerCounter64Stat("answers0-1", answers01OID, OID_LENGTH(answers01OID));
+  registerCounter64Stat("answers1-10", answers110OID, OID_LENGTH(answers110OID));
+  registerCounter64Stat("answers10-100", answers10100OID, OID_LENGTH(answers10100OID));
+  registerCounter64Stat("answers100-1000", answers1001000OID, OID_LENGTH(answers1001000OID));
+  registerCounter64Stat("answers-slow", answersSlowOID, OID_LENGTH(answersSlowOID));
+  registerCounter64Stat("auth4-answers0-1", auth4Answers01OID, OID_LENGTH(auth4Answers01OID));
+  registerCounter64Stat("auth4-answers1-10", auth4Answers110OID, OID_LENGTH(auth4Answers110OID));
+  registerCounter64Stat("auth4-answers10-100", auth4Answers10100OID, OID_LENGTH(auth4Answers10100OID));
+  registerCounter64Stat("auth4-answers100-1000", auth4Answers1001000OID, OID_LENGTH(auth4Answers1001000OID));
+  registerCounter64Stat("auth4-answers-slow", auth4AnswersslowOID, OID_LENGTH(auth4AnswersslowOID));
+  registerCounter64Stat("auth6-answers0-1", auth6Answers01OID, OID_LENGTH(auth6Answers01OID));
+  registerCounter64Stat("auth6-answers1-10", auth6Answers110OID, OID_LENGTH(auth6Answers110OID));
+  registerCounter64Stat("auth6-answers10-100", auth6Answers10100OID, OID_LENGTH(auth6Answers10100OID));
+  registerCounter64Stat("auth6-answers100-1000", auth6Answers1001000OID, OID_LENGTH(auth6Answers1001000OID));
+  registerCounter64Stat("auth6-answers-slow", auth6AnswersSlowOID, OID_LENGTH(auth6AnswersSlowOID));
+  registerCounter64Stat("qa-latency", qaLatencyOID, OID_LENGTH(qaLatencyOID));
+  registerCounter64Stat("unexpected-packets", unexpectedPacketsOID, OID_LENGTH(unexpectedPacketsOID));
+  registerCounter64Stat("case-mismatches", caseMismatchesOID, OID_LENGTH(caseMismatchesOID));
+  registerCounter64Stat("spoof-prevents", spoofPreventsOID, OID_LENGTH(spoofPreventsOID));
+  registerCounter64Stat("nsset-invalidations", nssetInvalidationsOID, OID_LENGTH(nssetInvalidationsOID));
+  registerCounter64Stat("resource-limits", resourceLimitsOID, OID_LENGTH(resourceLimitsOID));
+  registerCounter64Stat("over-capacity-drops", overCapacityDropsOID, OID_LENGTH(overCapacityDropsOID));
+  registerCounter64Stat("policy-drops", policyDropsOID, OID_LENGTH(policyDropsOID));
+  registerCounter64Stat("no-packet-error", noPacketErrorOID, OID_LENGTH(noPacketErrorOID));
+  registerCounter64Stat("dlg-only-drops", dlgOnlyDropsOID, OID_LENGTH(dlgOnlyDropsOID));
+  registerCounter64Stat("ignored-packets", ignoredPacketsOID, OID_LENGTH(ignoredPacketsOID));
+  registerCounter64Stat("max-mthread-stack", maxMthreadStackOID, OID_LENGTH(maxMthreadStackOID));
+  registerCounter64Stat("negcache-entries", negcacheEntriesOID, OID_LENGTH(negcacheEntriesOID));
+  registerCounter64Stat("throttle-entries", throttleEntriesOID, OID_LENGTH(throttleEntriesOID));
+  registerCounter64Stat("nsspeeds-entries", nsspeedsEntriesOID, OID_LENGTH(nsspeedsEntriesOID));
+  registerCounter64Stat("failed-host-entries", failedHostEntriesOID, OID_LENGTH(failedHostEntriesOID));
+  registerCounter64Stat("concurrent-queries", concurrentQueriesOID, OID_LENGTH(concurrentQueriesOID));
+  registerCounter64Stat("security-status", securityStatusOID, OID_LENGTH(securityStatusOID));
+  registerCounter64Stat("outgoing-timeouts", outgoingTimeoutsOID, OID_LENGTH(outgoingTimeoutsOID));
+  registerCounter64Stat("outgoing4-timeouts", outgoing4TimeoutsOID, OID_LENGTH(outgoing4TimeoutsOID));
+  registerCounter64Stat("outgoing6-timeouts", outgoing6TimeoutsOID, OID_LENGTH(outgoing6TimeoutsOID));
+  registerCounter64Stat("tcp-outqueries", tcpOutqueriesOID, OID_LENGTH(tcpOutqueriesOID));
+  registerCounter64Stat("all-outqueries", allOutqueriesOID, OID_LENGTH(allOutqueriesOID));
+  registerCounter64Stat("ipv6-outqueries", ipv6OutqueriesOID, OID_LENGTH(ipv6OutqueriesOID));
+  registerCounter64Stat("throttled-outqueries", throttledOutqueriesOID, OID_LENGTH(throttledOutqueriesOID));
+  registerCounter64Stat("dont-outqueries", dontOutqueriesOID, OID_LENGTH(dontOutqueriesOID));
+  registerCounter64Stat("unreachables", unreachablesOID, OID_LENGTH(unreachablesOID));
+  registerCounter64Stat("chain-resends", chainResendsOID, OID_LENGTH(chainResendsOID));
+  registerCounter64Stat("tcp-clients", tcpClientsOID, OID_LENGTH(tcpClientsOID));
+#ifdef __linux__
+  registerCounter64Stat("udp-recvbuf-errors", udpRecvbufErrorsOID, OID_LENGTH(udpRecvbufErrorsOID));
+  registerCounter64Stat("udp-sndbuf-errors", udpSndbufErrorsOID, OID_LENGTH(udpSndbufErrorsOID));
+  registerCounter64Stat("udp-noport-errors", udpNoportErrorsOID, OID_LENGTH(udpNoportErrorsOID));
+  registerCounter64Stat("udp-in-errors", udpinErrorsOID, OID_LENGTH(udpinErrorsOID));
+#endif /* __linux__ */
+  registerCounter64Stat("edns-ping-matches", ednsPingMatchesOID, OID_LENGTH(ednsPingMatchesOID));
+  registerCounter64Stat("edns-ping-mismatches", ednsPingMismatchesOID, OID_LENGTH(ednsPingMismatchesOID));
+  registerCounter64Stat("dnssec-queries", dnssecQueriesOID, OID_LENGTH(dnssecQueriesOID));
+  registerCounter64Stat("noping-outqueries", nopingOutqueriesOID, OID_LENGTH(nopingOutqueriesOID));
+  registerCounter64Stat("noedns-outqueries", noednsOutqueriesOID, OID_LENGTH(noednsOutqueriesOID));
+  registerCounter64Stat("uptime", uptimeOID, OID_LENGTH(uptimeOID));
+  registerCounter64Stat("real-memory-usage", realMemoryUsageOID, OID_LENGTH(realMemoryUsageOID));
+  registerCounter64Stat("fd-usage", fdUsageOID, OID_LENGTH(fdUsageOID));
+  registerCounter64Stat("user-msec", userMsecOID, OID_LENGTH(userMsecOID));
+  registerCounter64Stat("sys-msec", sysMsecOID, OID_LENGTH(sysMsecOID));
+  registerCounter64Stat("dnssec-validations", dnssecValidationsOID, OID_LENGTH(dnssecValidationsOID));
+  registerCounter64Stat("dnssec-result-insecure", dnssecResultInsecureOID, OID_LENGTH(dnssecResultInsecureOID));
+  registerCounter64Stat("dnssec-result-secure", dnssecResultSecureOID, OID_LENGTH(dnssecResultSecureOID));
+  registerCounter64Stat("dnssec-result-bogus", dnssecResultBogusOID, OID_LENGTH(dnssecResultBogusOID));
+  registerCounter64Stat("dnssec-result-indeterminate", dnssecResultIndeterminateOID, OID_LENGTH(dnssecResultIndeterminateOID));
+  registerCounter64Stat("dnssec-result-nta", dnssecResultNtaOID, OID_LENGTH(dnssecResultNtaOID));
+  registerCounter64Stat("policy-result-noaction", policyResultNoactionOID, OID_LENGTH(policyResultNoactionOID));
+  registerCounter64Stat("policy-result-drop", policyResultDropOID, OID_LENGTH(policyResultDropOID));
+  registerCounter64Stat("policy-result-nxdomain", policyResultNxdomainOID, OID_LENGTH(policyResultNxdomainOID));
+  registerCounter64Stat("policy-result-nodata", policyResultNodataOID, OID_LENGTH(policyResultNodataOID));
+  registerCounter64Stat("policy-result-truncate", policyResultTruncateOID, OID_LENGTH(policyResultTruncateOID));
+  registerCounter64Stat("policy-result-custom", policyResultCustomOID, OID_LENGTH(policyResultCustomOID));
+
+#endif /* HAVE_NET_SNMP */
+}
diff --git a/pdns/rec-snmp.hh b/pdns/rec-snmp.hh
new file mode 100644 (file)
index 0000000..3ccc73f
--- /dev/null
@@ -0,0 +1,19 @@
+#ifndef REC_SNMP_HH
+#define REC_SNMP_HH
+
+#pragma once
+
+#include "snmp-agent.hh"
+
+class RecursorSNMPAgent;
+
+class RecursorSNMPAgent: public SNMPAgent
+{
+public:
+  RecursorSNMPAgent(const std::string& name, const std::string& masterSocket);
+  bool sendCustomTrap(const std::string& reason);
+};
+
+extern std::shared_ptr<RecursorSNMPAgent> g_snmpAgent;
+
+#endif /* REC_SNMP_HH */
index bbdf12ff90d4b56c802340760c3d364f42087048..168f3af80f91d10b84a8ad8b1908451fd135fb60 100644 (file)
@@ -73,4 +73,5 @@ std::vector<ComboAddress>* pleaseGetServfailRemotes();
 std::vector<ComboAddress>* pleaseGetLargeAnswerRemotes();
 DNSName getRegisteredName(const DNSName& dom);
 std::atomic<unsigned long>* getDynMetric(const std::string& str);
+optional<uint64_t> getStatByName(const std::string& name);
 #endif 
index c5397bc86ad4ee5fd836a38e385d043ea826f038..fa40d1d03e85870ffaf3d3669d871faae767820c 100644 (file)
@@ -98,6 +98,11 @@ optional<uint64_t> get(const string& name)
   return ret;
 }
 
+optional<uint64_t> getStatByName(const std::string& name)
+{
+  return get(name);
+}
+
 map<string,string> getAllStatsMap()
 {
   map<string,string> ret;
@@ -637,7 +642,7 @@ static string doCurrentQueries()
 
 uint64_t* pleaseGetThrottleSize()
 {
-  return new uint64_t(t_sstorage->throttle.size());
+  return new uint64_t(t_sstorage ? t_sstorage->throttle.size() : 0);
 }
 
 static uint64_t getThrottleSize()
@@ -647,7 +652,7 @@ static uint64_t getThrottleSize()
 
 uint64_t* pleaseGetNegCacheSize()
 {
-  uint64_t tmp=t_sstorage->negcache.size();
+  uint64_t tmp=(t_sstorage ? t_sstorage->negcache.size() : 0);
   return new uint64_t(tmp);
 }
 
@@ -658,7 +663,7 @@ uint64_t getNegCacheSize()
 
 uint64_t* pleaseGetFailedHostsSize()
 {
-  uint64_t tmp=t_sstorage->fails.size();
+  uint64_t tmp=(t_sstorage ? t_sstorage->fails.size() : 0);
   return new uint64_t(tmp);
 }
 uint64_t getFailedHostsSize()
@@ -668,7 +673,7 @@ uint64_t getFailedHostsSize()
 
 uint64_t* pleaseGetNsSpeedsSize()
 {
-  return new uint64_t(t_sstorage->nsSpeeds.size());
+  return new uint64_t(t_sstorage ? t_sstorage->nsSpeeds.size() : 0);
 }
 
 uint64_t getNsSpeedsSize()
@@ -678,7 +683,7 @@ uint64_t getNsSpeedsSize()
 
 uint64_t* pleaseGetConcurrentQueries()
 {
-  return new uint64_t(MT->numProcesses()); 
+  return new uint64_t(MT ? MT->numProcesses() : 0);
 }
 
 static uint64_t getConcurrentQueries()
@@ -688,12 +693,12 @@ static uint64_t getConcurrentQueries()
 
 uint64_t* pleaseGetCacheSize()
 {
-  return new uint64_t(t_RC->size());
+  return new uint64_t(t_RC ? t_RC->size() : 0);
 }
 
 uint64_t* pleaseGetCacheBytes()
 {
-  return new uint64_t(t_RC->bytes());
+  return new uint64_t(t_RC ? t_RC->bytes() : 0);
 }
 
 
@@ -715,7 +720,7 @@ uint64_t doGetCacheBytes()
 
 uint64_t* pleaseGetCacheHits()
 {
-  return new uint64_t(t_RC->cacheHits);
+  return new uint64_t(t_RC ? t_RC->cacheHits : 0);
 }
 
 uint64_t doGetCacheHits()
@@ -725,7 +730,7 @@ uint64_t doGetCacheHits()
 
 uint64_t* pleaseGetCacheMisses()
 {
-  return new uint64_t(t_RC->cacheMisses);
+  return new uint64_t(t_RC ? t_RC->cacheMisses : 0);
 }
 
 uint64_t doGetCacheMisses()
@@ -736,12 +741,12 @@ uint64_t doGetCacheMisses()
 
 uint64_t* pleaseGetPacketCacheSize()
 {
-  return new uint64_t(t_packetCache->size());
+  return new uint64_t(t_packetCache ? t_packetCache->size() : 0);
 }
 
 uint64_t* pleaseGetPacketCacheBytes()
 {
-  return new uint64_t(t_packetCache->bytes());
+  return new uint64_t(t_packetCache ? t_packetCache->bytes() : 0);
 }
 
 
@@ -758,7 +763,7 @@ uint64_t doGetPacketCacheBytes()
 
 uint64_t* pleaseGetPacketCacheHits()
 {
-  return new uint64_t(t_packetCache->d_hits);
+  return new uint64_t(t_packetCache ? t_packetCache->d_hits : 0);
 }
 
 uint64_t doGetPacketCacheHits()
@@ -768,7 +773,7 @@ uint64_t doGetPacketCacheHits()
 
 uint64_t* pleaseGetPacketCacheMisses()
 {
-  return new uint64_t(t_packetCache->d_misses);
+  return new uint64_t(t_packetCache ? t_packetCache->d_misses : 0);
 }
 
 uint64_t doGetPacketCacheMisses()
index 90004d7297e426b8368a6ce0cb165bd557163c6f..1cca8d68634721fe9efbd1f4be91f6c700f95366 100644 (file)
@@ -1,6 +1,6 @@
 JSON11_LIBS = $(top_srcdir)/ext/json11/libjson11.la
 
-AM_CPPFLAGS = $(LUA_CFLAGS) $(YAHTTP_CFLAGS) $(BOOST_CPPFLAGS) $(BOTAN110_CFLAGS) $(SANITIZER_FLAGS) -O3 -Wall -pthread -DSYSCONFDIR=\"${sysconfdir}\" $(SYSTEMD_CFLAGS)
+AM_CPPFLAGS = $(LUA_CFLAGS) $(YAHTTP_CFLAGS) $(BOOST_CPPFLAGS) $(BOTAN110_CFLAGS) $(NET_SNMP_CFLAGS) $(SANITIZER_FLAGS) -O3 -Wall -pthread -DSYSCONFDIR=\"${sysconfdir}\" $(SYSTEMD_CFLAGS)
 
 AM_CPPFLAGS += \
        -I$(top_srcdir)/ext/json11 \
@@ -110,6 +110,7 @@ pdns_recursor_SOURCES = \
        rec-carbon.cc \
        rec-lua-conf.hh rec-lua-conf.cc \
        rec-protobuf.cc rec-protobuf.hh \
+       rec-snmp.hh rec-snmp.cc \
        rec_channel.cc rec_channel.hh \
        rec_channel_rec.cc \
        recpacketcache.cc recpacketcache.hh \
@@ -127,6 +128,7 @@ pdns_recursor_SOURCES = \
        selectmplexer.cc \
        sholder.hh \
        sillyrecords.cc \
+       snmp-agent.hh snmp-agent.cc \
        sortlist.cc sortlist.hh \
        sstuff.hh \
        syncres.cc syncres.hh \
@@ -152,6 +154,7 @@ pdns_recursor_LDADD = \
        $(JSON11_LIBS) \
        $(LIBCRYPTO_LIBS) \
        $(BOOST_CONTEXT_LIBS) \
+       $(NET_SNMP_LIBS) \
        $(SYSTEMD_LIBS) \
        $(RT_LIBS)
 
index 64b3af7e3c2b6867ce70d687ef83fcd4da7e74d5..7a0be912965b83cf77991d70d82c316a9faae583 100644 (file)
@@ -113,6 +113,8 @@ PDNS_CHECK_LIBCRYPTO([
 )
 PDNS_CHECK_LIBCRYPTO_ECDSA
 
+PDNS_WITH_NET_SNMP
+
 # check for tools we might need
 PDNS_CHECK_RAGEL
 PDNS_CHECK_CURL
@@ -205,6 +207,10 @@ AS_IF([test "x$PROTOBUF_LIBS" != "x" -a x"$PROTOC" != "x"],
   [AC_MSG_NOTICE([Protobuf: yes])],
   [AC_MSG_NOTICE([Protobuf: no])]
 )
+AS_IF([test "x$NET_SNMP_LIBS" != "x"],
+  [AC_MSG_NOTICE([SNMP: yes])],
+  [AC_MSG_NOTICE([SNMP: no])]
+)
 AS_IF([test "x$systemd" != "xn"],
   [AC_MSG_NOTICE([systemd: yes])],
   [AC_MSG_NOTICE([systemd: no])]
diff --git a/pdns/recursordist/m4/pdns_with_net_snmp.m4 b/pdns/recursordist/m4/pdns_with_net_snmp.m4
new file mode 120000 (symlink)
index 0000000..676095b
--- /dev/null
@@ -0,0 +1 @@
+../../../m4/pdns_with_net_snmp.m4
\ No newline at end of file
diff --git a/pdns/recursordist/rec-snmp.cc b/pdns/recursordist/rec-snmp.cc
new file mode 120000 (symlink)
index 0000000..9883d66
--- /dev/null
@@ -0,0 +1 @@
+../rec-snmp.cc
\ No newline at end of file
diff --git a/pdns/recursordist/rec-snmp.hh b/pdns/recursordist/rec-snmp.hh
new file mode 120000 (symlink)
index 0000000..b34bdac
--- /dev/null
@@ -0,0 +1 @@
+../rec-snmp.hh
\ No newline at end of file
diff --git a/pdns/recursordist/snmp-agent.cc b/pdns/recursordist/snmp-agent.cc
new file mode 120000 (symlink)
index 0000000..d786b47
--- /dev/null
@@ -0,0 +1 @@
+../snmp-agent.cc
\ No newline at end of file
diff --git a/pdns/recursordist/snmp-agent.hh b/pdns/recursordist/snmp-agent.hh
new file mode 120000 (symlink)
index 0000000..b5ddc99
--- /dev/null
@@ -0,0 +1 @@
+../snmp-agent.hh
\ No newline at end of file