4 #include "packethandler.hh"
6 #include "dnspacket.hh"
7 #include "auth-caches.hh"
9 #include "dnsseckeeper.hh"
14 #include "arguments.hh"
15 #include "resolver.hh"
16 #include "dns_random.hh"
17 #include "backends/gsql/ssql.hh"
18 #include "communicator.hh"
21 extern CommunicatorClass Communicator
;
23 pthread_mutex_t
PacketHandler::s_rfc2136lock
=PTHREAD_MUTEX_INITIALIZER
;
25 // Implement section 3.2.1 and 3.2.2 of RFC2136
26 int PacketHandler::checkUpdatePrerequisites(const DNSRecord
*rr
, DomainInfo
*di
) {
28 return RCode::FormErr
;
30 // 3.2.1 and 3.2.2 check content length.
31 if ( (rr
->d_class
== QClass::NONE
|| rr
->d_class
== QClass::ANY
) && rr
->d_clen
!= 0)
32 return RCode::FormErr
;
34 bool foundRecord
=false;
35 DNSResourceRecord rec
;
36 di
->backend
->lookup(QType(QType::ANY
), rr
->d_name
);
37 while(di
->backend
->get(rec
)) {
38 if (!rec
.qtype
.getCode())
40 if ((rr
->d_type
!= QType::ANY
&& rec
.qtype
== rr
->d_type
) || rr
->d_type
== QType::ANY
)
45 if (rr
->d_class
== QClass::ANY
&& !foundRecord
) {
46 if (rr
->d_type
== QType::ANY
)
47 return RCode::NXDomain
;
48 if (rr
->d_type
!= QType::ANY
)
49 return RCode::NXRRSet
;
53 if (rr
->d_class
== QClass::NONE
&& foundRecord
) {
54 if (rr
->d_type
== QType::ANY
)
55 return RCode::YXDomain
;
56 if (rr
->d_type
!= QType::ANY
)
57 return RCode::YXRRSet
;
60 return RCode::NoError
;
64 // Method implements section 3.4.1 of RFC2136
65 int PacketHandler::checkUpdatePrescan(const DNSRecord
*rr
) {
66 // The RFC stats that d_class != ZCLASS, but we only support the IN class.
67 if (rr
->d_class
!= QClass::IN
&& rr
->d_class
!= QClass::NONE
&& rr
->d_class
!= QClass::ANY
)
68 return RCode::FormErr
;
70 QType qtype
= QType(rr
->d_type
);
72 if (! qtype
.isSupportedType())
73 return RCode::FormErr
;
75 if ((rr
->d_class
== QClass::NONE
|| rr
->d_class
== QClass::ANY
) && rr
->d_ttl
!= 0)
76 return RCode::FormErr
;
78 if (rr
->d_class
== QClass::ANY
&& rr
->d_clen
!= 0)
79 return RCode::FormErr
;
81 if (qtype
.isMetadataType())
82 return RCode::FormErr
;
84 if (rr
->d_class
!= QClass::ANY
&& qtype
.getCode() == QType::ANY
)
85 return RCode::FormErr
;
87 return RCode::NoError
;
91 // Implements section 3.4.2 of RFC2136
92 uint
PacketHandler::performUpdate(const string
&msgPrefix
, const DNSRecord
*rr
, DomainInfo
*di
, bool isPresigned
, bool* narrow
, bool* haveNSEC3
, NSEC3PARAMRecordContent
*ns3pr
, bool *updatedSerial
) {
94 QType rrType
= QType(rr
->d_type
);
96 if (rrType
== QType::NSEC
|| rrType
== QType::NSEC3
) {
97 L
<<Logger::Warning
<<msgPrefix
<<"Trying to add/update/delete "<<rr
->d_name
<<"|"<<rrType
.getName()<<". These are generated records, ignoring!"<<endl
;
101 if (!isPresigned
&& ((!::arg().mustDo("direct-dnskey") && rrType
== QType::DNSKEY
) || rrType
== QType::RRSIG
)) {
102 L
<<Logger::Warning
<<msgPrefix
<<"Trying to add/update/delete "<<rr
->d_name
<<"|"<<rrType
.getName()<<" in non-presigned zone, ignoring!"<<endl
;
106 if ((rrType
== QType::NSEC3PARAM
|| rrType
== QType::DNSKEY
) && rr
->d_name
!= di
->zone
) {
107 L
<<Logger::Warning
<<msgPrefix
<<"Trying to add/update/delete "<<rr
->d_name
<<"|"<<rrType
.getName()<<", "<<rrType
.getName()<<" must be at zone apex, ignoring!"<<endl
;
112 uint changedRecords
= 0;
113 DNSResourceRecord rec
;
114 vector
<DNSResourceRecord
> rrset
, recordsToDelete
;
115 set
<DNSName
> delnonterm
, insnonterm
; // used to (at the end) fix ENT records.
118 if (rr
->d_class
== QClass::IN
) { // 3.4.2.2 QClass::IN means insert or update
119 DLOG(L
<<msgPrefix
<<"Add/Update record (QClass == IN) "<<rr
->d_name
<<"|"<<rrType
.getName()<<endl
);
121 if (rrType
== QType::NSEC3PARAM
) {
122 L
<<Logger::Notice
<<msgPrefix
<<"Adding/updating NSEC3PARAM for zone, resetting ordernames."<<endl
;
124 NSEC3PARAMRecordContent
nsec3param(rr
->d_content
->getZoneRepresentation(), di
->zone
.toString() /* FIXME400 huh */);
125 *narrow
= false; // adding a NSEC3 will cause narrow mode to be dropped, as you cannot specify that in a NSEC3PARAM record
126 d_dk
.setNSEC3PARAM(di
->zone
, nsec3param
, (*narrow
));
128 *haveNSEC3
= d_dk
.getNSEC3PARAM(di
->zone
, ns3pr
, narrow
);
130 vector
<DNSResourceRecord
> rrs
;
131 set
<DNSName
> qnames
, nssets
, dssets
;
132 di
->backend
->list(di
->zone
, di
->id
);
133 while (di
->backend
->get(rec
)) {
134 qnames
.insert(rec
.qname
);
135 if(rec
.qtype
.getCode() == QType::NS
&& rec
.qname
!= di
->zone
)
136 nssets
.insert(rec
.qname
);
137 if(rec
.qtype
.getCode() == QType::DS
)
138 dssets
.insert(rec
.qname
);
142 for(const auto& qname
: qnames
) {
146 if(qname
== di
->zone
)
148 if(nssets
.count(shorter
))
150 } while(shorter
.chopOff());
152 DNSName ordername
= DNSName(toBase32Hex(hashQNameWithSalt(*ns3pr
, qname
)));
153 if (! *narrow
&& (ddepth
== 0 || (ddepth
== 1 && nssets
.count(qname
)))) {
154 di
->backend
->updateDNSSECOrderNameAndAuth(di
->id
, qname
, ordername
, (ddepth
== 0 ));
156 if (nssets
.count(qname
)) {
158 di
->backend
->updateDNSSECOrderNameAndAuth(di
->id
, qname
, DNSName(), false, QType::NS
);
159 di
->backend
->updateDNSSECOrderNameAndAuth(di
->id
, qname
, DNSName(), false, QType::A
);
160 di
->backend
->updateDNSSECOrderNameAndAuth(di
->id
, qname
, DNSName(), false, QType::AAAA
);
163 di
->backend
->updateDNSSECOrderNameAndAuth(di
->id
, qname
, DNSName(), (ddepth
== 0));
165 if (ddepth
== 1 || dssets
.count(qname
)) // FIXME400 && ?
166 di
->backend
->updateDNSSECOrderNameAndAuth(di
->id
, qname
, ordername
, false, QType::DS
);
173 bool foundRecord
= false;
174 di
->backend
->lookup(rrType
, rr
->d_name
);
175 while (di
->backend
->get(rec
)) {
176 rrset
.push_back(rec
);
182 if (rrType
== QType::SOA
) { // SOA updates require the serial to be higher than the current
183 SOAData sdOld
, sdUpdate
;
184 DNSResourceRecord
*oldRec
= &rrset
.front();
185 fillSOAData(oldRec
->content
, sdOld
);
186 oldRec
->setContent(rr
->d_content
->getZoneRepresentation());
187 fillSOAData(oldRec
->content
, sdUpdate
);
188 if (rfc1982LessThan(sdOld
.serial
, sdUpdate
.serial
)) {
189 di
->backend
->replaceRRSet(di
->id
, oldRec
->qname
, oldRec
->qtype
, rrset
);
190 *updatedSerial
= true;
192 L
<<Logger::Notice
<<msgPrefix
<<"Replacing record "<<rr
->d_name
<<"|"<<rrType
.getName()<<endl
;
194 L
<<Logger::Notice
<<msgPrefix
<<"Provided serial ("<<sdUpdate
.serial
<<") is older than the current serial ("<<sdOld
.serial
<<"), ignoring SOA update."<<endl
;
197 // It's not possible to have multiple CNAME's with the same NAME. So we always update.
198 } else if (rrType
== QType::CNAME
) {
199 int changedCNames
= 0;
200 for (vector
<DNSResourceRecord
>::iterator i
= rrset
.begin(); i
!= rrset
.end(); i
++) {
201 if (i
->ttl
!= rr
->d_ttl
|| i
->content
!= rr
->d_content
->getZoneRepresentation()) {
203 i
->setContent(rr
->d_content
->getZoneRepresentation());
207 if (changedCNames
> 0) {
208 di
->backend
->replaceRRSet(di
->id
, rr
->d_name
, rrType
, rrset
);
209 L
<<Logger::Notice
<<msgPrefix
<<"Replacing record "<<rr
->d_name
<<"|"<<rrType
.getName()<<endl
;
210 changedRecords
+= changedCNames
;
212 L
<<Logger::Notice
<<msgPrefix
<<"Replace for record "<<rr
->d_name
<<"|"<<rrType
.getName()<<" requested, but no changes made."<<endl
;
215 // In any other case, we must check if the TYPE and RDATA match to provide an update (which effectively means a update of TTL)
219 for (vector
<DNSResourceRecord
>::iterator i
= rrset
.begin(); i
!= rrset
.end(); i
++) {
220 string content
= rr
->d_content
->getZoneRepresentation();
221 if (rrType
== i
->qtype
.getCode() && i
->getZoneRepresentation() == content
) {
223 if (i
->ttl
!= rr
->d_ttl
) {
230 di
->backend
->replaceRRSet(di
->id
, rr
->d_name
, rrType
, rrset
);
231 L
<<Logger::Notice
<<msgPrefix
<<"Replacing record "<<rr
->d_name
<<"|"<<rrType
.getName()<<endl
;
232 changedRecords
+= updateTTL
;
234 L
<<Logger::Notice
<<msgPrefix
<<"Replace for record "<<rr
->d_name
<<"|"<<rrType
.getName()<<" requested, but no changes made."<<endl
;
238 // ReplaceRRSet dumps our ordername and auth flag, so we need to correct it if we have changed records.
239 // We can take the auth flag from the first RR in the set, as the name is different, so should the auth be.
240 if (changedRecords
> 0) {
241 bool auth
= rrset
.front().auth
;
246 ordername
=DNSName(toBase32Hex(hashQNameWithSalt(*ns3pr
, rr
->d_name
)));
249 di
->backend
->updateDNSSECOrderNameAndAuth(di
->id
, rr
->d_name
, DNSName(), auth
);
251 di
->backend
->updateDNSSECOrderNameAndAuth(di
->id
, rr
->d_name
, ordername
, auth
);
252 if(!auth
|| rrType
== QType::DS
) {
253 di
->backend
->updateDNSSECOrderNameAndAuth(di
->id
, rr
->d_name
, DNSName(), false, QType::NS
);
254 di
->backend
->updateDNSSECOrderNameAndAuth(di
->id
, rr
->d_name
, DNSName(), false, QType::A
);
255 di
->backend
->updateDNSSECOrderNameAndAuth(di
->id
, rr
->d_name
, DNSName(), false, QType::AAAA
);
259 di
->backend
->updateDNSSECOrderNameAndAuth(di
->id
, rr
->d_name
, rr
->d_name
.makeRelative(di
->zone
), auth
);
260 if(!auth
|| rrType
== QType::DS
) {
261 di
->backend
->updateDNSSECOrderNameAndAuth(di
->id
, rr
->d_name
, DNSName(), false, QType::A
);
262 di
->backend
->updateDNSSECOrderNameAndAuth(di
->id
, rr
->d_name
, DNSName(), false, QType::AAAA
);
267 } // if (foundRecord)
269 // If we haven't found a record that matches, we must add it.
271 L
<<Logger::Notice
<<msgPrefix
<<"Adding record "<<rr
->d_name
<<"|"<<rrType
.getName()<<endl
;
272 delnonterm
.insert(rr
->d_name
); // always remove any ENT's in the place where we're going to add a record.
273 auto newRec
= DNSResourceRecord::fromWire(*rr
);
274 newRec
.domain_id
= di
->id
;
275 newRec
.auth
= (rr
->d_name
== di
->zone
|| rrType
.getCode() != QType::NS
);
276 di
->backend
->feedRecord(newRec
, DNSName());
280 // because we added a record, we need to fix DNSSEC data.
281 DNSName
shorter(rr
->d_name
);
282 bool auth
=newRec
.auth
;
283 bool fixDS
= (rrType
== QType::DS
);
285 if (di
->zone
!= shorter
) { // Everything at APEX is auth=1 && no ENT's
288 if (di
->zone
== shorter
)
291 bool foundShorter
= false;
292 di
->backend
->lookup(QType(QType::ANY
), shorter
);
293 while (di
->backend
->get(rec
)) {
294 if (rec
.qname
== rr
->d_name
&& rec
.qtype
== QType::DS
)
296 if (shorter
!= rr
->d_name
)
298 if (rec
.qtype
== QType::NS
) // are we inserting below a delegate?
302 if (!foundShorter
&& auth
&& shorter
!= rr
->d_name
) // haven't found any record at current level, insert ENT.
303 insnonterm
.insert(shorter
);
305 break; // if we find a shorter record, we can stop searching
306 } while(shorter
.chopOff());
313 ordername
=DNSName(toBase32Hex(hashQNameWithSalt(*ns3pr
, rr
->d_name
)));
316 di
->backend
->updateDNSSECOrderNameAndAuth(di
->id
, rr
->d_name
, DNSName(), auth
);
318 di
->backend
->updateDNSSECOrderNameAndAuth(di
->id
, rr
->d_name
, ordername
, auth
);
321 di
->backend
->updateDNSSECOrderNameAndAuth(di
->id
, rr
->d_name
, ordername
, true, QType::DS
);
326 di
->backend
->updateDNSSECOrderNameAndAuth(di
->id
, rr
->d_name
, DNSName(), false, QType::NS
);
327 di
->backend
->updateDNSSECOrderNameAndAuth(di
->id
, rr
->d_name
, DNSName(), false, QType::A
);
328 di
->backend
->updateDNSSECOrderNameAndAuth(di
->id
, rr
->d_name
, DNSName(), false, QType::AAAA
);
333 DNSName ordername
=rr
->d_name
.makeRelative(di
->zone
);
334 di
->backend
->updateDNSSECOrderNameAndAuth(di
->id
, rr
->d_name
, ordername
, auth
);
336 di
->backend
->updateDNSSECOrderNameAndAuth(di
->id
, rr
->d_name
, ordername
, true, QType::DS
);
339 di
->backend
->updateDNSSECOrderNameAndAuth(di
->id
, rr
->d_name
, DNSName(), false, QType::A
);
340 di
->backend
->updateDNSSECOrderNameAndAuth(di
->id
, rr
->d_name
, DNSName(), false, QType::AAAA
);
345 // If we insert an NS, all the records below it become non auth - so, we're inserting a delegate.
346 // Auth can only be false when the rr->d_name is not the zone
347 if (auth
== false && rrType
== QType::NS
) {
348 DLOG(L
<<msgPrefix
<<"Going to fix auth flags below "<<rr
->d_name
<<endl
);
349 insnonterm
.clear(); // No ENT's are needed below delegates (auth=0)
350 vector
<DNSName
> qnames
;
351 di
->backend
->listSubZone(rr
->d_name
, di
->id
);
352 while(di
->backend
->get(rec
)) {
353 if (rec
.qtype
.getCode() && rec
.qtype
.getCode() != QType::DS
&& rr
->d_name
!= rec
.qname
) // Skip ENT, DS and our already corrected record.
354 qnames
.push_back(rec
.qname
);
356 for(vector
<DNSName
>::const_iterator qname
=qnames
.begin(); qname
!= qnames
.end(); ++qname
) {
360 ordername
=DNSName(toBase32Hex(hashQNameWithSalt(*ns3pr
, *qname
)));
363 di
->backend
->updateDNSSECOrderNameAndAuth(di
->id
, rr
->d_name
, DNSName(), auth
); // FIXME400 no *qname here?
365 di
->backend
->updateDNSSECOrderNameAndAuth(di
->id
, *qname
, ordername
, auth
);
368 di
->backend
->updateDNSSECOrderNameAndAuth(di
->id
, *qname
, DNSName(), false, QType::NS
);
371 DNSName ordername
=DNSName(*qname
).makeRelative(di
->zone
);
372 di
->backend
->updateDNSSECOrderNameAndAuth(di
->id
, *qname
, ordername
, false, QType::NS
);
375 di
->backend
->updateDNSSECOrderNameAndAuth(di
->id
, *qname
, DNSName(), false, QType::A
);
376 di
->backend
->updateDNSSECOrderNameAndAuth(di
->id
, *qname
, DNSName(), false, QType::AAAA
);
380 } // rr->d_class == QClass::IN
383 // Delete records - section 3.4.2.3 and 3.4.2.4 with the exception of the 'always leave 1 NS rule' as that's handled by
384 // the code that calls this performUpdate().
385 if ((rr
->d_class
== QClass::ANY
|| rr
->d_class
== QClass::NONE
) && rrType
!= QType::SOA
) { // never delete a SOA.
386 DLOG(L
<<msgPrefix
<<"Deleting records: "<<rr
->d_name
<<"; QClass:"<<rr
->d_class
<<"; rrType: "<<rrType
.getName()<<endl
);
388 if (rrType
== QType::NSEC3PARAM
) {
389 L
<<Logger::Notice
<<msgPrefix
<<"Deleting NSEC3PARAM from zone, resetting ordernames."<<endl
;
390 if (rr
->d_class
== QClass::ANY
)
391 d_dk
.unsetNSEC3PARAM(rr
->d_name
);
392 else if (rr
->d_class
== QClass::NONE
) {
393 NSEC3PARAMRecordContent
nsec3rr(rr
->d_content
->getZoneRepresentation(), di
->zone
.toString() /* FIXME400 huh */);
394 if (ns3pr
->getZoneRepresentation() == nsec3rr
.getZoneRepresentation())
395 d_dk
.unsetNSEC3PARAM(rr
->d_name
);
401 // We retrieve new values, other RR's in this update package might need it as well.
402 *haveNSEC3
= d_dk
.getNSEC3PARAM(di
->zone
, ns3pr
, narrow
);
404 vector
<DNSResourceRecord
> rrs
;
405 set
<DNSName
> qnames
, nssets
, dssets
, ents
;
406 di
->backend
->list(di
->zone
, di
->id
);
407 while (di
->backend
->get(rec
)) {
408 qnames
.insert(rec
.qname
);
409 if(rec
.qtype
.getCode() == QType::NS
&& rec
.qname
!= di
->zone
)
410 nssets
.insert(rec
.qname
);
411 if(rec
.qtype
.getCode() == QType::DS
)
412 dssets
.insert(rec
.qname
);
413 if(!rec
.qtype
.getCode())
414 ents
.insert(rec
.qname
);
419 for(const DNSName
& qname
: qnames
) {
423 if(qname
== di
->zone
)
425 if(nssets
.count(shorter
))
427 } while(shorter
.chopOff());
429 DNSName ordername
=qname
.makeRelative(di
->zone
);
430 if (!ents
.count(qname
) && (ddepth
== 0 || (ddepth
== 1 && nssets
.count(qname
)))) {
431 di
->backend
->updateDNSSECOrderNameAndAuth(di
->id
, qname
, ordername
, (ddepth
== 0));
433 if (nssets
.count(qname
)) {
434 di
->backend
->updateDNSSECOrderNameAndAuth(di
->id
, qname
, DNSName(), false, QType::A
);
435 di
->backend
->updateDNSSECOrderNameAndAuth(di
->id
, qname
, DNSName(), false, QType::AAAA
);
438 di
->backend
->updateDNSSECOrderNameAndAuth(di
->id
, qname
, DNSName(), (ddepth
== 0));
440 if (ddepth
== 1 || dssets
.count(qname
))
441 di
->backend
->updateDNSSECOrderNameAndAuth(di
->id
, qname
, ordername
, true, QType::DS
);
444 } // end of NSEC3PARAM delete block
447 di
->backend
->lookup(rrType
, rr
->d_name
);
448 while(di
->backend
->get(rec
)) {
449 if (rr
->d_class
== QClass::ANY
) { // 3.4.2.3
450 if (rec
.qname
== di
->zone
&& (rec
.qtype
== QType::NS
|| rec
.qtype
== QType::SOA
)) // Never delete all SOA and NS's
451 rrset
.push_back(rec
);
453 recordsToDelete
.push_back(rec
);
455 if (rr
->d_class
== QClass::NONE
) { // 3.4.2.4
456 if (rrType
== rec
.qtype
&& rec
.getZoneRepresentation() == rr
->d_content
->getZoneRepresentation())
457 recordsToDelete
.push_back(rec
);
459 rrset
.push_back(rec
);
463 if (recordsToDelete
.size()) {
464 di
->backend
->replaceRRSet(di
->id
, rr
->d_name
, rrType
, rrset
);
465 L
<<Logger::Notice
<<msgPrefix
<<"Deleting record "<<rr
->d_name
<<"|"<<rrType
.getName()<<endl
;
466 changedRecords
+= recordsToDelete
.size();
469 // If we've removed a delegate, we need to reset ordername/auth for some records.
470 if (rrType
== QType::NS
&& rr
->d_name
!= di
->zone
) {
471 vector
<DNSName
> belowOldDelegate
, nsRecs
, updateAuthFlag
;
472 di
->backend
->listSubZone(rr
->d_name
, di
->id
);
473 while (di
->backend
->get(rec
)) {
474 if (rec
.qtype
.getCode()) // skip ENT records, they are always auth=false
475 belowOldDelegate
.push_back(rec
.qname
);
476 if (rec
.qtype
.getCode() == QType::NS
&& rec
.qname
!= rr
->d_name
)
477 nsRecs
.push_back(rec
.qname
);
480 for(auto &belowOldDel
: belowOldDelegate
)
482 bool isBelowDelegate
= false;
483 for(const auto & ns
: nsRecs
) {
484 if (ns
.isPartOf(belowOldDel
)) {
485 isBelowDelegate
=true;
489 if (!isBelowDelegate
)
490 updateAuthFlag
.push_back(belowOldDel
);
493 for (const auto &changeRec
:updateAuthFlag
) {
497 ordername
=DNSName(toBase32Hex(hashQNameWithSalt(*ns3pr
, changeRec
)));
499 di
->backend
->updateDNSSECOrderNameAndAuth(di
->id
, changeRec
, ordername
, true);
502 DNSName ordername
=changeRec
.makeRelative(di
->zone
);
503 di
->backend
->updateDNSSECOrderNameAndAuth(di
->id
, changeRec
, ordername
, true);
509 // We must check if we have a record below the current level and if we removed the 'last' record
510 // on that level. If so, we must insert an ENT record.
511 // We take extra care here to not 'include' the record that we just deleted. Some backends will still return it as they only reload on a commit.
512 bool foundDeeper
= false, foundOtherWithSameName
= false;
513 di
->backend
->listSubZone(rr
->d_name
, di
->id
);
514 while (di
->backend
->get(rec
)) {
515 if (rec
.qname
== rr
->d_name
&& !count(recordsToDelete
.begin(), recordsToDelete
.end(), rec
))
516 foundOtherWithSameName
= true;
517 if (rec
.qname
!= rr
->d_name
&& rec
.qtype
.getCode() != QType::NS
) //Skip NS records, as this would be a delegate that we can ignore as this does not require us to create a ENT
521 if (foundDeeper
&& !foundOtherWithSameName
) {
522 insnonterm
.insert(rr
->d_name
);
523 } else if (!foundOtherWithSameName
) {
524 // If we didn't have to insert an ENT, we might have deleted a record at very deep level
525 // and we must then clean up the ENT's above the deleted record.
526 DNSName
shorter(rr
->d_name
);
527 while (shorter
!= di
->zone
) {
529 bool foundRealRR
= false;
530 bool foundEnt
= false;
532 // The reason for a listSubZone here is because might go up the tree and find the ENT of another branch
533 // consider these non ENT-records:
536 // if we delete b.c.d.e.test.com, we go up to d.e.test.com and then find b.d.e.test.com because that's below d.e.test.com.
537 // At that point we can stop deleting ENT's because the tree is in tact again.
538 di
->backend
->listSubZone(shorter
, di
->id
);
540 while (di
->backend
->get(rec
)) {
541 if (rec
.qtype
.getCode())
547 if (foundEnt
) // only delete the ENT if we actually found one.
548 delnonterm
.insert(shorter
);
553 } else { // if (recordsToDelete.size())
554 L
<<Logger::Notice
<<msgPrefix
<<"Deletion for record "<<rr
->d_name
<<"|"<<rrType
.getName()<<" requested, but not found."<<endl
;
556 } // (End of delete block d_class == ANY || d_class == NONE
560 //Insert and delete ENT's
561 if (insnonterm
.size() > 0 || delnonterm
.size() > 0) {
562 DLOG(L
<<msgPrefix
<<"Updating ENT records - "<<insnonterm
.size()<<"|"<<delnonterm
.size()<<endl
);
563 di
->backend
->updateEmptyNonTerminals(di
->id
, insnonterm
, delnonterm
, false);
564 for (const auto &i
: insnonterm
) {
570 ordername
=DNSName(toBase32Hex(hashQNameWithSalt(*ns3pr
, i
)));
571 di
->backend
->updateDNSSECOrderNameAndAuth(di
->id
, i
, ordername
, true);
576 return changedRecords
;
579 int PacketHandler::forwardPacket(const string
&msgPrefix
, DNSPacket
*p
, DomainInfo
*di
) {
580 vector
<string
> forward
;
581 B
.getDomainMetadata(p
->qdomain
, "FORWARD-DNSUPDATE", forward
);
583 if (forward
.size() == 0 && ! ::arg().mustDo("forward-dnsupdate")) {
584 L
<<Logger::Notice
<<msgPrefix
<<"Not configured to forward to master, returning Refused."<<endl
;
585 return RCode::Refused
;
588 for(vector
<string
>::const_iterator master
=di
->masters
.begin(); master
!= di
->masters
.end(); master
++) {
589 L
<<Logger::Notice
<<msgPrefix
<<"Forwarding packet to master "<<*master
<<endl
;
592 remote
= ComboAddress(*master
, 53);
595 L
<<Logger::Error
<<msgPrefix
<<"Failed to parse "<<*master
<<" as valid remote."<<endl
;
600 if (remote
.sin4
.sin_family
== AF_INET
&& !::arg()["query-local-address"].empty()) {
601 local
= ComboAddress(::arg()["query-local-address"]);
602 } else if(remote
.sin4
.sin_family
== AF_INET6
&& !::arg()["query-local-address6"].empty()) {
603 local
= ComboAddress(::arg()["query-local-address6"]);
607 int sock
= makeQuerySocket(local
, false); // create TCP socket. RFC2136 section 6.2 seems to be ok with this.
609 L
<<Logger::Error
<<msgPrefix
<<"Error creating socket: "<<stringerror()<<endl
;
613 if( connect(sock
, (struct sockaddr
*)&remote
, remote
.getSocklen()) < 0 ) {
614 L
<<Logger::Error
<<msgPrefix
<<"Failed to connect to "<<remote
.toStringWithPort()<<": "<<stringerror()<<endl
;
618 catch(const PDNSException
& e
) {
619 L
<<Logger::Error
<<"Error closing master forwarding socket after connect() failed: "<<e
.reason
<<endl
;
624 DNSPacket
forwardPacket(*p
);
625 forwardPacket
.setID(dns_random(0xffff));
626 forwardPacket
.setRemote(&remote
);
627 uint16_t len
=htons(forwardPacket
.getString().length());
628 string
buffer((const char*)&len
, 2);
629 buffer
.append(forwardPacket
.getString());
630 if(write(sock
, buffer
.c_str(), buffer
.length()) < 0) {
631 L
<<Logger::Error
<<msgPrefix
<<"Unable to forward update message to "<<remote
.toStringWithPort()<<", error:"<<stringerror()<<endl
;
635 catch(const PDNSException
& e
) {
636 L
<<Logger::Error
<<"Error closing master forwarding socket after write() failed: "<<e
.reason
<<endl
;
641 int res
= waitForData(sock
, 10, 0);
643 L
<<Logger::Error
<<msgPrefix
<<"Timeout waiting for reply from master at "<<remote
.toStringWithPort()<<endl
;
647 catch(const PDNSException
& e
) {
648 L
<<Logger::Error
<<"Error closing master forwarding socket after a timeout occured: "<<e
.reason
<<endl
;
653 L
<<Logger::Error
<<msgPrefix
<<"Error waiting for answer from master at "<<remote
.toStringWithPort()<<", error:"<<stringerror()<<endl
;
657 catch(const PDNSException
& e
) {
658 L
<<Logger::Error
<<"Error closing master forwarding socket after an error occured: "<<e
.reason
<<endl
;
663 unsigned char lenBuf
[2];
665 recvRes
= recv(sock
, &lenBuf
, sizeof(lenBuf
), 0);
666 if (recvRes
< 0 || static_cast<size_t>(recvRes
) < sizeof(lenBuf
)) {
667 L
<<Logger::Error
<<msgPrefix
<<"Could not receive data (length) from master at "<<remote
.toStringWithPort()<<", error:"<<stringerror()<<endl
;
671 catch(const PDNSException
& e
) {
672 L
<<Logger::Error
<<"Error closing master forwarding socket after recv() failed: "<<e
.reason
<<endl
;
676 size_t packetLen
= lenBuf
[0]*256+lenBuf
[1];
678 buffer
.resize(packetLen
);
679 recvRes
= recv(sock
, &buffer
.at(0), packetLen
, 0);
681 L
<<Logger::Error
<<msgPrefix
<<"Could not receive data (dnspacket) from master at "<<remote
.toStringWithPort()<<", error:"<<stringerror()<<endl
;
685 catch(const PDNSException
& e
) {
686 L
<<Logger::Error
<<"Error closing master forwarding socket after recv() failed: "<<e
.reason
<<endl
;
693 catch(const PDNSException
& e
) {
694 L
<<Logger::Error
<<"Error closing master forwarding socket: "<<e
.reason
<<endl
;
698 MOADNSParser
mdp(false, buffer
.data(), static_cast<unsigned int>(recvRes
));
699 L
<<Logger::Info
<<msgPrefix
<<"Forward update message to "<<remote
.toStringWithPort()<<", result was RCode "<<mdp
.d_header
.rcode
<<endl
;
700 return mdp
.d_header
.rcode
;
703 L
<<Logger::Error
<<msgPrefix
<<"Failed to parse response packet from master at "<<remote
.toStringWithPort()<<endl
;
707 L
<<Logger::Error
<<msgPrefix
<<"Failed to forward packet to master(s). Returning ServFail."<<endl
;
708 return RCode::ServFail
;
712 int PacketHandler::processUpdate(DNSPacket
*p
) {
713 if (! ::arg().mustDo("dnsupdate"))
714 return RCode::Refused
;
716 string msgPrefix
="UPDATE (" + itoa(p
->d
.id
) + ") from " + p
->getRemote().toString() + " for " + p
->qdomain
.toLogString() + ": ";
717 L
<<Logger::Info
<<msgPrefix
<<"Processing started."<<endl
;
719 // if there is policy, we delegate all checks to it
720 if (this->d_update_policy_lua
== NULL
) {
722 // Check permissions - IP based
723 vector
<string
> allowedRanges
;
724 B
.getDomainMetadata(p
->qdomain
, "ALLOW-DNSUPDATE-FROM", allowedRanges
);
725 if (! ::arg()["allow-dnsupdate-from"].empty())
726 stringtok(allowedRanges
, ::arg()["allow-dnsupdate-from"], ", \t" );
729 for(vector
<string
>::const_iterator i
=allowedRanges
.begin(); i
!= allowedRanges
.end(); i
++)
732 if ( ! ng
.match(&p
->d_remote
)) {
733 L
<<Logger::Error
<<msgPrefix
<<"Remote not listed in allow-dnsupdate-from or domainmetadata. Sending REFUSED"<<endl
;
734 return RCode::Refused
;
738 // Check permissions - TSIG based.
739 vector
<string
> tsigKeys
;
740 B
.getDomainMetadata(p
->qdomain
, "TSIG-ALLOW-DNSUPDATE", tsigKeys
);
741 if (tsigKeys
.size() > 0) {
742 bool validKey
= false;
744 TSIGRecordContent trc
;
747 if (! p
->getTSIGDetails(&trc
, &inputkey
)) {
748 L
<<Logger::Error
<<msgPrefix
<<"TSIG key required, but packet does not contain key. Sending REFUSED"<<endl
;
749 return RCode::Refused
;
752 if (p
->d_tsig_algo
== TSIG_GSS
) {
753 GssName
inputname(p
->d_peer_principal
); // match against principal since GSS
754 for(vector
<string
>::const_iterator key
=tsigKeys
.begin(); key
!= tsigKeys
.end(); key
++) {
755 if (inputname
.match(*key
)) {
761 for(vector
<string
>::const_iterator key
=tsigKeys
.begin(); key
!= tsigKeys
.end(); key
++) {
762 if (inputkey
== DNSName(*key
)) { // because checkForCorrectTSIG has already been performed earlier on, if the names of the ky match with the domain given. THis is valid.
770 L
<<Logger::Error
<<msgPrefix
<<"TSIG key ("<<inputkey
<<") required, but no matching key found in domainmetadata, tried "<<tsigKeys
.size()<<". Sending REFUSED"<<endl
;
771 return RCode::Refused
;
775 if (tsigKeys
.size() == 0 && p
->d_havetsig
)
776 L
<<Logger::Warning
<<msgPrefix
<<"TSIG is provided, but domain is not secured with TSIG. Processing continues"<<endl
;
780 // RFC2136 uses the same DNS Header and Message as defined in RFC1035.
781 // This means we can use the MOADNSParser to parse the incoming packet. The result is that we have some different
782 // variable names during the use of our MOADNSParser.
783 MOADNSParser
mdp(false, p
->getString());
784 if (mdp
.d_header
.qdcount
!= 1) {
785 L
<<Logger::Warning
<<msgPrefix
<<"Zone Count is not 1, sending FormErr"<<endl
;
786 return RCode::FormErr
;
789 if (p
->qtype
.getCode() != QType::SOA
) { // RFC2136 2.3 - ZTYPE must be SOA
790 L
<<Logger::Warning
<<msgPrefix
<<"Query ZTYPE is not SOA, sending FormErr"<<endl
;
791 return RCode::FormErr
;
794 if (p
->qclass
!= QClass::IN
) {
795 L
<<Logger::Warning
<<msgPrefix
<<"Class is not IN, sending NotAuth"<<endl
;
796 return RCode::NotAuth
;
801 if(!B
.getDomainInfo(p
->qdomain
, di
) || !di
.backend
) {
802 L
<<Logger::Error
<<msgPrefix
<<"Can't determine backend for domain '"<<p
->qdomain
<<"' (or backend does not support DNS update operation)"<<endl
;
803 return RCode::NotAuth
;
806 if (di
.kind
== DomainInfo::Slave
)
807 return forwardPacket(msgPrefix
, p
, &di
);
809 // Check if all the records provided are within the zone
810 for(MOADNSParser::answers_t::const_iterator i
=mdp
.d_answers
.begin(); i
!= mdp
.d_answers
.end(); ++i
) {
811 const DNSRecord
*rr
= &i
->first
;
812 // Skip this check for other field types (like the TSIG - which is in the additional section)
813 // For a TSIG, the label is the dnskey, so it does not pass the endOn validation.
814 if (! (rr
->d_place
== DNSResourceRecord::ANSWER
|| rr
->d_place
== DNSResourceRecord::AUTHORITY
))
817 if (!rr
->d_name
.isPartOf(di
.zone
)) {
818 L
<<Logger::Error
<<msgPrefix
<<"Received update/record out of zone, sending NotZone."<<endl
;
819 return RCode::NotZone
;
824 Lock
l(&s_rfc2136lock
); //TODO: i think this lock can be per zone, not for everything
825 L
<<Logger::Info
<<msgPrefix
<<"starting transaction."<<endl
;
826 if (!di
.backend
->startTransaction(p
->qdomain
, -1)) { // Not giving the domain_id means that we do not delete the existing records.
827 L
<<Logger::Error
<<msgPrefix
<<"Backend for domain "<<p
->qdomain
<<" does not support transaction. Can't do Update packet."<<endl
;
828 return RCode::NotImp
;
831 // 3.2.1 and 3.2.2 - Prerequisite check
832 for(MOADNSParser::answers_t::const_iterator i
=mdp
.d_answers
.begin(); i
!= mdp
.d_answers
.end(); ++i
) {
833 const DNSRecord
*rr
= &i
->first
;
834 if (rr
->d_place
== DNSResourceRecord::ANSWER
) {
835 int res
= checkUpdatePrerequisites(rr
, &di
);
837 L
<<Logger::Error
<<msgPrefix
<<"Failed PreRequisites check, returning "<<RCode::to_s(res
)<<endl
;
838 di
.backend
->abortTransaction();
844 // 3.2.3 - Prerequisite check - this is outside of updatePrerequisitesCheck because we check an RRSet and not the RR.
845 typedef pair
<DNSName
, QType
> rrSetKey_t
;
846 typedef vector
<DNSResourceRecord
> rrVector_t
;
847 typedef std::map
<rrSetKey_t
, rrVector_t
> RRsetMap_t
;
848 RRsetMap_t preReqRRsets
;
849 for(const auto& i
: mdp
.d_answers
) {
850 const DNSRecord
* rr
= &i
.first
;
851 if (rr
->d_place
== DNSResourceRecord::ANSWER
) {
852 // Last line of 3.2.3
853 if (rr
->d_class
!= QClass::IN
&& rr
->d_class
!= QClass::NONE
&& rr
->d_class
!= QClass::ANY
)
854 return RCode::FormErr
;
856 if (rr
->d_class
== QClass::IN
) {
857 rrSetKey_t key
= make_pair(rr
->d_name
, QType(rr
->d_type
));
858 rrVector_t
*vec
= &preReqRRsets
[key
];
859 vec
->push_back(DNSResourceRecord::fromWire(*rr
));
864 if (preReqRRsets
.size() > 0) {
865 RRsetMap_t zoneRRsets
;
866 for (RRsetMap_t::iterator preRRSet
= preReqRRsets
.begin(); preRRSet
!= preReqRRsets
.end(); ++preRRSet
) {
867 rrSetKey_t rrSet
=preRRSet
->first
;
868 rrVector_t
*vec
= &preRRSet
->second
;
870 DNSResourceRecord rec
;
871 di
.backend
->lookup(QType(QType::ANY
), rrSet
.first
);
872 uint16_t foundRR
=0, matchRR
=0;
873 while (di
.backend
->get(rec
)) {
874 if (rec
.qtype
== rrSet
.second
) {
876 for(rrVector_t::iterator rrItem
=vec
->begin(); rrItem
!= vec
->end(); ++rrItem
) {
877 rrItem
->ttl
= rec
.ttl
; // The compare one line below also compares TTL, so we make them equal because TTL is not user within prerequisite checks.
883 if (matchRR
!= foundRR
|| foundRR
!= vec
->size()) {
884 L
<<Logger::Error
<<msgPrefix
<<"Failed PreRequisites check (RRs differ), returning NXRRSet"<<endl
;
885 di
.backend
->abortTransaction();
886 return RCode::NXRRSet
;
893 // 3.4 - Prescan & Add/Update/Delete records - is all done within a try block.
895 uint changedRecords
= 0;
896 // 3.4.1 - Prescan section
897 for(MOADNSParser::answers_t::const_iterator i
=mdp
.d_answers
.begin(); i
!= mdp
.d_answers
.end(); ++i
) {
898 const DNSRecord
*rr
= &i
->first
;
899 if (rr
->d_place
== DNSResourceRecord::AUTHORITY
) {
900 int res
= checkUpdatePrescan(rr
);
902 L
<<Logger::Error
<<msgPrefix
<<"Failed prescan check, returning "<<res
<<endl
;
903 di
.backend
->abortTransaction();
909 bool updatedSerial
=false;
910 NSEC3PARAMRecordContent ns3pr
;
912 bool haveNSEC3
= d_dk
.getNSEC3PARAM(di
.zone
, &ns3pr
, &narrow
);
913 bool isPresigned
= d_dk
.isPresigned(di
.zone
);
915 // 3.4.2 - Perform the updates.
916 // There's a special condition where deleting the last NS record at zone apex is never deleted (3.4.2.4)
917 // This means we must do it outside the normal performUpdate() because that focusses only on a separate RR.
918 vector
<const DNSRecord
*> nsRRtoDelete
;
920 // Another special case is the addition of both a CNAME and a non-CNAME for the same name (#6270)
921 set
<DNSName
> cn
, nocn
;
922 for (const auto &rr
: mdp
.d_answers
) {
923 if (rr
.first
.d_place
== DNSResourceRecord::AUTHORITY
&& rr
.first
.d_class
== QClass::IN
&& rr
.first
.d_ttl
> 0) {
925 if (rr
.first
.d_type
== QType::CNAME
) {
926 cn
.insert(rr
.first
.d_name
);
927 } else if (rr
.first
.d_type
!= QType::RRSIG
) {
928 nocn
.insert(rr
.first
.d_name
);
932 for (auto const &n
: cn
) {
933 if (nocn
.count(n
) > 0) {
934 L
<<Logger::Error
<<msgPrefix
<<"Refusing update, found CNAME and non-CNAME addition"<<endl
;
935 di
.backend
->abortTransaction();
936 return RCode::FormErr
;
940 vector
<const DNSRecord
*> cnamesToAdd
, nonCnamesToAdd
;
941 for(MOADNSParser::answers_t::const_iterator i
=mdp
.d_answers
.begin(); i
!= mdp
.d_answers
.end(); ++i
) {
942 const DNSRecord
*rr
= &i
->first
;
943 if (rr
->d_place
== DNSResourceRecord::AUTHORITY
) {
944 /* see if it's permitted by policy */
945 if (this->d_update_policy_lua
!= NULL
) {
946 if (this->d_update_policy_lua
->updatePolicy(rr
->d_name
, QType(rr
->d_type
), di
.zone
, p
) == false) {
947 L
<<Logger::Warning
<<msgPrefix
<<"Refusing update for " << rr
->d_name
<< "/" << QType(rr
->d_type
).getName() << ": Not permitted by policy"<<endl
;
950 L
<<Logger::Debug
<<msgPrefix
<<"Accepting update for " << rr
->d_name
<< "/" << QType(rr
->d_type
).getName() << ": Permitted by policy"<<endl
;
954 if (rr
->d_class
== QClass::NONE
&& rr
->d_type
== QType::NS
&& rr
->d_name
== di
.zone
)
955 nsRRtoDelete
.push_back(rr
);
956 else if (rr
->d_class
== QClass::IN
&& rr
->d_ttl
> 0) {
957 if (rr
->d_type
== QType::CNAME
) {
958 cnamesToAdd
.push_back(rr
);
960 nonCnamesToAdd
.push_back(rr
);
964 changedRecords
+= performUpdate(msgPrefix
, rr
, &di
, isPresigned
, &narrow
, &haveNSEC3
, &ns3pr
, &updatedSerial
);
967 for (const auto &rr
: cnamesToAdd
) {
968 DNSResourceRecord rec
;
969 di
.backend
->lookup(QType(QType::ANY
), rr
->d_name
);
970 while (di
.backend
->get(rec
)) {
971 if (rec
.qtype
!= QType::CNAME
&& rec
.qtype
!= QType::RRSIG
) {
972 L
<<Logger::Warning
<<msgPrefix
<<"Refusing update for " << rr
->d_name
<< "/" << QType(rr
->d_type
).getName() << ": Data other than CNAME exists for the same name"<<endl
;
973 di
.backend
->abortTransaction();
974 return RCode::Refused
;
977 changedRecords
+= performUpdate(msgPrefix
, rr
, &di
, isPresigned
, &narrow
, &haveNSEC3
, &ns3pr
, &updatedSerial
);
979 for (const auto &rr
: nonCnamesToAdd
) {
980 DNSResourceRecord rec
;
981 di
.backend
->lookup(QType(QType::CNAME
), rr
->d_name
);
982 while (di
.backend
->get(rec
)) {
983 if (rec
.qtype
== QType::CNAME
&& rr
->d_type
!= QType::RRSIG
) {
984 L
<<Logger::Warning
<<msgPrefix
<<"Refusing update for " << rr
->d_name
<< "/" << QType(rr
->d_type
).getName() << ": CNAME exists for the same name"<<endl
;
985 di
.backend
->abortTransaction();
986 return RCode::Refused
;
989 changedRecords
+= performUpdate(msgPrefix
, rr
, &di
, isPresigned
, &narrow
, &haveNSEC3
, &ns3pr
, &updatedSerial
);
991 if (nsRRtoDelete
.size()) {
992 vector
<DNSResourceRecord
> nsRRInZone
;
993 DNSResourceRecord rec
;
994 di
.backend
->lookup(QType(QType::NS
), di
.zone
);
995 while (di
.backend
->get(rec
)) {
996 nsRRInZone
.push_back(rec
);
998 if (nsRRInZone
.size() > nsRRtoDelete
.size()) { // only delete if the NS's we delete are less then what we have in the zone (3.4.2.4)
999 for (vector
<DNSResourceRecord
>::iterator inZone
=nsRRInZone
.begin(); inZone
!= nsRRInZone
.end(); inZone
++) {
1000 for (vector
<const DNSRecord
*>::iterator rr
=nsRRtoDelete
.begin(); rr
!= nsRRtoDelete
.end(); rr
++) {
1001 if (inZone
->getZoneRepresentation() == (*rr
)->d_content
->getZoneRepresentation())
1002 changedRecords
+= performUpdate(msgPrefix
, *rr
, &di
, isPresigned
, &narrow
, &haveNSEC3
, &ns3pr
, &updatedSerial
);
1008 // Section 3.6 - Update the SOA serial - outside of performUpdate because we do a SOA update for the complete update message
1009 if (changedRecords
> 0 && !updatedSerial
) {
1010 increaseSerial(msgPrefix
, &di
, haveNSEC3
, narrow
, &ns3pr
);
1014 if (changedRecords
> 0) {
1015 if (!di
.backend
->commitTransaction()) {
1016 L
<<Logger::Error
<<msgPrefix
<<"Failed to commit updates!"<<endl
;
1017 return RCode::ServFail
;
1020 S
.deposit("dnsupdate-changes", changedRecords
);
1022 // Purge the records!
1023 string
zone(di
.zone
.toString());
1025 purgeAuthCaches(zone
);
1028 if (di
.kind
== DomainInfo::Master
) {
1029 vector
<string
> notify
;
1030 B
.getDomainMetadata(p
->qdomain
, "NOTIFY-DNSUPDATE", notify
);
1031 if (!notify
.empty() && notify
.front() == "1") {
1032 Communicator
.notifyDomain(di
.zone
);
1036 L
<<Logger::Info
<<msgPrefix
<<"Update completed, "<<changedRecords
<<" changed records committed."<<endl
;
1038 //No change, no commit, we perform abort() because some backends might like this more.
1039 L
<<Logger::Info
<<msgPrefix
<<"Update completed, 0 changes, rolling back."<<endl
;
1040 di
.backend
->abortTransaction();
1042 return RCode::NoError
; //rfc 2136 3.4.2.5
1044 catch (SSqlException
&e
) {
1045 L
<<Logger::Error
<<msgPrefix
<<"Caught SSqlException: "<<e
.txtReason()<<"; Sending ServFail!"<<endl
;
1046 di
.backend
->abortTransaction();
1047 return RCode::ServFail
;
1049 catch (DBException
&e
) {
1050 L
<<Logger::Error
<<msgPrefix
<<"Caught DBException: "<<e
.reason
<<"; Sending ServFail!"<<endl
;
1051 di
.backend
->abortTransaction();
1052 return RCode::ServFail
;
1054 catch (PDNSException
&e
) {
1055 L
<<Logger::Error
<<msgPrefix
<<"Caught PDNSException: "<<e
.reason
<<"; Sending ServFail!"<<endl
;
1056 di
.backend
->abortTransaction();
1057 return RCode::ServFail
;
1059 catch(std::exception
&e
) {
1060 L
<<Logger::Error
<<msgPrefix
<<"Caught std:exception: "<<e
.what()<<"; Sending ServFail!"<<endl
;
1061 di
.backend
->abortTransaction();
1062 return RCode::ServFail
;
1065 L
<<Logger::Error
<<msgPrefix
<<"Caught unknown exception when performing update. Sending ServFail!"<<endl
;
1066 di
.backend
->abortTransaction();
1067 return RCode::ServFail
;
1071 void PacketHandler::increaseSerial(const string
&msgPrefix
, const DomainInfo
*di
, bool haveNSEC3
, bool narrow
, const NSEC3PARAMRecordContent
*ns3pr
) {
1073 if (!di
->backend
->getSOA(di
->zone
, sd
, true)) {
1074 throw PDNSException("SOA-Serial update failed because there was no SOA. Wowie.");
1077 uint32_t oldSerial
= sd
.serial
;
1078 if (oldSerial
== 0) { // using Autoserial, leave the serial alone.
1079 L
<<Logger::Notice
<<msgPrefix
<<"AutoSerial in use in domain \""<<di
->zone
.toLogString()<<"\", not updating SOA serial."<<endl
;
1083 vector
<string
> soaEdit2136Setting
;
1084 B
.getDomainMetadata(di
->zone
, "SOA-EDIT-DNSUPDATE", soaEdit2136Setting
);
1085 string soaEdit2136
= "DEFAULT";
1087 if (!soaEdit2136Setting
.empty()) {
1088 soaEdit2136
= soaEdit2136Setting
[0];
1089 if (pdns_iequals(soaEdit2136
, "SOA-EDIT") || pdns_iequals(soaEdit2136
,"SOA-EDIT-INCREASE") ){
1090 string soaEditSetting
;
1091 d_dk
.getSoaEdit(di
->zone
, soaEditSetting
);
1092 if (soaEditSetting
.empty()) {
1093 L
<<Logger::Error
<<msgPrefix
<<"Using "<<soaEdit2136
<<" for SOA-EDIT-DNSUPDATE increase on DNS update, but SOA-EDIT is not set for domain \""<< di
->zone
.toLogString() <<"\". Using DEFAULT for SOA-EDIT-DNSUPDATE"<<endl
;
1094 soaEdit2136
= "DEFAULT";
1096 soaEdit
= soaEditSetting
;
1100 DNSResourceRecord rr
;
1101 if (makeIncreasedSOARecord(sd
, soaEdit2136
, soaEdit
, rr
)) {
1102 di
->backend
->replaceRRSet(di
->id
, rr
.qname
, rr
.qtype
, vector
<DNSResourceRecord
>(1, rr
));
1103 L
<< Logger::Notice
<< msgPrefix
<< "Increasing SOA serial (" << oldSerial
<< " -> " << sd
.serial
<< ")" << endl
;
1105 //Correct ordername + auth flag
1109 ordername
= DNSName(toBase32Hex(hashQNameWithSalt(*ns3pr
, rr
.qname
)));
1111 di
->backend
->updateDNSSECOrderNameAndAuth(di
->id
, rr
.qname
, ordername
, true);
1113 DNSName ordername
= rr
.qname
.makeRelative(di
->zone
);
1114 di
->backend
->updateDNSSECOrderNameAndAuth(di
->id
, rr
.qname
, ordername
, true);