]>
git.ipfire.org Git - thirdparty/pdns.git/blob - pdns/dnsbackend.cc
7ababc55d72df3761a69ed4182cf3557f9441416
2 PowerDNS Versatile Database Driven Nameserver
3 Copyright (C) 2005 PowerDNS.COM BV
5 This program is free software; you can redistribute it and/or modify
6 it under the terms of the GNU General Public License version 2
7 as published by the Free Software Foundation
10 This program is distributed in the hope that it will be useful,
11 but WITHOUT ANY WARRANTY; without even the implied warranty of
12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 GNU General Public License for more details.
15 You should have received a copy of the GNU General Public License
16 along with this program; if not, write to the Free Software
17 Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
20 #include "dnsbackend.hh"
21 #include "arguments.hh"
22 #include "ueberbackend.hh"
25 #include <sys/types.h>
26 #include "dnspacket.hh"
29 string
DNSBackend::getRemote(DNSPacket
*p
)
31 return p
->getRemote();
34 bool DNSBackend::getRemote(DNSPacket
*p
, struct sockaddr
*sa
, Utility::socklen_t
*len
)
36 if(p
->d_remote
.getSocklen() < *len
)
38 *len
=p
->d_remote
.getSocklen();
39 memcpy(sa
,&p
->d_remote
,*len
);
43 void DNSBackend::setArgPrefix(const string
&prefix
)
48 bool DNSBackend::mustDo(const string
&key
)
50 return arg().mustDo(d_prefix
+"-"+key
);
53 const string
&DNSBackend::getArg(const string
&key
)
55 return arg()[d_prefix
+"-"+key
];
58 int DNSBackend::getArgAsNum(const string
&key
)
60 return arg().asNum(d_prefix
+"-"+key
);
63 void BackendFactory::declare(const string
&suffix
, const string
¶m
, const string
&help
, const string
&value
)
65 string fullname
=d_name
+suffix
+"-"+param
;
66 arg().set(fullname
,help
)=value
;
69 const string
&BackendFactory::getName() const
74 BackendMakerClass
&BackendMakers()
76 static BackendMakerClass bmc
;
80 void BackendMakerClass::report(BackendFactory
*bf
)
82 d_repository
[bf
->getName()]=bf
;
86 vector
<string
> BackendMakerClass::getModules()
90 // copy(d_repository.begin(), d_repository.end(),back_inserter(ret));
91 for(d_repository_t::const_iterator i
=d_repository
.begin();i
!=d_repository
.end();++i
)
92 ret
.push_back(i
->first
);
96 void BackendMakerClass::load_all()
98 // TODO: Implement this?
99 DIR *dir
=opendir(arg()["module-dir"].c_str());
101 L
<<Logger::Error
<<"Unable to open module directory '"<<arg()["module-dir"]<<"'"<<endl
;
104 struct dirent
*entry
;
105 while((entry
=readdir(dir
))) {
106 if(!strncmp(entry
->d_name
,"lib",3) &&
107 strlen(entry
->d_name
)>13 &&
108 !strcmp(entry
->d_name
+strlen(entry
->d_name
)-10,"backend.so"))
114 void BackendMakerClass::load(const string
&module
)
118 if(module
.find(".")==string::npos
)
119 res
=UeberBackend::loadmodule(arg()["module-dir"]+"/lib"+module
+"backend.so");
120 else if(module
[0]=='/' || (module
[0]=='.' && module
[1]=='/') || (module
[0]=='.' && module
[1]=='.')) // absolute or current path
121 res
=UeberBackend::loadmodule(module
);
123 res
=UeberBackend::loadmodule(arg()["module-dir"]+"/"+module
);
126 L
<<Logger::Error
<<"dnsbackend unable to load module in "<<module
<<endl
;
131 void BackendMakerClass::launch(const string
&instr
)
134 // throw ArgException("Not launching any backends - nameserver won't function");
136 vector
<string
> parts
;
137 stringtok(parts
,instr
,", ");
139 for(vector
<string
>::const_iterator i
=parts
.begin();i
!=parts
.end();++i
) {
140 const string
&part
=*i
;
143 vector
<string
>pparts
;
144 stringtok(pparts
,part
,": ");
149 if(d_repository
.find(module
)==d_repository
.end()) {
150 // this is *so* userfriendly
152 if(d_repository
.find(module
)==d_repository
.end())
153 throw ArgException("Trying to launch unknown backend '"+module
+"'");
155 d_repository
[module
]->declareArguments(name
);
156 d_instances
.push_back(make_pair(module
,name
));
160 int BackendMakerClass::numLauncheable()
162 return d_instances
.size();
165 vector
<DNSBackend
*>BackendMakerClass::all(bool metadataOnly
)
167 vector
<DNSBackend
*>ret
;
168 if(d_instances
.empty())
169 throw PDNSException("No database backends configured for launch, unable to function");
172 for(vector
<pair
<string
,string
> >::const_iterator i
=d_instances
.begin();i
!=d_instances
.end();++i
) {
175 made
= d_repository
[i
->first
]->makeMetadataOnly(i
->second
);
177 made
= d_repository
[i
->first
]->make(i
->second
);
179 throw PDNSException("Unable to launch backend '"+i
->first
+"'");
184 catch(PDNSException
&ae
) {
185 L
<<Logger::Error
<<"Caught an exception instantiating a backend: "<<ae
.reason
<<endl
;
186 L
<<Logger::Error
<<"Cleaning up"<<endl
;
187 for(vector
<DNSBackend
*>::const_iterator i
=ret
.begin();i
!=ret
.end();++i
)
192 L
<<Logger::Error
<<"Caught an exception instantiating a backend, cleaning up"<<endl
;
193 for(vector
<DNSBackend
*>::const_iterator i
=ret
.begin();i
!=ret
.end();++i
)
201 /** getSOA() is a function that is called to get the SOA of a domain. Callers should ONLY
202 use getSOA() and not perform a lookup() themselves as backends may decide to special case
205 Returns false if there is definitely no SOA for the domain. May throw a DBException
206 to indicate that the backend is currently unable to supply an answer.
208 WARNING: This function *may* fill out the db attribute of the SOAData, but then again,
209 it may not! If you find a zero in there, you may have been handed a non-live and cached
210 answer, in which case you need to perform a getDomainInfo call!
212 \param domain Domain we want to get the SOA details of
213 \param sd SOAData which is filled with the SOA details
215 bool DNSBackend::getSOA(const string
&domain
, SOAData
&sd
, DNSPacket
*p
)
217 this->lookup(QType(QType::SOA
),domain
,p
);
219 DNSResourceRecord rr
;
224 while(this->get(rr
)) {
226 fillSOAData(rr
.content
, sd
);
227 sd
.domain_id
=rr
.domain_id
;
229 sd
.scopeMask
= rr
.scopeMask
;
235 if(sd
.nameserver
.empty())
236 sd
.nameserver
=arg()["default-soa-name"];
238 if(sd
.hostmaster
.empty()) {
239 if (!arg().isEmpty("default-soa-mail")) {
240 sd
.hostmaster
=arg()["default-soa-mail"];
241 attodot(sd
.hostmaster
);
244 sd
.hostmaster
="hostmaster."+domain
;
247 if(!sd
.serial
) { // magic time!
248 DLOG(L
<<Logger::Warning
<<"Doing soa serialnumber autocalculation for "<<rr
.qname
<<endl
);
251 if (calculateSOASerial(domain
, sd
, serial
)) {
253 //DLOG(L<<"autocalculated soa serialnumber for "<<rr.qname<<" is "<<newest<<endl);
255 DLOG(L
<<"soa serialnumber calculation failed for "<<rr
.qname
<<endl
);
263 bool DNSBackend::getBeforeAndAfterNames(uint32_t id
, const std::string
& zonename
, const std::string
& qname
, std::string
& before
, std::string
& after
)
265 string lcqname
=toLower(qname
);
266 string lczonename
=toLower(zonename
);
267 lcqname
=makeRelative(lcqname
, lczonename
);
269 lcqname
=labelReverse(lcqname
);
271 bool ret
= this->getBeforeAndAfterNamesAbsolute(id
, lcqname
, dnc
, before
, after
);
273 before
=dotConcat(labelReverse(before
), lczonename
);
274 after
=dotConcat(labelReverse(after
), lczonename
);
279 * Calculates a SOA serial for the zone and stores it in the third
280 * argument. Returns false if calculation is not possible for some
281 * reason (in this case, the third argument is not inspected). If it
282 * returns true, the value returned in the third argument will be set
285 * \param domain The name of the domain
286 * \param sd Information about the SOA record already available
287 * \param serial Output parameter. Only inspected when we return true
289 bool DNSBackend::calculateSOASerial(const string
& domain
, const SOAData
& sd
, time_t& serial
)
291 // we do this by listing the domain and taking the maximum last modified timestamp
296 if(!(this->list(domain
, sd
.domain_id
))) {
297 DLOG(L
<<Logger::Warning
<<"Backend error trying to determine magic serial number of zone '"<<domain
<<"'"<<endl
);
301 while(this->get(i
)) {
302 if(i
.last_modified
>newest
)
303 newest
=i
.last_modified
;
306 serial
=newest
; // +arg().asNum("soa-serial-offset");