8 #include "arguments.hh"
13 #include "dnswriter.hh"
14 #include "dns_random.hh"
15 #include "namespaces.hh"
17 #include "stubresolver.hh"
19 #define LOCAL_RESOLV_CONF_PATH "/etc/resolv.conf"
20 // don't stat() for local resolv.conf more than once every INTERVAL secs.
21 #define LOCAL_RESOLV_CONF_MAX_CHECK_INTERVAL 60
23 // s_resolversForStub contains the ComboAddresses that are used by
25 static vector
<ComboAddress
> s_resolversForStub
;
26 static pthread_rwlock_t s_resolversForStubLock
= PTHREAD_RWLOCK_INITIALIZER
;
27 static bool s_stubResolvConfigured
= false;
29 // /etc/resolv.conf last modification time
30 static time_t s_localResolvConfMtime
= 0;
31 static time_t s_localResolvConfLastCheck
= 0;
34 * Returns false if no resolvers are configured, while emitting a warning about this
36 bool resolversDefined()
38 ReadLock
l(&s_resolversForStubLock
);
39 if (s_resolversForStub
.empty()) {
40 g_log
<<Logger::Warning
<<"No upstream resolvers configured, stub resolving (including secpoll and ALIAS) impossible."<<endl
;
47 * Parse /etc/resolv.conf and add those nameservers to s_resolversForStub
49 static void parseLocalResolvConf_locked(const time_t& now
)
52 s_localResolvConfLastCheck
= now
;
54 if (stat(LOCAL_RESOLV_CONF_PATH
, &st
) != -1) {
55 if (st
.st_mtime
!= s_localResolvConfMtime
) {
56 std::vector
<ComboAddress
> resolvers
= getResolvers(LOCAL_RESOLV_CONF_PATH
);
58 s_localResolvConfMtime
= st
.st_mtime
;
60 if (resolvers
.empty()) {
64 s_resolversForStub
= std::move(resolvers
);
69 static void parseLocalResolvConf()
71 const time_t now
= time(nullptr);
72 if ((s_localResolvConfLastCheck
+ LOCAL_RESOLV_CONF_MAX_CHECK_INTERVAL
) > now
)
75 WriteLock
wl(&s_resolversForStubLock
);
76 parseLocalResolvConf_locked(now
);
81 * Fill the s_resolversForStub vector with addresses for the upstream resolvers.
82 * First, parse the `resolver` configuration option for IP addresses to use.
83 * If that doesn't work, parse /etc/resolv.conf and add those nameservers to
86 * mainthread() calls this so you don't have to.
88 void stubParseResolveConf()
90 if(::arg().mustDo("resolver")) {
91 WriteLock
wl(&s_resolversForStubLock
);
93 stringtok(parts
, ::arg()["resolver"], " ,\t");
94 for (const auto& addr
: parts
)
95 s_resolversForStub
.push_back(ComboAddress(addr
, 53));
98 if (s_resolversForStub
.empty()) {
99 parseLocalResolvConf();
101 // Emit a warning if there are no stubs.
103 s_stubResolvConfigured
= true;
106 // s_resolversForStub contains the ComboAddresses that are used to resolve the
107 int stubDoResolve(const DNSName
& qname
, uint16_t qtype
, vector
<DNSZoneRecord
>& ret
)
109 // ensure resolver gets always configured
110 if (!s_stubResolvConfigured
) {
111 stubParseResolveConf();
113 // only check if resolvers come from local resolv.conf in the first place
114 if (s_localResolvConfMtime
!= 0) {
115 parseLocalResolvConf();
117 if (!resolversDefined())
118 return RCode::ServFail
;
120 ReadLock
l(&s_resolversForStubLock
);
121 vector
<uint8_t> packet
;
123 DNSPacketWriter
pw(packet
, qname
, qtype
);
124 pw
.getHeader()->id
=dns_random_uint16();
125 pw
.getHeader()->rd
=1;
127 string msg
="Doing stub resolving, using resolvers: ";
128 for (const auto& server
: s_resolversForStub
) {
129 msg
+= server
.toString() + ", ";
131 g_log
<<Logger::Debug
<<msg
.substr(0, msg
.length() - 2)<<endl
;
133 for(const ComboAddress
& dest
: s_resolversForStub
) {
134 Socket
sock(dest
.sin4
.sin_family
, SOCK_DGRAM
);
135 sock
.setNonBlocking();
137 sock
.send(string(packet
.begin(), packet
.end()));
141 waitForData(sock
.getHandle(), 2, 0);
144 sock
.read(reply
); // this calls recv
145 if(reply
.size() > sizeof(struct dnsheader
)) {
147 memcpy(&d
, reply
.c_str(), sizeof(d
));
148 if(d
.id
!= pw
.getHeader()->id
)
155 MOADNSParser
mdp(false, reply
);
156 if(mdp
.d_header
.rcode
== RCode::ServFail
)
159 for(MOADNSParser::answers_t::const_iterator i
=mdp
.d_answers
.begin(); i
!=mdp
.d_answers
.end(); ++i
) {
160 if(i
->first
.d_place
== 1 && i
->first
.d_type
==qtype
) {
167 g_log
<<Logger::Debug
<<"Question got answered by "<<dest
.toString()<<endl
;
168 return mdp
.d_header
.rcode
;
170 return RCode::ServFail
;
173 int stubDoResolve(const DNSName
& qname
, uint16_t qtype
, vector
<DNSRecord
>& ret
) {
174 vector
<DNSZoneRecord
> ret2
;
175 int res
= stubDoResolve(qname
, qtype
, ret2
);
176 for (const auto &r
: ret2
) {