]>
Commit | Line | Data |
---|---|---|
12c86877 | 1 | /* |
12471842 PL |
2 | * This file is part of PowerDNS or dnsdist. |
3 | * Copyright -- PowerDNS.COM B.V. and its contributors | |
4 | * | |
5 | * This program is free software; you can redistribute it and/or modify | |
6 | * it under the terms of version 2 of the GNU General Public License as | |
7 | * published by the Free Software Foundation. | |
8 | * | |
9 | * In addition, for the avoidance of any doubt, permission is granted to | |
10 | * link this program with OpenSSL and to (re)distribute the binaries | |
11 | * produced as the result of such linking. | |
12 | * | |
13 | * This program is distributed in the hope that it will be useful, | |
14 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | |
15 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |
16 | * GNU General Public License for more details. | |
17 | * | |
18 | * You should have received a copy of the GNU General Public License | |
19 | * along with this program; if not, write to the Free Software | |
20 | * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. | |
21 | */ | |
870a0fe4 AT |
22 | #ifdef HAVE_CONFIG_H |
23 | #include "config.h" | |
24 | #endif | |
619e8acc | 25 | #include "common_startup.hh" |
2470b36e | 26 | #include "ws-auth.hh" |
199631c6 | 27 | #include "secpoll-auth.hh" |
e903706d | 28 | #include <sys/time.h> |
29 | #include <sys/resource.h> | |
f45a622c | 30 | #include "dynhandler.hh" |
82ee5aa5 | 31 | #include "dnsseckeeper.hh" |
519f5484 | 32 | #include "threadname.hh" |
2211dac9 | 33 | #include "misc.hh" |
fa8fd4d2 | 34 | |
c2826d2e RG |
35 | #include <thread> |
36 | ||
6988eae9 PL |
37 | #ifdef HAVE_SYSTEMD |
38 | #include <systemd/sd-daemon.h> | |
39 | #endif | |
b653a73d | 40 | |
357f6a75 | 41 | bool g_anyToTcp; |
fc41a1a6 | 42 | bool g_8bitDNS; |
8900e2e3 | 43 | #ifdef HAVE_LUA_RECORDS |
cb6bd1a9 | 44 | bool g_doLuaRecord; |
af68014f | 45 | int g_luaRecordExecLimit; |
8900e2e3 | 46 | #endif |
619e8acc BH |
47 | typedef Distributor<DNSPacket,DNSPacket,PacketHandler> DNSDistributor; |
48 | ||
619e8acc | 49 | ArgvMap theArg; |
abc1d928 | 50 | StatBag S; //!< Statistics are gathered across PDNS via the StatBag class S |
bf269e28 RG |
51 | AuthPacketCache PC; //!< This is the main PacketCache, shared across all threads |
52 | AuthQueryCache QC; | |
c2826d2e RG |
53 | std::unique_ptr<DNSProxy> DP{nullptr}; |
54 | std::unique_ptr<DynListener> dl{nullptr}; | |
619e8acc | 55 | CommunicatorClass Communicator; |
12f224ab | 56 | shared_ptr<UDPNameserver> N; |
619e8acc | 57 | int avg_latency; |
8c98b341 | 58 | unique_ptr<TCPNameserver> TN; |
12f224ab RG |
59 | static vector<DNSDistributor*> g_distributors; |
60 | vector<std::shared_ptr<UDPNameserver> > g_udpReceivers; | |
619e8acc BH |
61 | |
62 | ArgvMap &arg() | |
63 | { | |
64 | return theArg; | |
65 | } | |
66 | ||
619e8acc BH |
67 | void declareArguments() |
68 | { | |
709cbf16 CH |
69 | ::arg().set("config-dir","Location of configuration directory (pdns.conf)")=SYSCONFDIR; |
70 | ::arg().set("config-name","Name of this virtual configuration - will rename the binary image")=""; | |
2dfe5b32 | 71 | ::arg().set("socket-dir",string("Where the controlsocket will live, ")+LOCALSTATEDIR+"/pdns when unset and not chrooted" )=""; |
709cbf16 CH |
72 | ::arg().set("module-dir","Default directory for modules")=PKGLIBDIR; |
73 | ::arg().set("chroot","If set, chroot to this directory for more security")=""; | |
74 | ::arg().set("logging-facility","Log under a specific facility")=""; | |
75 | ::arg().set("daemon","Operate as a daemon")="no"; | |
76 | ||
dea466f3 | 77 | ::arg().set("local-port","The port on which we listen")="53"; |
d07bf7ff | 78 | ::arg().setSwitch("dnsupdate","Enable/Disable DNS update (RFC2136) support. Default is no.")="no"; |
191f2e47 | 79 | ::arg().setSwitch("write-pid","Write a PID file")="yes"; |
71f758e0 | 80 | ::arg().set("allow-dnsupdate-from","A global setting to allow DNS updates from these IP ranges.")="127.0.0.0/8,::1"; |
ac340505 | 81 | ::arg().setSwitch("send-signed-notify","Send TSIG secured NOTIFY if TSIG key is configured for a domain")="yes"; |
771bb0b0 AT |
82 | ::arg().set("allow-unsigned-notify","Allow unsigned notifications for TSIG secured domains")="yes"; //FIXME: change to 'no' later |
83 | ::arg().set("allow-unsigned-supermaster", "Allow supermasters to create zones without TSIG signed NOTIFY")="yes"; | |
71f758e0 | 84 | ::arg().setSwitch("forward-dnsupdate","A global setting to allow DNS update packages that are for a Slave domain, to be forwarded to the master.")="yes"; |
cfccf353 | 85 | ::arg().setSwitch("log-dns-details","If PDNS should log DNS non-erroneous details")="no"; |
21a303f3 | 86 | ::arg().setSwitch("log-dns-queries","If PDNS should log all incoming DNS queries")="no"; |
dea466f3 | 87 | ::arg().set("local-address","Local IP addresses to which we bind")="0.0.0.0"; |
5ecb2885 | 88 | ::arg().setSwitch("local-address-nonexist-fail","Fail to start if one or more of the local-address's do not exist on this server")="yes"; |
fec7dd5a | 89 | ::arg().setSwitch("non-local-bind", "Enable binding to non-local addresses by using FREEBIND / BINDANY socket options")="no"; |
53b1ea52 | 90 | ::arg().set("local-ipv6","Local IP address to which we bind")="::"; |
bca4751c | 91 | ::arg().setSwitch("reuseport","Enable higher performance on compliant kernels by using SO_REUSEPORT allowing each receiver thread to open its own socket")="no"; |
5ecb2885 | 92 | ::arg().setSwitch("local-ipv6-nonexist-fail","Fail to start if one or more of the local-ipv6 addresses do not exist on this server")="yes"; |
f2994f92 BH |
93 | ::arg().set("query-local-address","Source IP address for sending queries")="0.0.0.0"; |
94 | ::arg().set("query-local-address6","Source IPv6 address for sending queries")="::"; | |
e7e691cc | 95 | ::arg().set("overload-queue-length","Maximum queuelength moving to packetcache only")="0"; |
dea466f3 | 96 | ::arg().set("max-queue-length","Maximum queuelength before considering situation lost")="5000"; |
a1fe72a4 | 97 | |
dbcb3066 | 98 | ::arg().set("retrieval-threads", "Number of AXFR-retrieval threads for slave operation")="2"; |
536ab56f | 99 | ::arg().setSwitch("api", "Enable/disable the REST API (including HTTP listener)")="no"; |
479e0976 | 100 | ::arg().set("api-key", "Static pre-shared authentication key for access to the REST API")=""; |
b8cd24cc | 101 | ::arg().setSwitch("default-api-rectify","Default API-RECTIFY value for zones")="yes"; |
4dfe94ae | 102 | ::arg().setSwitch("dname-processing", "If we should support DNAME records")="no"; |
dea466f3 BH |
103 | |
104 | ::arg().setCmd("help","Provide a helpful message"); | |
105 | ::arg().setCmd("version","Output version and compilation date"); | |
106 | ::arg().setCmd("config","Provide configuration file on standard output"); | |
107 | ::arg().setCmd("list-modules","Lists all modules available"); | |
108 | ::arg().setCmd("no-config","Don't parse configuration file"); | |
619e8acc | 109 | |
dea466f3 BH |
110 | ::arg().set("version-string","PowerDNS version in packets - full, anonymous, powerdns or custom")="full"; |
111 | ::arg().set("control-console","Debugging switch - don't use")="no"; // but I know you will! | |
dea466f3 | 112 | ::arg().set("loglevel","Amount of logging. Higher is more. Do not set below 3")="4"; |
b6cfa948 | 113 | ::arg().set("disable-syslog","Disable logging to syslog, useful when running inside a supervisor that logs stdout")="no"; |
b18fa400 | 114 | ::arg().set("log-timestamp","Print timestamps in log lines")="yes"; |
dea466f3 | 115 | ::arg().set("default-soa-name","name to insert in the SOA record if none set in the backend")="a.misconfigured.powerdns.server"; |
4c538037 | 116 | ::arg().set("default-soa-mail","mail address to insert in the SOA record if none set in the backend")=""; |
dea466f3 | 117 | ::arg().set("distributor-threads","Default number of Distributor (backend) threads to start")="3"; |
8267bd2c | 118 | ::arg().set("signing-threads","Default number of signer threads to start")="3"; |
37e4a4c3 | 119 | ::arg().set("receiver-threads","Default number of receiver threads to start")="1"; |
dea466f3 | 120 | ::arg().set("queue-limit","Maximum number of milliseconds to queue a query")="1500"; |
8eccac19 | 121 | ::arg().set("resolver","Use this resolver for ALIAS and the internal stub resolver")="no"; |
e77145bb | 122 | ::arg().set("udp-truncation-threshold", "Maximum UDP response size before we truncate")="1232"; |
619e8acc | 123 | |
dea466f3 | 124 | ::arg().set("config-name","Name of this virtual configuration - will rename the binary image")=""; |
619e8acc | 125 | |
dea466f3 BH |
126 | ::arg().set("load-modules","Load this module - supply absolute or relative path")=""; |
127 | ::arg().set("launch","Which backends to launch and order to query them in")=""; | |
128 | ::arg().setSwitch("disable-axfr","Disable zonetransfers but do allow TCP queries")="no"; | |
cbdec4ae | 129 | ::arg().set("allow-axfr-ips","Allow zonetransfers only to these subnets")="127.0.0.0/8,::1"; |
68bb0e57 | 130 | ::arg().set("only-notify", "Only send AXFR NOTIFY to these IP addresses or netmasks")="0.0.0.0/0,::/0"; |
24d3239e | 131 | ::arg().set("also-notify", "When notifying a domain, also notify these nameservers")=""; |
d207ad63 | 132 | ::arg().set("allow-notify-from","Allow AXFR NOTIFY from these IP ranges. If empty, drop all incoming notifies.")="0.0.0.0/0,::/0"; |
8bc65f13 | 133 | ::arg().set("slave-cycle-interval","Schedule slave freshness checks once every .. seconds")="60"; |
040712e0 BH |
134 | |
135 | ::arg().set("tcp-control-address","If set, PowerDNS can be controlled over TCP on this address")=""; | |
136 | ::arg().set("tcp-control-port","If set, PowerDNS can be controlled over TCP on this address")="53000"; | |
137 | ::arg().set("tcp-control-secret","If set, PowerDNS can be controlled over TCP after passing this secret")=""; | |
138 | ::arg().set("tcp-control-range","If set, remote control of PowerDNS is possible over these networks only")="127.0.0.0/8, 10.0.0.0/8, 192.168.0.0/16, 172.16.0.0/12, ::1/128, fe80::/10"; | |
619e8acc | 139 | |
dea466f3 BH |
140 | ::arg().setSwitch("slave","Act as a slave")="no"; |
141 | ::arg().setSwitch("master","Act as a master")="no"; | |
d3dfd71e | 142 | ::arg().setSwitch("superslave", "Act as a superslave")="no"; |
5633a4af | 143 | ::arg().setSwitch("disable-axfr-rectify","Disable the rectify step during an outgoing AXFR. Only required for regression testing.")="no"; |
dea466f3 | 144 | ::arg().setSwitch("guardian","Run within a guardian process")="no"; |
8db49a64 | 145 | ::arg().setSwitch("prevent-self-notification","Don't send notifications to what we think is ourself")="yes"; |
536ab56f CH |
146 | ::arg().setSwitch("any-to-tcp","Answer ANY queries with tc=1, shunting to TCP")="yes"; |
147 | ::arg().setSwitch("edns-subnet-processing","If we should act on EDNS Subnet options")="no"; | |
148 | ||
149 | ::arg().setSwitch("webserver","Start a webserver for monitoring (api=yes also enables the HTTP listener)")="no"; | |
150 | ::arg().setSwitch("webserver-print-arguments","If the webserver should print arguments")="no"; | |
151 | ::arg().set("webserver-address","IP Address of webserver/API to listen on")="127.0.0.1"; | |
152 | ::arg().set("webserver-port","Port of webserver/API to listen on")="8081"; | |
dea466f3 | 153 | ::arg().set("webserver-password","Password required for accessing the webserver")=""; |
be3e1477 | 154 | ::arg().set("webserver-allow-from","Webserver/API access is only allowed from these subnets")="127.0.0.1,::1"; |
8ca656a8 | 155 | ::arg().set("webserver-loglevel", "Amount of logging in the webserver (none, normal, detailed)") = "normal"; |
214b034e | 156 | ::arg().set("webserver-max-bodysize","Webserver/API maximum request/response body size in megabytes")="2"; |
dea466f3 | 157 | |
ec1c0ed6 | 158 | ::arg().setSwitch("do-ipv6-additional-processing", "Do AAAA additional processing")="yes"; |
dea466f3 | 159 | ::arg().setSwitch("query-logging","Hint backends that queries should be logged")="no"; |
952d3fcb | 160 | |
2db16252 | 161 | ::arg().set("carbon-namespace", "If set overwrites the first part of the carbon string")="pdns"; |
952d3fcb | 162 | ::arg().set("carbon-ourname", "If set, overrides our reported hostname for carbon stats")=""; |
f7a645ec | 163 | ::arg().set("carbon-instance", "If set overwrites the the instance name default")="auth"; |
90217d39 | 164 | ::arg().set("carbon-server", "If set, send metrics in carbon (graphite) format to this server IP address")=""; |
952d3fcb | 165 | ::arg().set("carbon-interval", "Number of seconds between carbon (graphite) updates")="30"; |
166 | ||
dea466f3 | 167 | ::arg().set("cache-ttl","Seconds to store packets in the PacketCache")="20"; |
ec7f535c PD |
168 | ::arg().set("negquery-cache-ttl","Seconds to store negative query results in the QueryCache")="60"; |
169 | ::arg().set("query-cache-ttl","Seconds to store query results in the QueryCache")="20"; | |
abc1d928 | 170 | ::arg().set("soa-minimum-ttl","Default SOA minimum ttl")="3600"; |
54c4c0d8 | 171 | ::arg().set("server-id", "Returned when queried for 'id.server' TXT or NSID, defaults to hostname - disabled or custom")=""; |
dea466f3 BH |
172 | ::arg().set("soa-refresh-default","Default SOA refresh")="10800"; |
173 | ::arg().set("soa-retry-default","Default SOA retry")="3600"; | |
174 | ::arg().set("soa-expire-default","Default SOA expire")="604800"; | |
4192773a KM |
175 | ::arg().set("default-soa-edit","Default SOA-EDIT value")=""; |
176 | ::arg().set("default-soa-edit-signed","Default SOA-EDIT value for signed zones")=""; | |
030850a9 RG |
177 | ::arg().set("dnssec-key-cache-ttl","Seconds to cache DNSSEC keys from the database")="30"; |
178 | ::arg().set("domain-metadata-cache-ttl","Seconds to cache domain metadata from the database")="60"; | |
dea466f3 BH |
179 | |
180 | ::arg().set("trusted-notification-proxy", "IP address of incoming notification proxy")=""; | |
8de9c054 | 181 | ::arg().set("slave-renotify", "If we should send out notifications for slaved updates")="no"; |
130a758d | 182 | ::arg().set("forward-notify", "IP addresses to forward received notifications to regardless of master or slave settings")=""; |
dea466f3 BH |
183 | |
184 | ::arg().set("default-ttl","Seconds a result is valid if not set otherwise")="3600"; | |
6ee2c056 | 185 | ::arg().set("max-tcp-connections","Maximum number of TCP connections")="20"; |
cb0af1a1 | 186 | ::arg().set("max-tcp-connections-per-client","Maximum number of simultaneous TCP connections per client")="0"; |
69a1b753 PD |
187 | ::arg().set("max-tcp-transactions-per-conn","Maximum number of subsequent queries per TCP connection")="0"; |
188 | ::arg().set("max-tcp-connection-duration","Maximum time in seconds that a TCP DNS connection is allowed to stay open.")="0"; | |
189 | ::arg().set("tcp-idle-timeout","Maximum time in seconds that a TCP DNS connection is allowed to stay open while being idle")="5"; | |
cb0af1a1 | 190 | |
dea466f3 BH |
191 | ::arg().setSwitch("no-shuffle","Set this to prevent random shuffling of answers - for regression testing")="off"; |
192 | ||
dea466f3 BH |
193 | ::arg().set("setuid","If set, change user id to this uid for more security")=""; |
194 | ::arg().set("setgid","If set, change group id to this gid for more security")=""; | |
195 | ||
bf269e28 RG |
196 | ::arg().set("max-cache-entries", "Maximum number of entries in the query cache")="1000000"; |
197 | ::arg().set("max-packet-cache-entries", "Maximum number of entries in the packet cache")="1000000"; | |
bba84134 | 198 | ::arg().set("max-signature-cache-entries", "Maximum number of signatures cache entries")=""; |
b5baefaf | 199 | ::arg().set("max-ent-entries", "Maximum number of empty non-terminals in a zone")="100000"; |
a28a204a | 200 | ::arg().set("entropy-source", "If set, read entropy from this file")="/dev/urandom"; |
5704e107 | 201 | |
3e8216c8 | 202 | ::arg().set("lua-prequery-script", "Lua script with prequery handler (DO NOT USE)")=""; |
0ecc1158 | 203 | ::arg().set("lua-dnsupdate-policy-script", "Lua script with DNS update policy handler")=""; |
5488e86b PD |
204 | |
205 | ::arg().setSwitch("traceback-handler","Enable the traceback handler (Linux only)")="yes"; | |
16d72778 | 206 | ::arg().setSwitch("direct-dnskey","Fetch DNSKEY, CDS and CDNSKEY RRs from backend during DNSKEY or CDS/CDNSKEY synthesis")="no"; |
28080ce6 | 207 | ::arg().set("default-ksk-algorithm","Default KSK algorithm")="ecdsa256"; |
36758d25 | 208 | ::arg().set("default-ksk-size","Default KSK size (0 means default)")="0"; |
28080ce6 | 209 | ::arg().set("default-zsk-algorithm","Default ZSK algorithm")=""; |
95cc7e8d | 210 | ::arg().set("default-zsk-size","Default ZSK size (0 means default)")="0"; |
28b66a94 | 211 | ::arg().set("max-nsec3-iterations","Limit the number of NSEC3 hash iterations")="500"; // RFC5155 10.3 |
0a862860 AT |
212 | |
213 | ::arg().set("include-dir","Include *.conf files from this directory"); | |
199631c6 | 214 | ::arg().set("security-poll-suffix","Domain name from which to query security update notifications")="secpoll.powerdns.com."; |
7f6f4d4f | 215 | |
389b7a05 | 216 | ::arg().setSwitch("expand-alias", "Expand ALIAS records")="no"; |
7f6f4d4f | 217 | ::arg().setSwitch("outgoing-axfr-expand-alias", "Expand ALIAS records during outgoing AXFR")="no"; |
fc41a1a6 | 218 | ::arg().setSwitch("8bit-dns", "Allow 8bit dns queries")="no"; |
af68014f | 219 | #ifdef HAVE_LUA_RECORDS |
27a630b4 CHB |
220 | ::arg().setSwitch("enable-lua-records", "Process LUA records for all zones (metadata overrides this)")="no"; |
221 | ::arg().set("lua-records-exec-limit", "LUA records scripts execution limit (instructions count). Values <= 0 mean no limit")="1000"; | |
af68014f | 222 | #endif |
0f76617d | 223 | ::arg().setSwitch("axfr-lower-serial", "Also AXFR a zone from a master with a lower serial")="no"; |
db8f9152 | 224 | |
86177332 | 225 | ::arg().set("lua-axfr-script", "Script to be used to edit incoming AXFRs")=""; |
db8f9152 | 226 | ::arg().set("xfr-max-received-mbytes", "Maximum number of megabytes received from an incoming XFR")="100"; |
e3619f57 | 227 | ::arg().set("axfr-fetch-timeout", "Maximum time in seconds for inbound AXFR to start or be idle after starting")="10"; |
940d7811 RG |
228 | |
229 | ::arg().set("tcp-fast-open", "Enable TCP Fast Open support on the listening sockets, using the supplied numerical value as the queue size")="0"; | |
e97cb679 | 230 | |
ba3d53d1 RG |
231 | ::arg().set("max-generate-steps", "Maximum number of $GENERATE steps when loading a zone from a file")="0"; |
232 | ||
e97cb679 | 233 | ::arg().set("rng", "Specify the random number generator to use. Valid values are auto,sodium,openssl,getrandom,arc4random,urandom.")="auto"; |
619e8acc BH |
234 | } |
235 | ||
22f1199c | 236 | static time_t s_start=time(0); |
e903706d | 237 | static uint64_t uptimeOfProcess(const std::string& str) |
238 | { | |
22f1199c | 239 | return time(0) - s_start; |
e903706d | 240 | } |
241 | ||
242 | static uint64_t getSysUserTimeMsec(const std::string& str) | |
243 | { | |
244 | struct rusage ru; | |
245 | getrusage(RUSAGE_SELF, &ru); | |
246 | ||
a2746484 | 247 | if(str=="sys-msec") { |
e903706d | 248 | return (ru.ru_stime.tv_sec*1000ULL + ru.ru_stime.tv_usec/1000); |
a2746484 | 249 | } |
e903706d | 250 | else |
251 | return (ru.ru_utime.tv_sec*1000ULL + ru.ru_utime.tv_usec/1000); | |
252 | ||
253 | } | |
254 | ||
d322f931 PD |
255 | static uint64_t getTCPConnectionCount(const std::string& str) |
256 | { | |
257 | return TN->numTCPConnections(); | |
258 | } | |
259 | ||
1a46890f | 260 | static uint64_t getQCount(const std::string& str) |
2bf07cf4 | 261 | try |
1a46890f | 262 | { |
263 | int totcount=0; | |
c2826d2e | 264 | for(const auto& d : g_distributors) { |
ba98c6d7 | 265 | if(!d) |
266 | continue; | |
491d03d7 | 267 | totcount += d->getQueueSize(); // this does locking and other things, so don't get smart |
1a46890f | 268 | } |
269 | return totcount; | |
270 | } | |
2bf07cf4 | 271 | catch(std::exception& e) |
272 | { | |
e6a9dde5 | 273 | g_log<<Logger::Error<<"Had error retrieving queue sizes: "<<e.what()<<endl; |
2bf07cf4 | 274 | return 0; |
275 | } | |
276 | catch(PDNSException& e) | |
277 | { | |
e6a9dde5 | 278 | g_log<<Logger::Error<<"Had error retrieving queue sizes: "<<e.reason<<endl; |
2bf07cf4 | 279 | return 0; |
280 | } | |
1a46890f | 281 | |
282 | static uint64_t getLatency(const std::string& str) | |
283 | { | |
284 | return avg_latency; | |
285 | } | |
286 | ||
619e8acc BH |
287 | void declareStats(void) |
288 | { | |
289 | S.declare("udp-queries","Number of UDP queries received"); | |
9951e2d0 | 290 | S.declare("udp-do-queries","Number of UDP queries received with DO bit"); |
619e8acc | 291 | S.declare("udp-answers","Number of answers sent out over UDP"); |
4b24088f | 292 | S.declare("udp-answers-bytes","Total size of answers sent out over UDP"); |
50dbdbeb PL |
293 | S.declare("udp4-answers-bytes","Total size of answers sent out over UDPv4"); |
294 | S.declare("udp6-answers-bytes","Total size of answers sent out over UDPv6"); | |
bd852e59 BH |
295 | |
296 | S.declare("udp4-answers","Number of IPv4 answers sent out over UDP"); | |
9951e2d0 | 297 | S.declare("udp4-queries","Number of IPv4 UDP queries received"); |
bd852e59 BH |
298 | S.declare("udp6-answers","Number of IPv6 answers sent out over UDP"); |
299 | S.declare("udp6-queries","Number of IPv6 UDP queries received"); | |
d3363b40 | 300 | S.declare("overload-drops","Queries dropped because backends overloaded"); |
bd852e59 | 301 | |
bb6e54fe | 302 | S.declare("rd-queries", "Number of recursion desired questions"); |
303 | S.declare("recursion-unanswered", "Number of packets unanswered by configured recursor"); | |
619e8acc BH |
304 | S.declare("recursing-answers","Number of recursive answers sent out"); |
305 | S.declare("recursing-questions","Number of questions sent to recursor"); | |
306 | S.declare("corrupt-packets","Number of corrupt packets received"); | |
c681ff64 | 307 | S.declare("signatures", "Number of DNSSEC signatures made"); |
619e8acc BH |
308 | S.declare("tcp-queries","Number of TCP queries received"); |
309 | S.declare("tcp-answers","Number of answers sent out over TCP"); | |
b552d7b1 | 310 | S.declare("tcp-answers-bytes","Total size of answers sent out over TCP"); |
50dbdbeb PL |
311 | S.declare("tcp4-answers-bytes","Total size of answers sent out over TCPv4"); |
312 | S.declare("tcp6-answers-bytes","Total size of answers sent out over TCPv6"); | |
313 | ||
5fd567ec | 314 | S.declare("tcp4-queries","Number of IPv4 TCP queries received"); |
315 | S.declare("tcp4-answers","Number of IPv4 answers sent out over TCP"); | |
316 | ||
317 | S.declare("tcp6-queries","Number of IPv6 TCP queries received"); | |
318 | S.declare("tcp6-answers","Number of IPv6 answers sent out over TCP"); | |
d322f931 PD |
319 | |
320 | S.declare("open-tcp-connections","Number of currently open TCP connections", getTCPConnectionCount);; | |
619e8acc | 321 | |
1a46890f | 322 | S.declare("qsize-q","Number of questions waiting for database attention", getQCount); |
619e8acc | 323 | |
71f758e0 KM |
324 | S.declare("dnsupdate-queries", "DNS update packets received."); |
325 | S.declare("dnsupdate-answers", "DNS update packets successfully answered."); | |
326 | S.declare("dnsupdate-refused", "DNS update packets that are refused."); | |
327 | S.declare("dnsupdate-changes", "DNS update changes to records in total."); | |
619e8acc | 328 | |
93aecccc RK |
329 | S.declare("incoming-notifications", "NOTIFY packets received."); |
330 | ||
e903706d | 331 | S.declare("uptime", "Uptime of process in seconds", uptimeOfProcess); |
af0c10e7 | 332 | S.declare("real-memory-usage", "Actual unique use of memory in bytes (approx)", getRealMemoryUsage); |
330dcb5c | 333 | S.declare("special-memory-usage", "Actual unique use of memory in bytes (approx)", getSpecialMemoryUsage); |
24538841 | 334 | S.declare("fd-usage", "Number of open filedescriptors", getOpenFileDescriptors); |
f45a622c | 335 | #ifdef __linux__ |
336 | S.declare("udp-recvbuf-errors", "UDP 'recvbuf' errors", udpErrorStats); | |
337 | S.declare("udp-sndbuf-errors", "UDP 'sndbuf' errors", udpErrorStats); | |
338 | S.declare("udp-noport-errors", "UDP 'noport' errors", udpErrorStats); | |
339 | S.declare("udp-in-errors", "UDP 'in' errors", udpErrorStats); | |
340 | #endif | |
341 | ||
e903706d | 342 | S.declare("sys-msec", "Number of msec spent in system time", getSysUserTimeMsec); |
343 | S.declare("user-msec", "Number of msec spent in user time", getSysUserTimeMsec); | |
344 | S.declare("meta-cache-size", "Number of entries in the metadata cache", DNSSECKeeper::dbdnssecCacheSizes); | |
345 | S.declare("key-cache-size", "Number of entries in the key cache", DNSSECKeeper::dbdnssecCacheSizes); | |
346 | S.declare("signature-cache-size", "Number of entries in the signature cache", signatureCacheSize); | |
347 | ||
619e8acc | 348 | S.declare("servfail-packets","Number of times a server-failed packet was sent out"); |
1a46890f | 349 | S.declare("latency","Average number of microseconds needed to answer a question", getLatency); |
619e8acc | 350 | S.declare("timedout-packets","Number of packets which weren't answered within timeout set"); |
199631c6 | 351 | S.declare("security-status", "Security status based on regular polling"); |
eb029b8e PL |
352 | S.declareDNSNameQTypeRing("queries","UDP Queries Received"); |
353 | S.declareDNSNameQTypeRing("nxdomain-queries","Queries for non-existent records within existent domains"); | |
354 | S.declareDNSNameQTypeRing("noerror-queries","Queries for existing records, but for type we don't have"); | |
355 | S.declareDNSNameQTypeRing("servfail-queries","Queries that could not be answered due to backend errors"); | |
356 | S.declareDNSNameQTypeRing("unauth-queries","Queries for domains that we are not authoritative for"); | |
619e8acc | 357 | S.declareRing("logmessages","Log Messages"); |
4eb26e0f | 358 | S.declareComboRing("remotes","Remote server IP addresses"); |
359 | S.declareComboRing("remotes-unauth","Remote hosts querying domains for which we are not auth"); | |
360 | S.declareComboRing("remotes-corrupt","Remote hosts sending corrupt packets"); | |
619e8acc BH |
361 | } |
362 | ||
619e8acc BH |
363 | int isGuarded(char **argv) |
364 | { | |
365 | char *p=strstr(argv[0],"-instance"); | |
366 | ||
367 | return !!p; | |
368 | } | |
369 | ||
c2826d2e | 370 | static void sendout(std::unique_ptr<DNSPacket>& a) |
619e8acc | 371 | { |
491d03d7 | 372 | if(!a) |
619e8acc BH |
373 | return; |
374 | ||
c2826d2e | 375 | N->send(*a); |
bd852e59 | 376 | |
491d03d7 | 377 | int diff=a->d_dt.udiff(); |
a2746484 | 378 | avg_latency=(int)(0.999*avg_latency+0.001*diff); |
619e8acc BH |
379 | } |
380 | ||
abc1d928 | 381 | //! The qthread receives questions over the internet via the Nameserver class, and hands them to the Distributor for further processing |
c2826d2e | 382 | static void qthread(unsigned int num) |
26d75dc2 | 383 | try |
619e8acc | 384 | { |
519f5484 | 385 | setThreadName("pdns/receiver"); |
09b12b5d | 386 | |
c2826d2e RG |
387 | g_distributors[num] = DNSDistributor::Create(::arg().asNum("distributor-threads", 1)); |
388 | DNSDistributor* distributor = g_distributors[num]; // the big dispatcher! | |
27c0050c RG |
389 | DNSPacket question(true); |
390 | DNSPacket cached(false); | |
619e8acc | 391 | |
1566533a | 392 | AtomicCounter &numreceived=*S.getPointer("udp-queries"); |
393 | AtomicCounter &numreceiveddo=*S.getPointer("udp-do-queries"); | |
bd852e59 | 394 | |
1566533a | 395 | AtomicCounter &numreceived4=*S.getPointer("udp4-queries"); |
bd852e59 | 396 | |
1566533a | 397 | AtomicCounter &numreceived6=*S.getPointer("udp6-queries"); |
d3363b40 | 398 | AtomicCounter &overloadDrops=*S.getPointer("overload-drops"); |
90b07284 | 399 | |
619e8acc | 400 | int diff; |
21a303f3 | 401 | bool logDNSQueries = ::arg().mustDo("log-dns-queries"); |
12f224ab | 402 | shared_ptr<UDPNameserver> NS; |
2c001eb6 RG |
403 | std::string buffer; |
404 | buffer.resize(DNSPacket::s_udpTruncationThreshold); | |
4ee30c66 MZ |
405 | |
406 | // If we have SO_REUSEPORT then create a new port for all receiver threads | |
407 | // other than the first one. | |
c2826d2e | 408 | if(N->canReusePort() ) { |
12f224ab RG |
409 | NS = g_udpReceivers[num]; |
410 | if (NS == nullptr) { | |
ed3afdfc PD |
411 | NS = N; |
412 | } | |
12f224ab RG |
413 | } else { |
414 | NS = N; | |
3a56adcc | 415 | } |
4ee30c66 | 416 | |
619e8acc | 417 | for(;;) { |
c2826d2e | 418 | if(!NS->receive(question, buffer)) { // receive a packet inline |
fe172793 | 419 | continue; // packet was broken, try again |
420 | } | |
421 | ||
296ff2ed | 422 | numreceived++; |
8a63d3ce | 423 | |
c2826d2e | 424 | if(question.d_remote.getSocklen()==sizeof(sockaddr_in)) |
bd852e59 BH |
425 | numreceived4++; |
426 | else | |
427 | numreceived6++; | |
619e8acc | 428 | |
c2826d2e | 429 | if(question.d_dnssecOk) |
9951e2d0 KM |
430 | numreceiveddo++; |
431 | ||
c2826d2e | 432 | if(question.d.qr) |
6a90bacf BH |
433 | continue; |
434 | ||
c2826d2e RG |
435 | S.ringAccount("queries", question.qdomain, question.qtype); |
436 | S.ringAccount("remotes", question.d_remote); | |
fe498ace BH |
437 | if(logDNSQueries) { |
438 | string remote; | |
c2826d2e RG |
439 | if(question.hasEDNSSubnet()) |
440 | remote = question.getRemote().toString() + "<-" + question.getRealRemote().toString(); | |
fe498ace | 441 | else |
c2826d2e RG |
442 | remote = question.getRemote().toString(); |
443 | g_log << Logger::Notice<<"Remote "<< remote <<" wants '" << question.qdomain<<"|"<<question.qtype.getName() << | |
444 | "', do = " <<question.d_dnssecOk <<", bufsize = "<< question.getMaxReplyLen(); | |
445 | if(question.d_ednsRawPacketSizeLimit > 0 && question.getMaxReplyLen() != (unsigned int)question.d_ednsRawPacketSizeLimit) | |
446 | g_log<<" ("<<question.d_ednsRawPacketSizeLimit<<")"; | |
e6a9dde5 | 447 | g_log<<": "; |
fe498ace | 448 | } |
abc8f3f9 | 449 | |
c2826d2e RG |
450 | if(PC.enabled() && (question.d.opcode != Opcode::Notify && question.d.opcode != Opcode::Update) && question.couldBeCached()) { |
451 | bool haveSomething=PC.get(question, cached); // does the PacketCache recognize this question? | |
75fde355 KM |
452 | if (haveSomething) { |
453 | if(logDNSQueries) | |
e6a9dde5 | 454 | g_log<<"packetcache HIT"<<endl; |
c2826d2e RG |
455 | cached.setRemote(&question.d_remote); // inlined |
456 | cached.setSocket(question.getSocket()); // inlined | |
457 | cached.d_anyLocal = question.d_anyLocal; | |
458 | cached.setMaxReplyLen(question.getMaxReplyLen()); | |
459 | cached.d.rd=question.d.rd; // copy in recursion desired bit | |
460 | cached.d.id=question.d.id; | |
75fde355 | 461 | cached.commitD(); // commit d to the packet inlined |
c2826d2e RG |
462 | NS->send(cached); // answer it then inlined |
463 | diff=question.d_dt.udiff(); | |
da286f66 | 464 | avg_latency=(int)(0.999*avg_latency+0.001*diff); // 'EWMA' |
75fde355 KM |
465 | continue; |
466 | } | |
619e8acc | 467 | } |
bf269e28 | 468 | |
078f4c97 | 469 | if(distributor->isOverloaded()) { |
e7e691cc | 470 | if(logDNSQueries) |
e6a9dde5 | 471 | g_log<<"Dropped query, backends are overloaded"<<endl; |
d3363b40 | 472 | overloadDrops++; |
e7e691cc BH |
473 | continue; |
474 | } | |
475 | ||
9a037bfa | 476 | if(PC.enabled() && logDNSQueries) |
e6a9dde5 | 477 | g_log<<"packetcache MISS"<<endl; |
e7e691cc | 478 | |
491d03d7 | 479 | try { |
c2826d2e | 480 | distributor->question(question, &sendout); // otherwise, give to the distributor |
491d03d7 | 481 | } |
482 | catch(DistributorFatal& df) { // when this happens, we have leaked loads of memory. Bailing out time. | |
483 | _exit(1); | |
484 | } | |
619e8acc | 485 | } |
619e8acc | 486 | } |
26d75dc2 | 487 | catch(PDNSException& pe) |
488 | { | |
e6a9dde5 | 489 | g_log<<Logger::Error<<"Fatal error in question thread: "<<pe.reason<<endl; |
26d75dc2 | 490 | _exit(1); |
491 | } | |
619e8acc | 492 | |
2250bafa | 493 | static void* dummyThread(void *) |
494 | { | |
495 | void* ignore=0; | |
496 | pthread_exit(ignore); | |
497 | } | |
498 | ||
499 | static void triggerLoadOfLibraries() | |
500 | { | |
501 | pthread_t tid; | |
502 | pthread_create(&tid, 0, dummyThread, 0); | |
503 | void* res; | |
504 | pthread_join(tid, &res); | |
505 | } | |
506 | ||
619e8acc BH |
507 | void mainthread() |
508 | { | |
b51ef4f9 | 509 | Utility::srandom(); |
619e8acc | 510 | |
76ba685e PL |
511 | gid_t newgid = 0; |
512 | if(!::arg()["setgid"].empty()) | |
2211dac9 | 513 | newgid = strToGID(::arg()["setgid"]); |
76ba685e PL |
514 | uid_t newuid = 0; |
515 | if(!::arg()["setuid"].empty()) | |
2211dac9 | 516 | newuid = strToUID(::arg()["setuid"]); |
af7d3ea6 | 517 | |
357f6a75 | 518 | g_anyToTcp = ::arg().mustDo("any-to-tcp"); |
fc41a1a6 | 519 | g_8bitDNS = ::arg().mustDo("8bit-dns"); |
8900e2e3 | 520 | #ifdef HAVE_LUA_RECORDS |
27a630b4 | 521 | g_doLuaRecord = ::arg().mustDo("enable-lua-records"); |
32829819 | 522 | g_LuaRecordSharedState = (::arg()["enable-lua-records"] == "shared"); |
27a630b4 | 523 | g_luaRecordExecLimit = ::arg().asNum("lua-records-exec-limit"); |
8900e2e3 | 524 | #endif |
8dee0750 | 525 | |
1cd66b8e | 526 | DNSPacket::s_udpTruncationThreshold = std::max(512, ::arg().asNum("udp-truncation-threshold")); |
af7d3ea6 | 527 | DNSPacket::s_doEDNSSubnetProcessing = ::arg().mustDo("edns-subnet-processing"); |
199631c6 | 528 | |
bf269e28 RG |
529 | PC.setTTL(::arg().asNum("cache-ttl")); |
530 | PC.setMaxEntries(::arg().asNum("max-packet-cache-entries")); | |
531 | QC.setMaxEntries(::arg().asNum("max-cache-entries")); | |
532 | ||
150e318e | 533 | stubParseResolveConf(); |
199631c6 | 534 | |
f0f3f0b0 | 535 | if(!::arg()["chroot"].empty()) { |
75336810 PL |
536 | #ifdef HAVE_SYSTEMD |
537 | char *ns; | |
538 | ns = getenv("NOTIFY_SOCKET"); | |
539 | if (ns != nullptr) { | |
e6a9dde5 | 540 | g_log<<Logger::Error<<"Unable to chroot when running from systemd. Please disable chroot= or set the 'Type' for this service to 'simple'"<<endl; |
75336810 PL |
541 | exit(1); |
542 | } | |
543 | #endif | |
2250bafa | 544 | triggerLoadOfLibraries(); |
dea466f3 | 545 | if(::arg().mustDo("master") || ::arg().mustDo("slave")) |
4957a608 | 546 | gethostbyname("a.root-servers.net"); // this forces all lookup libraries to be loaded |
f1d6a7ce | 547 | Utility::dropGroupPrivs(newuid, newgid); |
dea466f3 | 548 | if(chroot(::arg()["chroot"].c_str())<0 || chdir("/")<0) { |
a702a96c | 549 | g_log<<Logger::Error<<"Unable to chroot to '"+::arg()["chroot"]+"': "<<stringerror()<<", exiting"<<endl; |
619e8acc BH |
550 | exit(1); |
551 | } | |
552 | else | |
e6a9dde5 | 553 | g_log<<Logger::Error<<"Chrooted to '"<<::arg()["chroot"]<<"'"<<endl; |
f1d6a7ce KM |
554 | } else { |
555 | Utility::dropGroupPrivs(newuid, newgid); | |
556 | } | |
357f6a75 | 557 | |
dea47634 | 558 | AuthWebServer webserver; |
f1d6a7ce | 559 | Utility::dropUserPrivs(newuid); |
619e8acc | 560 | |
8eccac19 | 561 | if(::arg().mustDo("resolver")){ |
c2826d2e | 562 | DP=std::unique_ptr<DNSProxy>(new DNSProxy(::arg()["resolver"])); |
619e8acc BH |
563 | DP->go(); |
564 | } | |
e6402e23 PL |
565 | |
566 | try { | |
567 | doSecPoll(true); | |
568 | } | |
569 | catch(...) {} | |
570 | ||
efc10591 PL |
571 | { |
572 | // Some sanity checking on default key settings | |
573 | bool hadKeyError = false; | |
574 | int kskAlgo{0}, zskAlgo{0}; | |
575 | for (const string& algotype : {"ksk", "zsk"}) { | |
576 | int algo, size; | |
577 | if (::arg()["default-"+algotype+"-algorithm"].empty()) | |
578 | continue; | |
579 | algo = DNSSECKeeper::shorthand2algorithm(::arg()["default-"+algotype+"-algorithm"]); | |
580 | size = ::arg().asNum("default-"+algotype+"-size"); | |
581 | if (algo == -1) { | |
582 | g_log<<Logger::Error<<"Error: default-"<<algotype<<"-algorithm set to unknown algorithm: "<<::arg()["default-"+algotype+"-algorithm"]<<endl; | |
583 | hadKeyError = true; | |
584 | } | |
585 | else if (algo <= 10 && size == 0) { | |
586 | g_log<<Logger::Error<<"Error: default-"<<algotype<<"-algorithm is set to an algorithm ("<<::arg()["default-"+algotype+"-algorithm"]<<") that requires a non-zero default-"<<algotype<<"-size!"<<endl; | |
587 | hadKeyError = true; | |
588 | } | |
589 | if (algotype == "ksk") { | |
590 | kskAlgo = algo; | |
591 | } else { | |
592 | zskAlgo = algo; | |
593 | } | |
8b8e8670 | 594 | } |
efc10591 PL |
595 | if (hadKeyError) { |
596 | exit(1); | |
597 | } | |
598 | if (kskAlgo == 0 && zskAlgo != 0) { | |
599 | g_log<<Logger::Error<<"Error: default-zsk-algorithm is set, but default-ksk-algorithm is not set."<<endl; | |
600 | exit(1); | |
601 | } | |
602 | if (zskAlgo != 0 && zskAlgo != kskAlgo) { | |
603 | g_log<<Logger::Error<<"Error: default-zsk-algorithm ("<<::arg()["default-zsk-algorithm"]<<"), when set, can not be different from default-ksk-algorithm ("<<::arg()["default-ksk-algorithm"]<<")."<<endl; | |
604 | exit(1); | |
8b8e8670 | 605 | } |
82ee5aa5 PL |
606 | } |
607 | ||
619e8acc BH |
608 | // NOW SAFE TO CREATE THREADS! |
609 | dl->go(); | |
610 | ||
536ab56f | 611 | if(::arg().mustDo("webserver") || ::arg().mustDo("api")) |
dea47634 CH |
612 | webserver.go(); |
613 | ||
dad0736b | 614 | if(::arg().mustDo("slave") || ::arg().mustDo("master") || !::arg()["forward-notify"].empty()) |
619e8acc BH |
615 | Communicator.go(); |
616 | ||
8c98b341 | 617 | TN->go(); // tcp nameserver launch |
952d3fcb | 618 | |
ff99a74b | 619 | unsigned int max_rthreads= ::arg().asNum("receiver-threads", 1); |
2bf07cf4 | 620 | g_distributors.resize(max_rthreads); |
c2826d2e RG |
621 | for(unsigned int n=0; n < max_rthreads; ++n) { |
622 | std::thread t(qthread, n); | |
623 | t.detach(); | |
624 | } | |
619e8acc | 625 | |
c2826d2e | 626 | std::thread carbonThread(carbonDumpThread); // runs even w/o carbon, might change @ runtime |
ba98c6d7 | 627 | |
6988eae9 PL |
628 | #ifdef HAVE_SYSTEMD |
629 | /* If we are here, notify systemd that we are ay-ok! This might have some | |
630 | * timing issues with the backend-threads. e.g. if the initial MySQL connection | |
631 | * is slow and times out (leading to process termination through the backend) | |
632 | * We probably have told systemd already that we have started correctly. | |
633 | */ | |
634 | sd_notify(0, "READY=1"); | |
635 | #endif | |
636 | ||
199631c6 | 637 | for(;;) { |
638 | sleep(1800); | |
ea272da2 | 639 | try { |
640 | doSecPoll(false); | |
641 | } | |
642 | catch(...){} | |
199631c6 | 643 | } |
619e8acc | 644 | |
e6a9dde5 | 645 | g_log<<Logger::Error<<"Mainthread exiting - should never happen"<<endl; |
619e8acc | 646 | } |