]>
Commit | Line | Data |
---|---|---|
92c90b44 BH |
1 | /* |
2 | PowerDNS Versatile Database Driven Nameserver | |
3 | Copyright (C) 2002-2011 PowerDNS.COM BV | |
4 | ||
5 | This program is free software; you can redistribute it and/or modify | |
6ca3fa73 | 6 | it under the terms of the GNU General Public License version 2 as |
92c90b44 BH |
7 | published by the Free Software Foundation |
8 | ||
f782fe38 MH |
9 | Additionally, the license of this program contains a special |
10 | exception which allows to distribute the program in binary form when | |
11 | it is linked against OpenSSL. | |
12 | ||
92c90b44 BH |
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 St, Fifth Floor, Boston, MA 02110-1301 USA | |
21 | */ | |
22 | ||
870a0fe4 AT |
23 | #ifdef HAVE_CONFIG_H |
24 | #include "config.h" | |
25 | #endif | |
92c90b44 BH |
26 | #include "dnsseckeeper.hh" |
27 | #include "dnspacket.hh" | |
28 | #include "namespaces.hh" | |
fa8fd4d2 | 29 | |
63347c6c | 30 | uint32_t localtime_format_YYYYMMDDSS(time_t t, uint32_t seq) |
6ca3fa73 SB |
31 | { |
32 | struct tm tm; | |
33 | localtime_r(&t, &tm); | |
34 | return | |
35 | (uint32_t)(tm.tm_year+1900) * 1000000u | |
36 | + (uint32_t)(tm.tm_mon + 1) * 10000u | |
37 | + (uint32_t)tm.tm_mday * 100u | |
38 | + seq; | |
39 | } | |
40 | ||
13f9e280 | 41 | uint32_t calculateEditSOA(uint32_t old_serial, const string& kind, const DNSName& zonename) |
92c90b44 | 42 | { |
f81291fd | 43 | if(pdns_iequals(kind,"INCEPTION-INCREMENT")) { |
5ba9719b RA |
44 | time_t inception = getStartOfWeek(); |
45 | uint32_t inception_serial = localtime_format_YYYYMMDDSS(inception, 1); | |
46 | uint32_t dont_increment_after = localtime_format_YYYYMMDDSS(inception + 2*86400, 99); | |
47 | ||
13f9e280 | 48 | if(old_serial < inception_serial - 1) { /* less than <inceptionday>00 */ |
83609e21 | 49 | return inception_serial; /* return <inceptionday>01 (skipping <inceptionday>00 as possible value) */ |
f613d242 CH |
50 | } else if (old_serial < inception_serial+1) { |
51 | /* "<inceptionday>00" and "<inceptionday>01" are reserved for inception increasing, so jump to "<inceptionday>02" */ | |
52 | return inception_serial+1; | |
13f9e280 | 53 | } else if(old_serial <= dont_increment_after) { /* >= <inceptionday>00 but <= <inceptionday+2>99 */ |
f613d242 | 54 | return old_serial + 1; |
83609e21 | 55 | } |
5ba9719b | 56 | } |
5ba9719b RA |
57 | else if(pdns_iequals(kind,"INCREMENT-WEEKS")) { |
58 | time_t inception = getStartOfWeek(); | |
13f9e280 | 59 | return (old_serial + (inception / (7*86400))); |
5ba9719b RA |
60 | } |
61 | else if(pdns_iequals(kind,"EPOCH")) { | |
5a7a3b67 | 62 | // coverity[store_truncates_time_t] |
4646277d | 63 | return time(nullptr); |
5ba9719b RA |
64 | } |
65 | else if(pdns_iequals(kind,"INCEPTION-EPOCH")) { | |
eee11292 | 66 | uint32_t inception = getStartOfWeek(); |
13f9e280 | 67 | if (old_serial < inception) |
5ba9719b | 68 | return inception; |
d605927b VV |
69 | } |
70 | else if(pdns_iequals(kind,"NONE")) { | |
71 | // do nothing to serial. needed because a metadata of "" will use the default-soa-edit setting instead. | |
72 | } | |
73 | else if(!kind.empty()) { | |
e6a9dde5 | 74 | g_log<<Logger::Warning<<"SOA-EDIT type '"<<kind<<"' for zone "<<zonename<<" is unknown."<<endl; |
5ba9719b | 75 | } |
0afb4e96 CH |
76 | // Seen strictly, this is a broken config: we can only come here if |
77 | // both SOA-EDIT and default-soa-edit are set to "", but the latter | |
78 | // should be set to "NONE" instead. | |
13f9e280 | 79 | return old_serial; |
90ba52e0 | 80 | } |
81 | ||
13f9e280 CH |
82 | uint32_t calculateEditSOA(uint32_t old_serial, DNSSECKeeper& dk, const DNSName& zonename) { |
83 | string kind; | |
84 | dk.getSoaEdit(zonename, kind); | |
13f9e280 | 85 | return calculateEditSOA(old_serial, kind, zonename); |
5ba9719b | 86 | } |
a6448d95 | 87 | |
13f9e280 CH |
88 | /** Used for SOA-EDIT-DNSUPDATE and SOA-EDIT-API. */ |
89 | static uint32_t calculateIncreaseSOA(uint32_t old_serial, const string& increaseKind, const string& editKind, const DNSName& zonename) { | |
636301b9 CH |
90 | if (pdns_iequals(increaseKind, "SOA-EDIT-INCREASE")) { |
91 | uint32_t new_serial = old_serial; | |
92 | if (!editKind.empty()) { | |
865d5504 PD |
93 | if (pdns_iequals(editKind, "INCEPTION-EPOCH")) { |
94 | new_serial = calculateEditSOA(old_serial, "EPOCH", zonename); | |
95 | } else { | |
96 | new_serial = calculateEditSOA(old_serial, editKind, zonename); | |
97 | } | |
a6448d95 | 98 | } |
636301b9 CH |
99 | if (new_serial <= old_serial) { |
100 | new_serial = old_serial + 1; | |
a6448d95 | 101 | } |
636301b9 | 102 | return new_serial; |
a6448d95 | 103 | } |
636301b9 CH |
104 | else if (pdns_iequals(increaseKind, "SOA-EDIT")) { |
105 | return calculateEditSOA(old_serial, editKind, zonename); | |
106 | } | |
107 | else if (pdns_iequals(increaseKind, "INCREASE")) { | |
13f9e280 | 108 | return old_serial + 1; |
a6448d95 CH |
109 | } |
110 | else if (pdns_iequals(increaseKind, "EPOCH")) { | |
5a7a3b67 | 111 | // coverity[store_truncates_time_t] |
4646277d | 112 | return time(nullptr); |
a6448d95 | 113 | } |
636301b9 | 114 | else if (pdns_iequals(increaseKind, "DEFAULT")) { |
4646277d | 115 | time_t now = time(nullptr); |
636301b9 CH |
116 | uint32_t new_serial = localtime_format_YYYYMMDDSS(now, 1); |
117 | if (new_serial <= old_serial) { | |
118 | new_serial = old_serial + 1; | |
119 | } | |
120 | return new_serial; | |
121 | } else if(!increaseKind.empty()) { | |
e6a9dde5 | 122 | g_log<<Logger::Warning<<"SOA-EDIT-API/DNSUPDATE type '"<<increaseKind<<"' for zone "<<zonename<<" is unknown."<<endl; |
a6448d95 | 123 | } |
636301b9 | 124 | return old_serial; |
a6448d95 CH |
125 | } |
126 | ||
13f9e280 CH |
127 | /** Used for SOA-EDIT-DNSUPDATE and SOA-EDIT-API. |
128 | * Good if you already *have* a DNSResourceRecord. | |
129 | * Content in rr is suitable for writing into a backend. | |
130 | * | |
131 | * @return true if changes may have been made | |
132 | */ | |
a6448d95 CH |
133 | bool increaseSOARecord(DNSResourceRecord& rr, const string& increaseKind, const string& editKind) { |
134 | if (increaseKind.empty()) | |
135 | return false; | |
136 | ||
137 | SOAData sd; | |
138 | fillSOAData(rr.content, sd); | |
13f9e280 CH |
139 | |
140 | sd.serial = calculateIncreaseSOA(sd.serial, increaseKind, editKind, rr.qname); | |
141 | rr.content = makeSOAContent(sd)->getZoneRepresentation(true); | |
142 | return true; | |
143 | } | |
144 | ||
145 | /** Used for SOA-EDIT-DNSUPDATE and SOA-EDIT-API. | |
146 | * Makes a mostly reset DNSResourceRecord for you in @param rrout. | |
147 | * Content in rrout is suitable for writing into a backend. | |
148 | * | |
149 | * @return true if rrout is now valid | |
150 | */ | |
151 | bool makeIncreasedSOARecord(SOAData& sd, const string& increaseKind, const string& editKind, DNSResourceRecord& rrout) { | |
152 | if (increaseKind.empty()) | |
153 | return false; | |
154 | ||
155 | sd.serial = calculateIncreaseSOA(sd.serial, increaseKind, editKind, sd.qname); | |
156 | rrout.qname = sd.qname; | |
157 | rrout.content = makeSOAContent(sd)->getZoneRepresentation(true); | |
158 | rrout.qtype = QType::SOA; | |
159 | rrout.domain_id = sd.domain_id; | |
d563b11a | 160 | rrout.auth = true; |
13f9e280 CH |
161 | rrout.ttl = sd.ttl; |
162 | ||
a6448d95 CH |
163 | return true; |
164 | } | |
5fff7d51 KM |
165 | |
166 | DNSZoneRecord makeEditedDNSZRFromSOAData(DNSSECKeeper& dk, const SOAData& sd, DNSResourceRecord::Place place) { | |
167 | SOAData edited = sd; | |
168 | edited.serial = calculateEditSOA(sd.serial, dk, sd.qname); | |
169 | ||
170 | DNSRecord soa; | |
171 | soa.d_name = sd.qname; | |
172 | soa.d_type = QType::SOA; | |
173 | soa.d_ttl = sd.ttl; | |
174 | soa.d_place = place; | |
d06dcda4 | 175 | soa.setContent(makeSOAContent(edited)); |
5fff7d51 KM |
176 | |
177 | DNSZoneRecord dzr; | |
178 | dzr.domain_id = sd.domain_id; | |
179 | dzr.signttl = sd.ttl; | |
180 | dzr.auth = true; | |
9bbcf03a | 181 | dzr.dr = std::move(soa); |
5fff7d51 KM |
182 | |
183 | return dzr; | |
184 | } |