]> granicus.if.org Git - pdns/commitdiff
dnsdist: Add `help()` and `showVersion()`
authorRemi Gacogne <remi.gacogne@powerdns.com>
Tue, 9 Aug 2016 14:07:26 +0000 (16:07 +0200)
committerRemi Gacogne <remi.gacogne@powerdns.com>
Wed, 10 Aug 2016 19:41:21 +0000 (21:41 +0200)
pdns/README-dnsdist.md
pdns/dnsdist-console.cc
pdns/dnsdist-lua2.cc
pdns/dnsdist.hh

index 88d74d0607ec08bbb88715dfe49d3411d60a0845..bd91fa39003dec15b9d89791aeddebe88d52b681 100644 (file)
@@ -1170,7 +1170,7 @@ Here are all functions:
     * `carbonServer(serverIP, [ourname], [interval])`: report statistics to serverIP using our hostname, or 'ourname' if provided, every 'interval' seconds
  * Control socket related:
     * `makeKey()`: generate a new server access key, emit configuration line ready for pasting
-    * `setKey(key)`: set access key to that key. 
+    * `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
@@ -1179,10 +1179,11 @@ Here are all functions:
     * `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   
+    * `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
     * `showResponseLatency()`: show a plot of the response time latency distribution
+    * `showVersion()`: show the current version of dnsdist
  * Logging related
     * `infolog(string)`: log at level info
     * `warnlog(string)`: log at level warning
@@ -1245,7 +1246,8 @@ instantiate a server with additional parameters
     * `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()`)
-    * `showRules()`: show all defined rules (Pool, Block, QPS, addAnyTCRule)
+    * `showResponseRules()`: show all defined response rules
+    * `showRules()`: show all defined rules
     * `topResponseRule()`: move the last response rule to the first position
     * `topRule()`: move the last rule to the first position
  * Built-in Actions for Rules:
@@ -1272,7 +1274,7 @@ instantiate a server with additional 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()`: move queries requesting DNSSEC processing to this pool
+    * `setDNSSECPool(pool)`: move queries requesting DNSSEC processing to this pool
  * Policy member data:
     * `name`: the policy name
     * `policy`: the policy function
index 1b37daac165ea372ae706177f3aad6b4a1640f5d..4a7f05412a8f1d8caf679c606ccb36c896144d05 100644 (file)
@@ -219,56 +219,143 @@ void doConsole()
   }
 }
 /**** CARGO CULT CODE AHEAD ****/
