OpenDNSSEC-signer 2.1.12
adapi.c
Go to the documentation of this file.
1/*
2 * Copyright (c) 2009-2011 NLNet Labs. All rights reserved.
3 *
4 * Redistribution and use in source and binary forms, with or without
5 * modification, are permitted provided that the following conditions
6 * are met:
7 * 1. Redistributions of source code must retain the above copyright
8 * notice, this list of conditions and the following disclaimer.
9 * 2. Redistributions in binary form must reproduce the above copyright
10 * notice, this list of conditions and the following disclaimer in the
11 * documentation and/or other materials provided with the distribution.
12 *
13 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
14 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
15 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
16 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
17 * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
18 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
19 * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
20 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER
21 * IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
22 * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
23 * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
24 *
25 */
26
32#include "config.h"
33#include "adapter/adapi.h"
34#include "duration.h"
35#include "log.h"
36#include "status.h"
37#include "util.h"
38#include "signer/zone.h"
39
40#include <ldns/ldns.h>
41
42static const char* adapi_str = "adapter";
43
44
49uint32_t
51{
52 if (!zone || !zone->db) {
53 return 0;
54 }
55 return zone->db->inbserial;
56}
57
58
63void
64adapi_set_serial(zone_type* zone, uint32_t serial)
65{
66 if (!zone || !zone->db) {
67 return;
68 }
69 zone->db->inbserial = serial;
70}
71
72
77ldns_rdf*
79{
80 if (!zone) {
81 return NULL;
82 }
83 return zone->apex;
84}
85
86
91uint32_t
93{
94 if (!zone) {
95 return 0;
96 }
97 return zone->default_ttl;
98}
99
100
101/*
102 * Do full zone transaction.
103 *
104 */
105void
106adapi_trans_full(zone_type* zone, unsigned more_coming)
107{
108 time_t start = 0;
109 time_t end = 0;
110 uint32_t num_added = 0;
111 if (!zone || !zone->db) {
112 return;
113 }
114 namedb_diff(zone->db, 0, more_coming);
115
116 if (zone->stats) {
117 pthread_mutex_lock(&zone->stats->stats_lock);
118 zone->stats->nsec_time = 0;
119 zone->stats->nsec_count = 0;
120 pthread_mutex_unlock(&zone->stats->stats_lock);
121 }
122 start = time(NULL);
123 /* nsecify(3) */
124 namedb_nsecify(zone->db, &num_added);
125 end = time(NULL);
126 if (zone->stats) {
127 pthread_mutex_lock(&zone->stats->stats_lock);
128 if (!zone->stats->start_time) {
129 zone->stats->start_time = start;
130 }
131 zone->stats->nsec_time = (end-start);
132 zone->stats->nsec_count = num_added;
133 pthread_mutex_unlock(&zone->stats->stats_lock);
134 }
135}
136
137
138/*
139 * Do incremental zone transaction.
140 *
141 */
142void
143adapi_trans_diff(zone_type* zone, unsigned more_coming)
144{
145 time_t start = 0;
146 time_t end = 0;
147 uint32_t num_added = 0;
148 if (!zone || !zone->db) {
149 return;
150 }
151 namedb_diff(zone->db, 1, more_coming);
152
153 if (zone->stats) {
154 pthread_mutex_lock(&zone->stats->stats_lock);
155 zone->stats->nsec_time = 0;
156 zone->stats->nsec_count = 0;
157 pthread_mutex_unlock(&zone->stats->stats_lock);
158 }
159 start = time(NULL);
160 /* nsecify(3) */
161 namedb_nsecify(zone->db, &num_added);
162 end = time(NULL);
163 if (zone->stats) {
164 pthread_mutex_lock(&zone->stats->stats_lock);
165 if (!zone->stats->start_time) {
166 zone->stats->start_time = start;
167 }
168 zone->stats->nsec_time = (end-start);
169 zone->stats->nsec_count = num_added;
170 pthread_mutex_unlock(&zone->stats->stats_lock);
171 }
172}
173
174
179static ods_status
180adapi_process_soa(zone_type* zone, ldns_rr* rr, int add, int backup)
181{
182 uint32_t tmp = 0;
183 ldns_rdf* soa_rdata = NULL;
184 ods_status status = ODS_STATUS_OK;
185
186 ods_log_assert(rr);
187 ods_log_assert(zone);
188 ods_log_assert(zone->name);
189 ods_log_assert(zone->signconf);
190
191 if (backup) {
192 /* no need to do processing */
193 return ODS_STATUS_OK;
194 }
195 if (zone->signconf->soa_ttl) {
196 tmp = (uint32_t) duration2time(zone->signconf->soa_ttl);
197 ods_log_verbose("[%s] zone %s set soa ttl to %u",
198 adapi_str, zone->name, tmp);
199 ldns_rr_set_ttl(rr, tmp);
200 }
201 if (zone->signconf->soa_min) {
202 tmp = (uint32_t) duration2time(zone->signconf->soa_min);
203 ods_log_verbose("[%s] zone %s set soa minimum to %u",
204 adapi_str, zone->name, tmp);
205 soa_rdata = ldns_rr_set_rdf(rr,
206 ldns_native2rdf_int32(LDNS_RDF_TYPE_INT32, tmp),
207 SE_SOA_RDATA_MINIMUM);
208 if (soa_rdata) {
209 ldns_rdf_deep_free(soa_rdata);
210 soa_rdata = NULL;
211 } else {
212 ods_log_error("[%s] unable to %s soa to zone %s: failed to replace "
213 "soa minimum rdata", adapi_str, add?"add":"delete",
214 zone->name);
215 return ODS_STATUS_ASSERT_ERR;
216 }
217 }
218 if (!add) {
219 /* we are done */
220 return ODS_STATUS_OK;
221 }
222 tmp = ldns_rdf2native_int32(ldns_rr_rdf(rr, SE_SOA_RDATA_SERIAL));
223 status = namedb_update_serial(zone->db, zone->name,
224 zone->signconf->soa_serial, tmp);
225 if (status != ODS_STATUS_OK) {
226 ods_log_error("[%s] unable to add soa to zone %s: failed to replace "
227 "soa serial rdata (%s)", adapi_str, zone->name,
228 ods_status2str(status));
229 if (status == ODS_STATUS_CONFLICT_ERR) {
230 ods_log_error("[%s] If this is the result of a key rollover, "
231 "please increment the serial in the unsigned zone %s",
232 adapi_str, zone->name);
233 }
234 return status;
235 }
236 ods_log_verbose("[%s] zone %s set soa serial to %u", adapi_str,
237 zone->name, zone->db->intserial);
238 soa_rdata = ldns_rr_set_rdf(rr, ldns_native2rdf_int32(LDNS_RDF_TYPE_INT32,
239 zone->db->intserial), SE_SOA_RDATA_SERIAL);
240 if (soa_rdata) {
241 ldns_rdf_deep_free(soa_rdata);
242 soa_rdata = NULL;
243 } else {
244 ods_log_error("[%s] unable to add soa to zone %s: failed to replace "
245 "soa serial rdata", adapi_str, zone->name);
246 return ODS_STATUS_ERR;
247 }
248 zone->db->serial_updated = 1;
249 return ODS_STATUS_OK;
250}
251
252
257static void
258adapi_process_dnskey(zone_type* zone, ldns_rr* rr)
259{
260 uint32_t tmp = 0;
261 ods_log_assert(rr);
262 ods_log_assert(zone);
263 ods_log_assert(zone->name);
264 ods_log_assert(zone->signconf);
265 tmp = (uint32_t) duration2time(zone->signconf->dnskey_ttl);
266 ods_log_verbose("[%s] zone %s set dnskey ttl to %u",
267 adapi_str, zone->name, tmp);
268 ldns_rr_set_ttl(rr, tmp);
269}
270
271
276static ods_status
277adapi_process_rr(zone_type* zone, ldns_rr* rr, int add, int backup)
278{
279 ods_status status = ODS_STATUS_OK;
280 uint32_t tmp = 0;
281 ods_log_assert(rr);
282 ods_log_assert(zone);
283 ods_log_assert(zone->name);
284 ods_log_assert(zone->db);
285 ods_log_assert(zone->signconf);
286 /* We only support IN class */
287 if (ldns_rr_get_class(rr) != LDNS_RR_CLASS_IN) {
288 ods_log_warning("[%s] only class in is supported, changing class "
289 "to in", adapi_str);
290 ldns_rr_set_class(rr, LDNS_RR_CLASS_IN);
291 }
292 /* RR processing */
293 if (ldns_rr_get_type(rr) == LDNS_RR_TYPE_SOA) {
294 if (ldns_dname_compare(ldns_rr_owner(rr), zone->apex)) {
295 ods_log_error("[%s] unable to %s rr to zone: soa record has "
296 "invalid owner name", adapi_str, add?"add":"delete");
297 return ODS_STATUS_ERR;
298 }
299 status = adapi_process_soa(zone, rr, add, backup);
300 if (status != ODS_STATUS_OK) {
301 ods_log_error("[%s] unable to %s rr: failed to process soa "
302 "record", adapi_str, add?"add":"delete");
303 return status;
304 }
305 } else {
306 if (ldns_dname_compare(ldns_rr_owner(rr), zone->apex) &&
307 !ldns_dname_is_subdomain(ldns_rr_owner(rr), zone->apex)) {
308 ods_log_warning("[%s] zone %s contains out-of-zone data, "
309 "skipping", adapi_str, zone->name);
310 return ODS_STATUS_UNCHANGED;
311 } else if (ldns_rr_get_type(rr) == LDNS_RR_TYPE_DNSKEY) {
312 adapi_process_dnskey(zone, rr);
313 } else if (util_is_dnssec_rr(rr) && !backup) {
314 ods_log_warning("[%s] zone %s contains dnssec data (type=%u), "
315 "skipping", adapi_str, zone->name,
316 (unsigned) ldns_rr_get_type(rr));
317 return ODS_STATUS_UNCHANGED;
318 } else if (zone->signconf->max_zone_ttl) {
319 /* Convert MaxZoneTTL */
320 tmp = (uint32_t) duration2time(zone->signconf->max_zone_ttl);
321 }
322 }
323 /* //MaxZoneTTL. Only set for RRtype != SOA && RRtype != DNSKEY */
324 if (tmp && tmp < ldns_rr_ttl(rr)) {
325 char* str = ldns_rdf2str(ldns_rr_owner(rr));
326 if (str) {
327 str[(strlen(str))-1] = '\0';
328 /* replace tabs with white space */
329 for (int i = 0; i < strlen(str); i++) {
330 if (str[i] == '\t') {
331 str[i] = ' ';
332 }
333 }
334 ods_log_warning("[%s] TTL %u exceeds MaxZoneTTL %u for rrset "
335 "<%s,%s>", adapi_str, ldns_rr_ttl(rr), tmp, str,
336 rrset_type2str(ldns_rr_get_type(rr)));
337 LDNS_FREE(str);
338 }
339 }
340
341 /* TODO: DNAME and CNAME checks */
342 /* TODO: NS and DS checks */
343
344 if (add) {
345 return zone_add_rr(zone, rr, 1);
346 } else {
347 return zone_del_rr(zone, rr, 1);
348 }
349 /* not reached */
350 return ODS_STATUS_ERR;
351}
352
353
358ods_status
359adapi_add_rr(zone_type* zone, ldns_rr* rr, int backup)
360{
361 return adapi_process_rr(zone, rr, 1, backup);
362}
363
364
369ods_status
370adapi_del_rr(zone_type* zone, ldns_rr* rr, int backup)
371{
372 return adapi_process_rr(zone, rr, 0, backup);
373}
374
375
380ods_status
382{
383 ods_status status = ODS_STATUS_OK;
384 if (!fd || !zone || !zone->db) {
385 ods_log_error("[%s] unable to print zone: file descriptor, zone or "
386 "name database missing", adapi_str);
387 return ODS_STATUS_ASSERT_ERR;
388 }
389 namedb_export(fd, zone->db, &status);
390 return status;
391}
392
393
398ods_status
400{
401 rrset_type* rrset = NULL;
402 ods_status status = ODS_STATUS_OK;
403 if (!fd || !zone || !zone->db) {
404 ods_log_error("[%s] unable to print axfr: file descriptor, zone or "
405 "name database missing", adapi_str);
406 return ODS_STATUS_ASSERT_ERR;
407 }
408 namedb_export(fd, zone->db, &status);
409 if (status == ODS_STATUS_OK) {
410 rrset = zone_lookup_rrset(zone, zone->apex, LDNS_RR_TYPE_SOA);
411 ods_log_assert(rrset);
412 rrset_print(fd, rrset, 1, &status);
413 }
414 return status;
415}
416
417
422ods_status
424{
425 rrset_type* rrset = NULL;
426 ods_status status = ODS_STATUS_OK;
427 if (!fd || !zone || !zone->db || !zone->ixfr) {
428 ods_log_error("[%s] unable to print ixfr: file descriptor, zone or "
429 "name database missing", adapi_str);
430 return ODS_STATUS_ASSERT_ERR;
431 }
432 if (!zone->db->is_initialized) {
433 /* no ixfr yet */
434 return ODS_STATUS_OK;
435 }
436 rrset = zone_lookup_rrset(zone, zone->apex, LDNS_RR_TYPE_SOA);
437 ods_log_assert(rrset);
438 rrset_print(fd, rrset, 1, &status);
439 if (status != ODS_STATUS_OK) {
440 return status;
441 }
442 pthread_mutex_lock(&zone->ixfr->ixfr_lock);
443 if (ixfr_print(fd, zone->ixfr)) {
444 zone->adoutbound->error = 1;
445 }
446 pthread_mutex_unlock(&zone->ixfr->ixfr_lock);
447 rrset_print(fd, rrset, 1, &status);
448 return status;
449}
void adapi_set_serial(zone_type *zone, uint32_t serial)
Definition: adapi.c:64
ods_status adapi_add_rr(zone_type *zone, ldns_rr *rr, int backup)
Definition: adapi.c:359
void adapi_trans_full(zone_type *zone, unsigned more_coming)
Definition: adapi.c:106
ods_status adapi_printixfr(FILE *fd, zone_type *zone)
Definition: adapi.c:423
ods_status adapi_del_rr(zone_type *zone, ldns_rr *rr, int backup)
Definition: adapi.c:370
ods_status adapi_printzone(FILE *fd, zone_type *zone)
Definition: adapi.c:381
ods_status adapi_printaxfr(FILE *fd, zone_type *zone)
Definition: adapi.c:399
uint32_t adapi_get_serial(zone_type *zone)
Definition: adapi.c:50
uint32_t adapi_get_ttl(zone_type *zone)
Definition: adapi.c:92
ldns_rdf * adapi_get_origin(zone_type *zone)
Definition: adapi.c:78
void adapi_trans_diff(zone_type *zone, unsigned more_coming)
Definition: adapi.c:143
int ixfr_print(FILE *fd, ixfr_type *ixfr)
Definition: ixfr.c:216
void namedb_export(FILE *fd, namedb_type *db, ods_status *status)
Definition: namedb.c:1025
void namedb_diff(namedb_type *db, unsigned is_ixfr, unsigned more_coming)
Definition: namedb.c:811
ods_status namedb_update_serial(namedb_type *db, const char *zone_name, const char *format, uint32_t inbound_serial)
Definition: namedb.c:193
void namedb_nsecify(namedb_type *db, uint32_t *num_added)
Definition: namedb.c:872
const char * rrset_type2str(ldns_rr_type type)
Definition: rrset.c:158
void rrset_print(FILE *fd, rrset_type *rrset, int skip_rrsigs, ods_status *status)
Definition: rrset.c:871
unsigned error
Definition: adapter.h:63
pthread_mutex_t ixfr_lock
Definition: ixfr.h:64
unsigned is_initialized
Definition: namedb.h:57
uint32_t intserial
Definition: namedb.h:54
uint32_t inbserial
Definition: namedb.h:53
unsigned serial_updated
Definition: namedb.h:58
duration_type * soa_ttl
Definition: signconf.h:66
duration_type * soa_min
Definition: signconf.h:67
const char * soa_serial
Definition: signconf.h:68
duration_type * dnskey_ttl
Definition: signconf.h:62
duration_type * max_zone_ttl
Definition: signconf.h:70
pthread_mutex_t stats_lock
Definition: stats.h:63
time_t nsec_time
Definition: stats.h:55
time_t start_time
Definition: stats.h:61
uint32_t nsec_count
Definition: stats.h:54
signconf_type * signconf
Definition: zone.h:77
uint32_t default_ttl
Definition: zone.h:63
stats_type * stats
Definition: zone.h:85
namedb_type * db
Definition: zone.h:79
ldns_rdf * apex
Definition: zone.h:61
ixfr_type * ixfr
Definition: zone.h:80
const char * name
Definition: zone.h:69
adapter_type * adoutbound
Definition: zone.h:75
ods_status zone_add_rr(zone_type *zone, ldns_rr *rr, int do_stats)
Definition: zone.c:529
ods_status zone_del_rr(zone_type *zone, ldns_rr *rr, int do_stats)
Definition: zone.c:611
rrset_type * zone_lookup_rrset(zone_type *zone, ldns_rdf *owner, ldns_rr_type type)
Definition: zone.c:510