2 * This file is part of PowerDNS or dnsdist.
3 * Copyright -- PowerDNS.COM B.V. and its contributors
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.
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.
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.
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.
30 #include "lua-recursor4.hh"
32 #include "namespaces.hh"
33 #include "rec-lua-conf.hh"
34 #include "rec-protozero.hh"
36 #include "rec-snmp.hh"
37 #include "rec_channel.hh"
38 #include "threadname.hh"
42 #endif /* NOD_ENABLED */
44 #ifdef HAVE_BOOST_CONTAINER_FLAT_SET_HPP
45 #include <boost/container/flat_set.hpp>
48 //! used to send information to a newborn mthread
51 DNSComboWriter(const std::string& query, const struct timeval& now, shared_ptr<RecursorLua4> luaContext) :
52 d_mdp(true, query), d_now(now), d_query(query), d_luaContext(luaContext)
56 DNSComboWriter(const std::string& query, const struct timeval& now, std::unordered_set<std::string>&& policyTags, shared_ptr<RecursorLua4> luaContext, LuaContext::LuaObject&& data, std::vector<DNSRecord>&& records) :
57 d_mdp(true, query), d_now(now), d_query(query), d_policyTags(std::move(policyTags)), d_records(std::move(records)), d_luaContext(luaContext), d_data(std::move(data))
61 void setRemote(const ComboAddress& sa)
66 void setSource(const ComboAddress& sa)
71 void setLocal(const ComboAddress& sa)
76 void setDestination(const ComboAddress& sa)
81 void setSocket(int sock)
86 string getRemote() const
88 if (d_source == d_remote) {
89 return d_source.toStringWithPort();
91 return d_source.toStringWithPort() + " (proxied by " + d_remote.toStringWithPort() + ")";
94 std::vector<ProxyProtocolValue> d_proxyProtocolValues;
97 /* Remote client, might differ from d_source
98 in case of XPF, in which case d_source holds
99 the IP of the client and d_remote of the proxy
101 ComboAddress d_remote;
102 ComboAddress d_source;
103 /* Destination address, might differ from
104 d_destination in case of XPF, in which case
105 d_destination holds the IP of the proxy and
106 d_local holds our own. */
107 ComboAddress d_local;
108 ComboAddress d_destination;
109 RecEventTrace d_eventTrace;
110 boost::uuids::uuid d_uuid;
111 string d_requestorId;
114 struct timeval d_kernelTimestamp
119 std::unordered_set<std::string> d_policyTags;
120 std::string d_routingTag;
121 std::vector<DNSRecord> d_records;
123 // d_data is tied to this LuaContext so we need to keep it alive and use it, not a newer one, as long as d_data exists
124 shared_ptr<RecursorLua4> d_luaContext;
125 LuaContext::LuaObject d_data;
127 EDNSSubnetOpts d_ednssubnet;
128 shared_ptr<TCPConnection> d_tcpConnection;
129 boost::optional<uint16_t> d_extendedErrorCode{boost::none};
130 string d_extendedErrorExtra;
131 boost::optional<int> d_rcode{boost::none};
133 unsigned int d_tag{0};
135 uint32_t d_ttlCap{std::numeric_limits<uint32_t>::max()};
136 bool d_variable{false};
137 bool d_ecsFound{false};
138 bool d_ecsParsed{false};
139 bool d_followCNAMERecords{false};
140 bool d_logResponse{false};
142 bool d_responsePaddingDisabled{false};
143 std::map<std::string, RecursorLua4::MetaValue> d_meta;
146 extern thread_local unique_ptr<FDMultiplexer> t_fdm;
147 extern uint16_t g_minUdpSourcePort;
148 extern uint16_t g_maxUdpSourcePort;
150 // you can ask this class for a UDP socket to send a query from
151 // this socket is not yours, don't even think about deleting it
152 // but after you call 'returnSocket' on it, don't assume anything anymore
155 unsigned int d_numsocks;
163 LWResult::Result getSocket(const ComboAddress& toaddr, int* fd);
165 // return a socket to the pool, or simply erase it
166 void returnSocket(int fd);
169 // returns -1 for errors which might go away, throws for ones that won't
170 static int makeClientSocket(int family);
173 enum class PaddingMode
179 typedef MTasker<std::shared_ptr<PacketID>, PacketBuffer, PacketIDCompare> MT_t;
180 extern thread_local std::unique_ptr<MT_t> MT; // the big MTasker
182 extern bool g_logCommonErrors;
183 extern size_t g_proxyProtocolMaximumSize;
184 extern std::atomic<bool> g_quiet;
185 extern NetmaskGroup g_XPFAcl;
186 extern thread_local std::shared_ptr<std::vector<std::unique_ptr<RemoteLogger>>> t_protobufServers;
187 extern thread_local std::shared_ptr<RecursorLua4> t_pdl;
188 extern bool g_gettagNeedsEDNSOptions;
189 extern NetmaskGroup g_paddingFrom;
190 extern unsigned int g_paddingTag;
191 extern PaddingMode g_paddingMode;
192 extern thread_local std::shared_ptr<std::vector<std::unique_ptr<RemoteLogger>>> t_outgoingProtobufServers;
193 extern unsigned int g_maxMThreads;
194 extern bool g_reusePort;
195 extern bool g_anyToTcp;
196 extern size_t g_tcpMaxQueriesPerConn;
197 extern unsigned int g_maxTCPPerClient;
198 extern int g_tcpTimeout;
199 extern uint16_t g_udpTruncationThreshold;
200 extern double g_balancingFactor;
201 extern size_t g_maxUDPQueriesPerRound;
202 extern bool g_useKernelTimestamp;
203 extern thread_local std::shared_ptr<NetmaskGroup> t_allowFrom;
204 extern thread_local std::shared_ptr<NetmaskGroup> t_allowNotifyFrom;
205 extern thread_local std::shared_ptr<notifyset_t> t_allowNotifyFor;
206 extern thread_local std::unique_ptr<UDPClientSocks> t_udpclientsocks;
207 extern bool g_useIncomingECS;
208 extern boost::optional<ComboAddress> g_dns64Prefix;
209 extern DNSName g_dns64PrefixReverse;
210 extern uint64_t g_latencyStatSize;
211 extern bool g_addExtendedResolutionDNSErrors;
212 extern uint16_t g_xpfRRCode;
213 extern NetmaskGroup g_proxyProtocolACL;
214 extern std::atomic<bool> g_statsWanted;
215 extern uint32_t g_disthashseed;
217 extern char** g_argv;
218 extern std::shared_ptr<SyncRes::domainmap_t> g_initialDomainMap; // new threads needs this to be setup
219 extern std::shared_ptr<NetmaskGroup> g_initialAllowFrom; // new thread needs to be setup with this
220 extern std::shared_ptr<NetmaskGroup> g_initialAllowNotifyFrom; // new threads need this to be setup
221 extern std::shared_ptr<notifyset_t> g_initialAllowNotifyFor; // new threads need this to be setup
222 extern thread_local std::shared_ptr<Regex> t_traceRegex;
223 extern string g_programname;
224 extern string g_pidfname;
225 extern RecursorControlChannel g_rcc; // only active in the handler thread
228 extern bool g_nodEnabled;
229 extern DNSName g_nodLookupDomain;
230 extern bool g_nodLog;
231 extern SuffixMatchNode g_nodDomainWL;
232 extern std::string g_nod_pbtag;
233 extern bool g_udrEnabled;
234 extern bool g_udrLog;
235 extern std::string g_udr_pbtag;
236 extern thread_local std::shared_ptr<nod::NODDB> t_nodDBp;
237 extern thread_local std::shared_ptr<nod::UniqueResponseDB> t_udrDBp;
241 extern thread_local std::shared_ptr<std::vector<std::unique_ptr<FrameStreamLogger>>> t_frameStreamServers;
242 extern thread_local uint64_t t_frameStreamServersGeneration;
243 #endif /* HAVE_FSTRM */
245 #ifdef HAVE_BOOST_CONTAINER_FLAT_SET_HPP
246 extern boost::container::flat_set<uint16_t> g_avoidUdpSourcePorts;
248 extern std::set<uint16_t> g_avoidUdpSourcePorts;
251 /* without reuseport, all listeners share the same sockets */
252 typedef vector<pair<int, boost::function<void(int, boost::any&)>>> deferredAdd_t;
253 extern deferredAdd_t g_deferredAdds;
255 typedef map<ComboAddress, uint32_t, ComboAddress::addressOnlyLessThan> tcpClientCounts_t;
256 extern thread_local std::unique_ptr<tcpClientCounts_t> t_tcpClientCounts;
260 return MT ? MT.get() : nullptr;
263 /* this function is called with both a string and a vector<uint8_t> representing a packet */
265 static bool sendResponseOverTCP(const std::unique_ptr<DNSComboWriter>& dc, const T& packet)
268 buf[0] = packet.size() / 256;
269 buf[1] = packet.size() % 256;
271 Utility::iovec iov[2];
272 iov[0].iov_base = (void*)buf;
274 iov[1].iov_base = (void*)&*packet.begin();
275 iov[1].iov_len = packet.size();
277 int wret = Utility::writev(dc->d_socket, iov, 2);
278 bool hadError = true;
281 g_log << Logger::Warning << "EOF writing TCP answer to " << dc->getRemote() << endl;
285 g_log << Logger::Warning << "Error writing TCP answer to " << dc->getRemote() << ": " << strerror(err) << endl;
287 else if ((unsigned int)wret != 2 + packet.size()) {
288 g_log << Logger::Warning << "Oops, partial answer sent to " << dc->getRemote() << " for " << dc->d_mdp.d_qname << " (size=" << (2 + packet.size()) << ", sent " << wret << ")" << endl;
297 // For communicating with our threads effectively readonly after
299 // First we have the handler thread, t_id == 0 (some other helper
300 // threads like SNMP might have t_id == 0 as well) then the
301 // distributor threads if any and finally the workers
306 int writeToThread{-1};
307 int readToThread{-1};
308 int writeFromThread{-1};
309 int readFromThread{-1};
310 int writeQueriesToThread{-1}; // this one is non-blocking
311 int readQueriesToThread{-1};
315 static RecThreadInfo& self()
317 return s_threadInfos.at(t_id);
320 static RecThreadInfo& info(unsigned int i)
322 return s_threadInfos.at(i);
325 static vector<RecThreadInfo>& infos()
327 return s_threadInfos;
330 bool isDistributor() const
335 return s_weDistributeQueries && listener;
338 bool isHandler() const
346 bool isWorker() const
351 bool isListener() const
356 bool isTaskThread() const
371 void setListener(bool flag = true)
381 static unsigned int id()
386 static void setThreadId(unsigned int id)
391 std::string getName() const
396 static unsigned int numHandlers()
401 static unsigned int numTaskThreads()
406 static unsigned int numWorkers()
408 return s_numWorkerThreads;
411 static unsigned int numDistributors()
413 return s_numDistributorThreads;
416 static bool weDistributeQueries()
418 return s_weDistributeQueries;
421 static void setWeDistributeQueries(bool flag)
423 s_weDistributeQueries = flag;
426 static void setNumWorkerThreads(unsigned int n)
428 s_numWorkerThreads = n;
431 static void setNumDistributorThreads(unsigned int n)
433 s_numDistributorThreads = n;
436 static unsigned int numRecursorThreads()
438 return numHandlers() + numDistributors() + numWorkers() + numTaskThreads();
441 static int runThreads();
442 static void makeThreadPipes();
444 void setExitCode(int e)
449 // FD corresponding to TCP sockets this thread is listening on.
450 // These FDs are also in deferredAdds when we have one socket per
451 // listener, and in g_deferredAdds instead.
452 std::set<int> tcpSockets;
453 // FD corresponding to listening sockets if we have one socket per
454 // listener (with reuseport), otherwise all listeners share the
455 // same FD and g_deferredAdds is then used instead
456 deferredAdd_t deferredAdds;
458 struct ThreadPipeSet pipes;
460 uint64_t numberOfDistributedQueries{0};
463 void start(unsigned int id, const string& name, const std::map<unsigned int, std::set<int>>& cpusMap);
469 // handle the web server, carbon, statistics and the control channel
471 // accept incoming queries (and distributes them to the workers if pdns-distributes-queries is set)
472 bool listener{false};
475 // run async tasks: from TastQueue and ZoneToCache
476 bool taskThread{false};
478 static thread_local unsigned int t_id;
479 static std::vector<RecThreadInfo> s_threadInfos;
480 static bool s_weDistributeQueries; // if true, 1 or more threads listen on the incoming query sockets and distribute them to workers
481 static unsigned int s_numDistributorThreads;
482 static unsigned int s_numWorkerThreads;
491 PacketBuffer GenUDPQueryResponse(const ComboAddress& dest, const string& query);
492 bool checkProtobufExport(LocalStateHolder<LuaConfigItems>& luaconfsLocal);
493 bool checkOutgoingProtobufExport(LocalStateHolder<LuaConfigItems>& luaconfsLocal);
494 bool checkFrameStreamExport(LocalStateHolder<LuaConfigItems>& luaconfsLocal);
495 void getQNameAndSubnet(const std::string& question, DNSName* dnsname, uint16_t* qtype, uint16_t* qclass,
496 bool& foundECS, EDNSSubnetOpts* ednssubnet, EDNSOptionViewMap* options,
497 bool& foundXPF, ComboAddress* xpfSource, ComboAddress* xpfDest);
498 void protobufLogQuery(LocalStateHolder<LuaConfigItems>& luaconfsLocal, const boost::uuids::uuid& uniqueId, const ComboAddress& remote, const ComboAddress& local, const Netmask& ednssubnet, bool tcp, uint16_t id, size_t len, const DNSName& qname, uint16_t qtype, uint16_t qclass, const std::unordered_set<std::string>& policyTags, const std::string& requestorId, const std::string& deviceId, const std::string& deviceName, const std::map<std::string, RecursorLua4::MetaValue>& meta);
499 bool isAllowNotifyForZone(DNSName qname);
500 bool checkForCacheHit(bool qnameParsed, unsigned int tag, const string& data,
501 DNSName& qname, uint16_t& qtype, uint16_t& qclass,
502 const struct timeval& now,
503 string& response, uint32_t& qhash,
504 RecursorPacketCache::OptPBData& pbData, bool tcp, const ComboAddress& source);
505 void protobufLogResponse(pdns::ProtoZero::RecMessage& message);
506 void protobufLogResponse(const struct dnsheader* dh, LocalStateHolder<LuaConfigItems>& luaconfsLocal,
507 const RecursorPacketCache::OptPBData& pbData, const struct timeval& tv,
508 bool tcp, const ComboAddress& source, const ComboAddress& destination,
509 const EDNSSubnetOpts& ednssubnet,
510 const boost::uuids::uuid& uniqueId, const string& requestorId, const string& deviceId,
511 const string& deviceName, const std::map<std::string, RecursorLua4::MetaValue>& meta,
512 const RecEventTrace& eventTrace);
513 void requestWipeCaches(const DNSName& canon);
514 void startDoResolve(void* p);
515 bool expectProxyProtocol(const ComboAddress& from);
516 void finishTCPReply(std::unique_ptr<DNSComboWriter>& dc, bool hadError, bool updateInFlight);
517 void checkFastOpenSysctl(bool active);
518 void checkTFOconnect();
519 void makeTCPServerSockets(deferredAdd_t& deferredAdds, std::set<int>& tcpSockets);
520 void handleNewTCPQuestion(int fd, FDMultiplexer::funcparam_t&);
522 void makeUDPServerSockets(deferredAdd_t& deferredAdds);
524 #define LOCAL_NETS "127.0.0.0/8, 10.0.0.0/8, 100.64.0.0/10, 169.254.0.0/16, 192.168.0.0/16, 172.16.0.0/12, ::1/128, fc00::/7, fe80::/10"
525 #define LOCAL_NETS_INVERSE "!127.0.0.0/8, !10.0.0.0/8, !100.64.0.0/10, !169.254.0.0/16, !192.168.0.0/16, !172.16.0.0/12, !::1/128, !fc00::/7, !fe80::/10"
526 // Bad Nets taken from both:
527 // http://www.iana.org/assignments/iana-ipv4-special-registry/iana-ipv4-special-registry.xhtml
529 // http://www.iana.org/assignments/iana-ipv6-special-registry/iana-ipv6-special-registry.xhtml
530 // where such a network may not be considered a valid destination
531 #define BAD_NETS "0.0.0.0/8, 192.0.0.0/24, 192.0.2.0/24, 198.51.100.0/24, 203.0.113.0/24, 240.0.0.0/4, ::/96, ::ffff:0:0/96, 100::/64, 2001:db8::/32"
532 #define DONT_QUERY LOCAL_NETS ", " BAD_NETS