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