OpenDNSSEC-signer  1.4.5
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 "shared/duration.h"
35 #include "shared/log.h"
36 #include "shared/status.h"
37 #include "shared/util.h"
38 #include "signer/zone.h"
39 
40 #include <ldns/ldns.h>
41 
42 static const char* adapi_str = "adapter";
43 
44 
49 uint32_t
51 {
52  if (!zone || !zone->db) {
53  return 0;
54  }
55  return zone->db->inbserial;
56 }
57 
58 
63 void
64 adapi_set_serial(zone_type* zone, uint32_t serial)
65 {
66  if (!zone || !zone->db) {
67  return;
68  }
69  zone->db->inbserial = serial;
70  return;
71 }
72 
73 
78 ldns_rdf*
80 {
81  if (!zone) {
82  return NULL;
83  }
84  return zone->apex;
85 }
86 
87 
92 ldns_rr_class
94 {
95  if (!zone) {
96  return LDNS_RR_CLASS_IN;
97  }
98  return zone->klass;
99 }
100 
101 
106 uint32_t
108 {
109  if (!zone) {
110  return 0;
111  }
112  return zone->default_ttl;
113 }
114 
115 
116 /*
117  * Do full zone transaction.
118  *
119  */
120 void
121 adapi_trans_full(zone_type* zone, unsigned more_coming)
122 {
123  time_t start = 0;
124  time_t end = 0;
125  uint32_t num_added = 0;
126  if (!zone || !zone->db) {
127  return;
128  }
129  namedb_diff(zone->db, 0, more_coming);
130 
131  if (zone->stats) {
133  zone->stats->nsec_time = 0;
134  zone->stats->nsec_count = 0;
136  }
137  start = time(NULL);
138  /* nsecify(3) */
139  namedb_nsecify(zone->db, &num_added);
140  end = time(NULL);
141  if (zone->stats) {
143  if (!zone->stats->start_time) {
144  zone->stats->start_time = start;
145  }
146  zone->stats->nsec_time = (end-start);
147  zone->stats->nsec_count = num_added;
149  }
150  return;
151 }
152 
153 
154 /*
155  * Do incremental zone transaction.
156  *
157  */
158 void
159 adapi_trans_diff(zone_type* zone, unsigned more_coming)
160 {
161  time_t start = 0;
162  time_t end = 0;
163  uint32_t num_added = 0;
164  if (!zone || !zone->db) {
165  return;
166  }
167  namedb_diff(zone->db, 1, more_coming);
168 
169  if (zone->stats) {
171  zone->stats->nsec_time = 0;
172  zone->stats->nsec_count = 0;
174  }
175  start = time(NULL);
176  /* nsecify(3) */
177  namedb_nsecify(zone->db, &num_added);
178  end = time(NULL);
179  if (zone->stats) {
181  if (!zone->stats->start_time) {
182  zone->stats->start_time = start;
183  }
184  zone->stats->nsec_time = (end-start);
185  zone->stats->nsec_count = num_added;
187  }
188  return;
189 }
190 
191 
196 static ods_status
197 adapi_process_soa(zone_type* zone, ldns_rr* rr, int add, int backup)
198 {
199  uint32_t tmp = 0;
200  ldns_rdf* soa_rdata = NULL;
201  ods_status status = ODS_STATUS_OK;
202 
203  ods_log_assert(rr);
204  ods_log_assert(zone);
205  ods_log_assert(zone->name);
206  ods_log_assert(zone->signconf);
207 
208  if (backup) {
209  /* no need to do processing */
210  return ODS_STATUS_OK;
211  }
212  if (zone->signconf->soa_ttl) {
213  tmp = (uint32_t) duration2time(zone->signconf->soa_ttl);
214  ods_log_verbose("[%s] zone %s set soa ttl to %u",
215  adapi_str, zone->name, tmp);
216  ldns_rr_set_ttl(rr, tmp);
217  }
218  if (zone->signconf->soa_min) {
219  tmp = (uint32_t) duration2time(zone->signconf->soa_min);
220  ods_log_verbose("[%s] zone %s set soa minimum to %u",
221  adapi_str, zone->name, tmp);
222  soa_rdata = ldns_rr_set_rdf(rr,
223  ldns_native2rdf_int32(LDNS_RDF_TYPE_INT32, tmp),
225  if (soa_rdata) {
226  ldns_rdf_deep_free(soa_rdata);
227  soa_rdata = NULL;
228  } else {
229  ods_log_error("[%s] unable to %s soa to zone %s: failed to replace "
230  "soa minimum rdata", adapi_str, add?"add":"delete",
231  zone->name);
232  return ODS_STATUS_ASSERT_ERR;
233  }
234  }
235  if (!add) {
236  /* we are done */
237  return ODS_STATUS_OK;
238  }
239  tmp = ldns_rdf2native_int32(ldns_rr_rdf(rr, SE_SOA_RDATA_SERIAL));
240  status = namedb_update_serial(zone->db, zone->name,
241  zone->signconf->soa_serial, tmp);
242  if (status != ODS_STATUS_OK) {
243  ods_log_error("[%s] unable to add soa to zone %s: failed to replace "
244  "soa serial rdata (%s)", adapi_str, zone->name,
245  ods_status2str(status));
246  if (status == ODS_STATUS_CONFLICT_ERR) {
247  ods_log_error("[%s] If this is the result of a key rollover, "
248  "please increment the serial in the unsigned zone %s",
249  adapi_str, zone->name);
250  }
251  return status;
252  }
253  ods_log_verbose("[%s] zone %s set soa serial to %u", adapi_str,
254  zone->name, zone->db->intserial);
255  soa_rdata = ldns_rr_set_rdf(rr, ldns_native2rdf_int32(LDNS_RDF_TYPE_INT32,
256  zone->db->intserial), SE_SOA_RDATA_SERIAL);
257  if (soa_rdata) {
258  ldns_rdf_deep_free(soa_rdata);
259  soa_rdata = NULL;
260  } else {
261  ods_log_error("[%s] unable to add soa to zone %s: failed to replace "
262  "soa serial rdata", adapi_str, zone->name);
263  return ODS_STATUS_ERR;
264  }
265  zone->db->serial_updated = 1;
266  return ODS_STATUS_OK;
267 }
268 
269 
274 static void
275 adapi_process_dnskey(zone_type* zone, ldns_rr* rr)
276 {
277  uint32_t tmp = 0;
278  ods_log_assert(rr);
279  ods_log_assert(zone);
280  ods_log_assert(zone->name);
281  ods_log_assert(zone->signconf);
282  tmp = (uint32_t) duration2time(zone->signconf->dnskey_ttl);
283  ods_log_verbose("[%s] zone %s set dnskey ttl to %u",
284  adapi_str, zone->name, tmp);
285  ldns_rr_set_ttl(rr, tmp);
286  return;
287 }
288 
289 
294 static ods_status
295 adapi_process_rr(zone_type* zone, ldns_rr* rr, int add, int backup)
296 {
297  ods_status status = ODS_STATUS_OK;
298  ods_log_assert(rr);
299  ods_log_assert(zone);
300  ods_log_assert(zone->name);
301  ods_log_assert(zone->db);
302  ods_log_assert(zone->signconf);
303  /* We only support IN class */
304  if (ldns_rr_get_class(rr) != LDNS_RR_CLASS_IN) {
305  ods_log_warning("[%s] only class in is supported, changing class "
306  "to in");
307  ldns_rr_set_class(rr, LDNS_RR_CLASS_IN);
308  }
309  /* RR processing */
310  if (ldns_rr_get_type(rr) == LDNS_RR_TYPE_SOA) {
311  if (ldns_dname_compare(ldns_rr_owner(rr), zone->apex)) {
312  ods_log_error("[%s] unable to %s rr to zone: soa record has "
313  "invalid owner name", adapi_str, add?"add":"delete");
314  return ODS_STATUS_ERR;
315  }
316  status = adapi_process_soa(zone, rr, add, backup);
317  if (status != ODS_STATUS_OK) {
318  ods_log_error("[%s] unable to %s rr: failed to process soa "
319  "record", adapi_str, add?"add":"delete");
320  return status;
321  }
322  } else {
323  if (ldns_dname_compare(ldns_rr_owner(rr), zone->apex) &&
324  !ldns_dname_is_subdomain(ldns_rr_owner(rr), zone->apex)) {
325  ods_log_warning("[%s] zone %s contains out-of-zone data, "
326  "skipping", adapi_str, zone->name);
327  return ODS_STATUS_UNCHANGED;
328  } else if (ldns_rr_get_type(rr) == LDNS_RR_TYPE_DNSKEY) {
329  adapi_process_dnskey(zone, rr);
330  } else if (util_is_dnssec_rr(rr) && !backup) {
331  ods_log_warning("[%s] zone %s contains dnssec data (type=%u), "
332  "skipping", adapi_str, zone->name,
333  (unsigned) ldns_rr_get_type(rr));
334  return ODS_STATUS_UNCHANGED;
335  }
336  }
337 
338  /* TODO: DNAME and CNAME checks */
339  /* TODO: NS and DS checks */
340 
341  if (add) {
342  return zone_add_rr(zone, rr, 1);
343  } else {
344  return zone_del_rr(zone, rr, 1);
345  }
346  /* not reached */
347  return ODS_STATUS_ERR;
348 }
349 
350 
356 adapi_add_rr(zone_type* zone, ldns_rr* rr, int backup)
357 {
358  return adapi_process_rr(zone, rr, 1, backup);
359 }
360 
361 
367 adapi_del_rr(zone_type* zone, ldns_rr* rr, int backup)
368 {
369  return adapi_process_rr(zone, rr, 0, backup);
370 }
371 
372 
378 adapi_printzone(FILE* fd, zone_type* zone)
379 {
380  ods_status status = ODS_STATUS_OK;
381  if (!fd || !zone || !zone->db) {
382  ods_log_error("[%s] unable to print zone: file descriptor, zone or "
383  "name database missing", adapi_str);
384  return ODS_STATUS_ASSERT_ERR;
385  }
386  namedb_export(fd, zone->db, &status);
387  return status;
388 }
389 
390 
396 adapi_printaxfr(FILE* fd, zone_type* zone)
397 {
398  rrset_type* rrset = NULL;
399  ods_status status = ODS_STATUS_OK;
400  if (!fd || !zone || !zone->db) {
401  ods_log_error("[%s] unable to print axfr: file descriptor, zone or "
402  "name database missing", adapi_str);
403  return ODS_STATUS_ASSERT_ERR;
404  }
405  namedb_export(fd, zone->db, &status);
406  if (status == ODS_STATUS_OK) {
407  rrset = zone_lookup_rrset(zone, zone->apex, LDNS_RR_TYPE_SOA);
408  ods_log_assert(rrset);
409  rrset_print(fd, rrset, 1, &status);
410  }
411  return status;
412 }
413 
414 
420 adapi_printixfr(FILE* fd, zone_type* zone)
421 {
422  rrset_type* rrset = NULL;
423  ods_status status = ODS_STATUS_OK;
424  if (!fd || !zone || !zone->db || !zone->ixfr) {
425  ods_log_error("[%s] unable to print ixfr: file descriptor, zone or "
426  "name database missing", adapi_str);
427  return ODS_STATUS_ASSERT_ERR;
428  }
429  if (!zone->db->is_initialized) {
430  /* no ixfr yet */
431  return ODS_STATUS_OK;
432  }
433  rrset = zone_lookup_rrset(zone, zone->apex, LDNS_RR_TYPE_SOA);
434  ods_log_assert(rrset);
435  rrset_print(fd, rrset, 1, &status);
436  if (status != ODS_STATUS_OK) {
437  return status;
438  }
439  lock_basic_lock(&zone->ixfr->ixfr_lock);
440  ixfr_print(fd, zone->ixfr);
442  rrset_print(fd, rrset, 1, &status);
443  return status;
444 }