+const std::vector<ConsoleKeyword> g_consoleKeywords{
+  /* keyword, function, parameters, description */
+  { "addACL", true, "netmask", "add to the ACL set who can use this server" },
+  { "addAction", true, "DNS rule, DNS action", "add a rule" },
+  { "addAnyTCRule", true, "", "generate TC=1 answers to ANY queries received over UDP, moving them to TCP" },
+  { "addDelay", true, "domain, n", "delay answers within that domain by n milliseconds" },
+  { "addDisableValidationRule", true, "DNS rule", "set the CD flags to 1 for all queries matching the specified domain" },
+  { "addDNSCryptBind", true, "\"127.0.0.1:8443\", \"provider name\", \"/path/to/resolver.cert\", \"/path/to/resolver.key\", [false], [TCP Fast Open queue size]", "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 optional parameter sets SO_REUSEPORT when available. The last parameter sets the TCP Fast Open queue size, enabling TCP Fast Open when available and the value is larger than 0" },
+  { "addDomainBlock", true, "domain", "block queries within this domain" },
+  { "addDomainSpoof", true, "domain, ip[, ip6]", "generate answers for A/AAAA/ANY queries using the ip parameters" },
+  { "addDynBlocks", true, "addresses, message[, seconds]", "block the set of addresses with message `msg`, for `seconds` seconds (10 by default)" },
+  { "addLocal", true, "netmask, [true], [false], [TCP Fast Open queue size]", "add to addresses we listen on. Second optional parameter sets TCP or not. Third optional parameter sets SO_REUSEPORT when available. Last parameter sets the TCP Fast Open queue size, enabling TCP Fast Open when available and the value is larger than 0" },
+  { "addLuaAction", true, "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. Good for rare packets but where you want to do a lot of processing" },
+  { "addNoRecurseRule", true, "domain", "clear the RD flag for all queries matching the specified domain" },
+  { "addPoolRule", true, "domain, pool", "send queries to this domain to that pool" },
+  { "addQPSLimit", true, "domain, n", "limit queries within that domain to n per second" },
+  { "addQPSPoolRule", true, "x, limit, pool", "like `addPoolRule`, but only select at most 'limit' queries/s for this pool, letting the subsequent rules apply otherwise" },
+  { "addResponseAction", true, "DNS rule, DNS response action", "add a response rule" },
+  { "AllowAction", true, "", "let these packets go through" },
+  { "AllRule", true, "", "matches all traffic" },
+  { "AndRule", true, "list of DNS rules", "matches if all sub-rules matches" },
+  { "benchRule", true, "DNS Rule [, iterations [, suffix]]", "bench the specified DNS rule" },
+  { "carbonServer", true, "serverIP, [ourname], [interval]", "report statistics to serverIP using our hostname, or 'ourname' if provided, every 'interval' seconds" },
+  { "controlSocket", true, "addr", "open a control socket on this address / connect to this address in client mode" },
+  { "clearDynBlocks", true, "", "clear all dynamic blocks" },
+  { "clearRules", true, "", "remove all current rules" },
+  { "DelayAction", true, "milliseconds", "delay the response by the specified amount of milliseconds (UDP-only)" },
+  { "delta", true, "", "shows all commands entered that changed the configuration" },
+  { "DisableValidationAction", true, "", "set the CD bit in the question, let it go through" },
+  { "DropAction", true, "", "drop these packets" },
+  { "dumpStats", true, "", "print all statistics we gather" },
+  { "exceedNXDOMAINs", true, "rate, seconds", "get set of addresses that exceed `rate` NXDOMAIN/s over `seconds` seconds" },
+  { "exceedQRate", true, "rate, seconds", "get set of address that exceed `rate` queries/s over `seconds` seconds" },
+  { "exceedQTypeRate", true, "type, rate, seconds", "get set of address that exceed `rate` queries/s for queries of type `type` over `seconds` seconds" },
+  { "exceedRespByterate", true, "rate, seconds", "get set of addresses that exeeded `rate` bytes/s answers over `seconds` seconds" },
+  { "exceedServFails", true, "rate, seconds", "get set of addresses that exceed `rate` servails/s over `seconds` seconds" },
+  { "firstAvailable", false, "", "picks the server with the lowest `order` that has not exceeded its QPS limit" },
+  { "fixupCase", true, "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" },
+  { "generateDNSCryptCertificate", true, "\"/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` timestamp until the `validUntil` one, signed with the provider private key" },
+  { "generateDNSCryptProviderKeys", true, "\"/path/to/providerPublic.key\", \"/path/to/providerPrivate.key\"", "generate a new provider keypair"},
+  { "getPoolServers", true, "pool", "return servers part of this pool" },
+  { "getResponseRing", true, "", "return the current content of the response ring" },
+  { "getServer", true, "n", "returns server with index n" },
+  { "getServers", true, "", "returns a table with all defined servers" },
+  { "grepq", true, "Netmask|DNS Name|100ms|{\"::1\", \"powerdns.com\", \"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" },
+  { "leastOutstanding", false, "", "Send traffic to downstream server with least outstanding queries, with the lowest 'order', and within that the lowest recent latency"},
+  { "LogAction", true, "[filename], [binary]", "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" },
+  { "makeKey", true, "", "generate a new server access key, emit configuration line ready for pasting" },
+  { "MaxQPSIPRule", true, "qps, v4Mask=32, v6Mask=64", "matches traffic exceeding the qps limit per subnet" },
+  { "MaxQPSRule", true, "qps", "matches traffic **not** exceeding this qps limit" },
+  { "mvResponseRule", true, "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" },
+  { "mvRule", true, "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" },
+  { "newDNSName", true, "name", "make a DNSName based on this .-terminated name" },
+  { "newQPSLimiter", true, "rate, burst", "configure a QPS limiter with that rate and that burst capacity" },
+  { "newRemoteLogger", true, "address:port [, timeout=2, maxQueuedEntries=100, reconnectWaitTime=1]", "create a Remote Logger object, to use with `RemoteLogAction()` and `RemoteLogResponseAction()`" },
+  { "newRuleAction", true, "DNS rule, DNS action", "return a pair of DNS Rule and DNS Action, to be used with `setRules()`" },
+  { "newServer", true, "{address=\"ip:port\", qps=1000, order=1, weight=10, pool=\"abuse\", retries=5, tcpSendTimeout=30, tcpRecvTimeout=30, checkName=\"a.root-servers.net.\", checkType=\"A\", maxCheckFailures=1, mustResolve=false, useClientSubnet=true, source=\"address|interface name|address@interface\"", "instantiate a server" },
+  { "newServerPolicy", true, "name, function", "create a policy object from a Lua function" },
+  { "newSuffixMatchNode", true, "", "returns a new SuffixMatchNode" },
+  { "NoRecurseAction", true, "", "strip RD bit from the question, let it go through" },
+  { "PoolAction", true, "poolname", "set the packet into the specified pool" },
+  { "printDNSCryptProviderFingerprint", true, "\"/path/to/providerPublic.key\"", "display the fingerprint of the provided resolver public key" },
+  { "RegexRule", true, "regex", "matches the query name against the supplied regex" },
+  { "RemoteLogAction", true, "RemoteLogger", "send the content of this query to a remote logger via Protocol Buffer" },
+  { "RemoteLogResponseAction", true, "RemoteLogger", "send the content of this response to a remote logger via Protocol Buffer" },
+  { "rmResponseRule", true, "n", "remove response rule n" },
+  { "rmRule", true, "n", "remove rule n" },
+  { "rmServer", true, "n", "remove server with index n" },
+  { "roundrobin", false, "", "Simple round robin over available servers" },
+  { "QNameLabelsCountRule", true, "min, max", "matches if the qname has less than `min` or more than `max` labels" },
+  { "QNameWireLengthRule", true, "min, max", "matches if the qname's length on the wire is less than `min` or more than `max` bytes" },
+  { "QTypeRule", true, "qtype", "matches queries with the specified qtype" },
+  { "setACL", true, "{netmask, netmask}", "replace the ACL set with these netmasks. Use `setACL({})` to reset the list, meaning no one can use us" },
+  { "setDNSSECPool", true, "pool name", "move queries requesting DNSSEC processing to this pool" },
+  { "setECSOverride", true, "bool", "whether to override an existing EDNS Client Subnet value in the query" },
+  { "setECSSourcePrefixV4", true, "prefix-length", "the EDNS Client Subnet prefix-length used for IPv4 queries" },
+  { "setECSSourcePrefixV6", true, "prefix-length", "the EDNS Client Subnet prefix-length used for IPv6 queries" },
+  { "setKey", true, "key", "set access key to that key" },
+  { "setLocal", true, "netmask, [true], [false], [TCP Fast Open queue size]", "reset list of addresses we listen on to this address. Second optional parameter sets TCP or not. Third optional parameter sets SO_REUSEPORT when available. Last parameter sets the TCP Fast Open queue size, enabling TCP Fast Open when available and the value is larger than 0." },
+  { "setMaxTCPClientThreads", true, "n", "set the maximum of TCP client threads, handling TCP connections" },
+  { "setMaxTCPQueuedConnections", true, "n", "set the maximum number of TCP connections queued (waiting to be picked up by a client thread)" },
+  { "setMaxUDPOutstanding", true, "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" },
+  { "setRules", true, "list of rules", "replace the current rules with the supplied list of pairs of DNS Rules and DNS Actions (see `newRuleAction()`)" },
+  { "setServerPolicy", true, "policy", "set server selection policy to that policy" },
+  { "setServerPolicyLua", true, "name, function", "set server selection policy to one named 'name' and provided by 'function'" },
+  { "setTCPRecvTimeout", true, "n", "set the read timeout on TCP connections from the client, in seconds" },
+  { "setTCPSendTimeout", true, "n", "set the write timeout on TCP connections from the client, in seconds" },
+  { "setVerboseHealthChecks", true, "bool", "set whether health check errors will be logged" },
+  { "show", true, "string", "outputs `string`" },
+  { "showACL", true, "", "show our ACL set" },
+  { "showDNSCryptBinds", true, "", "display the currently configured DNSCrypt binds" },
+  { "showDynBlocks", true, "", "show dynamic blocks in force" },
+  { "showResponseLatency", true, "", "show a plot of the response time latency distribution" },
+  { "showResponseRules", true, "", "show all defined response rules" },
+  { "showRules", true, "", "show all defined rules" },
+  { "showServerPolicy", true, "", "show name of currently operational server selection policy" },
+  { "showServers", true, "", "output all servers" },
+  { "showVersion", true, "", "show the current version" },
+  { "shutdown", true, "", "shut down `dnsdist`" },
+  { "SpoofAction", true, "{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" },
+  { "TCAction", true, "", "create answer to query with TC and RD bits set, to move to TCP" },
+  { "testCrypto", true, "", "test of the crypto all works" },
+  { "topBandwidth", true, "top", "show top-`top` clients that consume the most bandwidth over length of ringbuffer" },
+  { "topClients", true, "n", "show top-`n` clients sending the most queries over length of ringbuffer" },
+  { "topQueries", true, "n[, labels]", "show top 'n' queries, as grouped when optionally cut down to 'labels' labels" },
+  { "topResponses", true, "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" },
+  { "topResponseRule", true, "", "move the last response rule to the first position" },
+  { "topRule", true, "", "move the last rule to the first position" },
+  { "topSlow", true, "[top][, limit][, labels]", "show `top` queries slower than `limit` milliseconds, grouped by last `labels` labels" },
+  { "truncateTC", true, "bool", "if set (default) truncate TC=1 answers so they are actually empty. Fixes an issue for PowerDNS Authoritative Server 2.9.22" },
+  { "webserver", true, "address:port, password [, apiKey [, customHeaders ]])", "launch a webserver with stats on that address with that password" },
+  { "whashed", false, "", "Weighted hashed ('sticky') distribution over available servers, based on the server 'weight' parameter" },
+  { "wrandom", false, "", "Weighted random over available servers, based on the server 'weight' parameter" },
+};
+
 extern "C" {
 char* my_generator(const char* text, int state)
 {
   string t(text);
   /* to keep it readable, we try to keep only 4 keywords per line
      and to start a new line when the first letter changes */
-  vector<string> words{"addACL(", "addAction(", "addAnyTCRule()", "addDelay(",
-      "addDisableValidationRule(", "addDNSCryptBind(", "addDomainBlock(",
-      "addDomainSpoof(", "addDynBlocks(", "addLocal(", "addLuaAction(",
-      "addNoRecurseRule(", "addPoolRule(", "addQPSLimit(", "addQPSPoolRule(",
-      "addResponseAction(",
-      "AllowAction(", "AllRule(", "AndRule(",
-      "benchRule(",
-      "carbonServer(", "controlSocket(", "clearDynBlocks()", "clearRules(",
-      "DelayAction(", "delta()", "DisableValidationAction(", "DropAction(",
-      "dumpStats()",
-      "exceedNXDOMAINs(", "exceedQRate(", "exceedQTypeRate(", "exceedRespByterate(",
-      "exceedServFails(",
-      "firstAvailable", "fixupCase(",
-      "generateDNSCryptCertificate(", "generateDNSCryptProviderKeys(", "getPoolServers(", "getResponseRing(",
-      "getServer(", "getServers()", "grepq(",
-      "leastOutstanding", "LogAction(",
-      "makeKey()", "MaxQPSIPRule(", "MaxQPSRule(", "mvResponseRule(",
-      "mvRule(",
-      "newDNSName(", "newQPSLimiter(", "newRemoteLogger(", "newRuleAction(", "newServer(",
-      "newServerPolicy(", "newSuffixMatchNode(", "NoRecurseAction(",
-      "PoolAction(", "printDNSCryptProviderFingerprint(",
-      "RegexRule(", "RemoteLogAction(", "RemoteLogResponseAction(", "rmResponseRule(",
-      "rmRule(", "rmServer(", "roundrobin",
-      "QNameLabelsCountRule(", "QNameWireLengthRule(", "QTypeRule(",
-      "setACL(", "setDNSSECPool(", "setECSOverride(",
-      "setECSSourcePrefixV4(", "setECSSourcePrefixV6(", "setKey(", "setLocal(",
-      "setMaxTCPClientThreads(", "setMaxTCPQueuedConnections(", "setMaxUDPOutstanding(", "setRules(",
-      "setServerPolicy(", "setServerPolicyLua(",
-      "setTCPRecvTimeout(", "setTCPSendTimeout(", "setVerboseHealthChecks(", "show(", "showACL()",
-      "showDNSCryptBinds()", "showDynBlocks()", "showResponseLatency()", "showResponseRules()",
-      "showRules()", "showServerPolicy()", "showServers()", "shutdown()", "SpoofAction(",
-      "TCAction(", "testCrypto()", "topBandwidth(", "topClients(",
-      "topQueries(", "topResponses(", "topResponseRule()", "topRule()", "topSlow(",
-      "truncateTC(",
-      "webserver(", "whashed", "wrandom" };
   static int s_counter=0;
   int counter=0;
   if(!state)
     s_counter=0;
 
-  for(auto w : words) {
-    if(boost::starts_with(w, t) && counter++ == s_counter)  {
+  for(const auto& keyword : g_consoleKeywords) {
+    if(boost::starts_with(keyword.name, t) && counter++ == s_counter)  {
+      std::string value(keyword.name);
       s_counter++;
-      return strdup(w.c_str());
+      if (keyword.function) {
+        value += "(";
+        if (keyword.parameters.empty()) {
+          value += ")";
+        }
+      }
+      return strdup(value.c_str());
     }
   }
   return 0;
index 08ef7c9529c428e40b82bc638b2c9a865e21f552..12066df03a3e88110cd7dbda32fbdc8fe44d44e5 100644 (file)
@@ -796,6 +796,28 @@ void moreLua(bool client)
         return fe.local.toStringWithPort();
       });
 
+    g_lua.writeFunction("help", [](boost::optional<std::string> command) {
+        setLuaNoSideEffect();
+        g_outputBuffer = "";
+        for (const auto& keyword : g_consoleKeywords) {
+          if (!command) {
+            g_outputBuffer += keyword.toString() + "\n";
+          }
+          else if (keyword.name == command) {
+            g_outputBuffer = keyword.toString() + "\n";
+            return;
+          }
+        }
+        if (command) {
+          g_outputBuffer = "Nothing found for " + *command + "\n";
+        }
+      });
+
+    g_lua.writeFunction("showVersion", []() {
+        setLuaNoSideEffect();
+        g_outputBuffer = "dnsdist " + std::string(VERSION) + "\n";
+      });
+
 #ifdef HAVE_EBPF
     g_lua.writeFunction("newBPFFilter", [](uint32_t maxV4, uint32_t maxV6, uint32_t maxQNames) {
         return std::make_shared<BPFFilter>(maxV4, maxV6, maxQNames);
index ee9d2e9719250a03ff08ba382b08c3060583badb..a91fd16e64e0567209007bcae865fb4f5651703c 100644 (file)
@@ -609,6 +609,24 @@ extern bool g_ECSOverride;
 extern bool g_verboseHealthChecks;
 extern uint32_t g_staleCacheEntriesTTL;
 
+struct ConsoleKeyword {
+  std::string name;
+  bool function;
+  std::string parameters;
+  std::string description;
+  std::string toString() const
+  {
+    std::string res(name);
+    if (function) {
+      res += "(" + parameters + ")";
+    }
+    res += ": ";
+    res += description;
+    return res;
+  }
+};
+extern const std::vector<ConsoleKeyword> g_consoleKeywords;
+
 #ifdef HAVE_EBPF
 extern shared_ptr<BPFFilter> g_defaultBPFFilter;
 #endif /* HAVE_EBPF */