OpenDNSSEC-signer  1.4.1
adapi.c
Go to the documentation of this file.
1 /*
2  * $Id$
3  *
4  * Copyright (c) 2009-2011 NLNet Labs. All rights reserved.
5  *
6  * Redistribution and use in source and binary forms, with or without
7  * modification, are permitted provided that the following conditions
8  * are met:
9  * 1. Redistributions of source code must retain the above copyright
10  * notice, this list of conditions and the following disclaimer.
11  * 2. Redistributions in binary form must reproduce the above copyright
12  * notice, this list of conditions and the following disclaimer in the
13  * documentation and/or other materials provided with the distribution.
14  *
15  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
16  * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
17  * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
18  * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
19  * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
20  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
21  * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
22  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER
23  * IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
24  * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
25  * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
26  *
27  */
28 
34 #include "config.h"
35 #include "adapter/adapi.h"
36 #include "shared/duration.h"
37 #include "shared/log.h"
38 #include "shared/status.h"
39 #include "shared/util.h"
40 #include "signer/zone.h"
41 
42 #include <ldns/ldns.h>
43 
44 static const char* adapi_str = "adapter";
45 
46 
51 uint32_t
53 {
54  if (!zone || !zone->db) {
55  return 0;
56  }
57  return zone->db->inbserial;
58 }
59 
60 
65 void
66 adapi_set_serial(zone_type* zone, uint32_t serial)
67 {
68  if (!zone || !zone->db) {
69  return;
70  }
71  zone->db->inbserial = serial;
72  return;
73 }
74 
75 
80 ldns_rdf*
82 {
83  if (!zone) {
84  return NULL;
85  }
86  return zone->apex;
87 }
88 
89 
94 ldns_rr_class
96 {
97  if (!zone) {
98  return LDNS_RR_CLASS_IN;
99  }
100  return zone->klass;
101 }
102 
103 
108 uint32_t
110 {
111  if (!zone) {
112  return 0;
113  }
114  return zone->default_ttl;
115 }
116 
117 
118 /*
119  * Do full zone transaction.
120  *
121  */
122 void
123 adapi_trans_full(zone_type* zone, unsigned more_coming)
124 {
125  time_t start = 0;
126  time_t end = 0;
127  uint32_t num_added = 0;
128  if (!zone || !zone->db) {
129  return;
130  }
131  namedb_diff(zone->db, 0, more_coming);
132 
133  if (zone->stats) {
135  zone->stats->nsec_time = 0;
136  zone->stats->nsec_count = 0;
138  }
139  start = time(NULL);
140  /* nsecify(3) */
141  namedb_nsecify(zone->db, &num_added);
142  end = time(NULL);
143  if (zone->stats) {
145  if (!zone->stats->start_time) {
146  zone->stats->start_time = start;
147  }
148  zone->stats->nsec_time = (end-start);
149  zone->stats->nsec_count = num_added;
151  }
152  return;
153 }
154 
155 
156 /*
157  * Do incremental zone transaction.
158  *
159  */
160 void
161 adapi_trans_diff(zone_type* zone, unsigned more_coming)
162 {
163  time_t start = 0;
164  time_t end = 0;
165  uint32_t num_added = 0;
166  if (!zone || !zone->db) {
167  return;
168  }
169  namedb_diff(zone->db, 1, more_coming);
170 
171  if (zone->stats) {
173  zone->stats->nsec_time = 0;
174  zone->stats->nsec_count = 0;
176  }
177  start = time(NULL);
178  /* nsecify(3) */
179  namedb_nsecify(zone->db, &num_added);
180  end = time(NULL);
181  if (zone->stats) {
183  if (!zone->stats->start_time) {
184  zone->stats->start_time = start;
185  }
186  zone->stats->nsec_time = (end-start);
187  zone->stats->nsec_count = num_added;
189  }
190  return;
191 }
192 
193 
198 static ods_status
199 adapi_process_soa(zone_type* zone, ldns_rr* rr, int add, int backup)
200 {
201  uint32_t tmp = 0;
202  ldns_rdf* soa_rdata = NULL;
203  ods_status status = ODS_STATUS_OK;
204 
205  ods_log_assert(rr);
206  ods_log_assert(zone);
207  ods_log_assert(zone->name);
208  ods_log_assert(zone->signconf);
209 
210  if (zone->signconf->soa_ttl) {
211  tmp = (uint32_t) duration2time(zone->signconf->soa_ttl);
212  ods_log_verbose("[%s] zone %s set soa ttl to %u",
213  adapi_str, zone->name, tmp);
214  ldns_rr_set_ttl(rr, tmp);
215  }
216  if (zone->signconf->soa_min) {
217  tmp = (uint32_t) duration2time(zone->signconf->soa_min);
218  ods_log_verbose("[%s] zone %s set soa minimum to %u",
219  adapi_str, zone->name, tmp);
220  soa_rdata = ldns_rr_set_rdf(rr,
221  ldns_native2rdf_int32(LDNS_RDF_TYPE_INT32, tmp),
223  if (soa_rdata) {
224  ldns_rdf_deep_free(soa_rdata);
225  soa_rdata = NULL;
226  } else {
227  ods_log_error("[%s] unable to %s soa to zone %s: failed to replace "
228  "soa minimum rdata", adapi_str, add?"add":"delete",
229  zone->name);
230  return ODS_STATUS_ASSERT_ERR;
231  }
232  }
233  if (!add) {
234  /* we are done */
235  return ODS_STATUS_OK;
236  }
237  tmp = ldns_rdf2native_int32(ldns_rr_rdf(rr, SE_SOA_RDATA_SERIAL));
238  status = namedb_update_serial(zone->db, zone->name,
239  zone->signconf->soa_serial, tmp);
240  if (status != ODS_STATUS_OK) {
241  ods_log_error("[%s] unable to add soa to zone %s: failed to replace "
242  "soa serial rdata (%s)", adapi_str, zone->name,
243  ods_status2str(status));
244  return status;
245  }
246  ods_log_verbose("[%s] zone %s set soa serial to %u", adapi_str,
247  zone->name, zone->db->intserial);
248  soa_rdata = ldns_rr_set_rdf(rr, ldns_native2rdf_int32(LDNS_RDF_TYPE_INT32,
249  zone->db->intserial), SE_SOA_RDATA_SERIAL);
250  if (soa_rdata) {
251  ldns_rdf_deep_free(soa_rdata);
252  soa_rdata = NULL;
253  } else {
254  ods_log_error("[%s] unable to add soa to zone %s: failed to replace "
255  "soa serial rdata", adapi_str, zone->name);
256  return ODS_STATUS_ERR;
257  }
258  if (!backup) {
259  zone->db->serial_updated = 1;
260  }
261  return ODS_STATUS_OK;
262 }
263 
264 
269 static void
270 adapi_process_dnskey(zone_type* zone, ldns_rr* rr)
271 {
272  uint32_t tmp = 0;
273  ods_log_assert(rr);
274  ods_log_assert(zone);
275  ods_log_assert(zone->name);
276  ods_log_assert(zone->signconf);
277  tmp = (uint32_t) duration2time(zone->signconf->dnskey_ttl);
278  ods_log_verbose("[%s] zone %s set dnskey ttl to %u",
279  adapi_str, zone->name, tmp);
280  ldns_rr_set_ttl(rr, tmp);
281  return;
282 }
283 
284 
289 static ods_status
290 adapi_process_rr(zone_type* zone, ldns_rr* rr, int add, int backup)
291 {
292  ods_status status = ODS_STATUS_OK;
293  ods_log_assert(rr);
294  ods_log_assert(zone);
295  ods_log_assert(zone->name);
296  ods_log_assert(zone->db);
297  ods_log_assert(zone->signconf);
298  /* We only support IN class */
299  if (ldns_rr_get_class(rr) != LDNS_RR_CLASS_IN) {
300  ods_log_warning("[%s] only class in is supported, changing class "
301  "to in");
302  ldns_rr_set_class(rr, LDNS_RR_CLASS_IN);
303  }
304  /* RR processing */
305  if (ldns_rr_get_type(rr) == LDNS_RR_TYPE_SOA) {
306  if (ldns_dname_compare(ldns_rr_owner(rr), zone->apex)) {
307  ods_log_error("[%s] unable to %s rr to zone: soa record has "
308  "invalid owner name", adapi_str, add?"add":"delete");
309  return ODS_STATUS_ERR;
310  }
311  status = adapi_process_soa(zone, rr, add, backup);
312  if (status != ODS_STATUS_OK) {
313  ods_log_error("[%s] unable to %s rr: failed to process soa "
314  "record", adapi_str, add?"add":"delete");
315  return status;
316  }
317  } else {
318  if (ldns_dname_compare(ldns_rr_owner(rr), zone->apex) &&
319  !ldns_dname_is_subdomain(ldns_rr_owner(rr), zone->apex)) {
320  ods_log_warning("[%s] zone %s contains out-of-zone data, "
321  "skipping", adapi_str, zone->name);
322  return ODS_STATUS_UNCHANGED;
323  } else if (ldns_rr_get_type(rr) == LDNS_RR_TYPE_DNSKEY) {
324  adapi_process_dnskey(zone, rr);
325  } else if (util_is_dnssec_rr(rr) && !backup) {
326  ods_log_warning("[%s] zone %s contains dnssec data (type=%u), "
327  "skipping", adapi_str, zone->name,
328  (unsigned) ldns_rr_get_type(rr));
329  return ODS_STATUS_UNCHANGED;
330  }
331  }
332 
333  /* TODO: DNAME and CNAME checks */
334  /* TODO: NS and DS checks */
335 
336  if (add) {
337  return zone_add_rr(zone, rr, 1);
338  } else {
339  return zone_del_rr(zone, rr, 1);
340  }
341  /* not reached */
342  return ODS_STATUS_ERR;
343 }
344 
345 
351 adapi_add_rr(zone_type* zone, ldns_rr* rr, int backup)
352 {
353  return adapi_process_rr(zone, rr, 1, backup);
354 }
355 
356 
362 adapi_del_rr(zone_type* zone, ldns_rr* rr, int backup)
363 {
364  return adapi_process_rr(zone, rr, 0, backup);
365 }
366 
367 
373 adapi_printzone(FILE* fd, zone_type* zone)
374 {
375  ods_status status = ODS_STATUS_OK;
376  if (!fd || !zone || !zone->db) {
377  ods_log_error("[%s] unable to print zone: file descriptor, zone or "
378  "name database missing", adapi_str);
379  return ODS_STATUS_ASSERT_ERR;
380  }
381  namedb_export(fd, zone->db, &status);
382  return status;
383 }
384 
385 
391 adapi_printaxfr(FILE* fd, zone_type* zone)
392 {
393  rrset_type* rrset = NULL;
394  ods_status status = ODS_STATUS_OK;
395  if (!fd || !zone || !zone->db) {
396  ods_log_error("[%s] unable to print axfr: file descriptor, zone or "
397  "name database missing", adapi_str);
398  return ODS_STATUS_ASSERT_ERR;
399  }
400  namedb_export(fd, zone->db, &status);
401  if (status == ODS_STATUS_OK) {
402  rrset = zone_lookup_rrset(zone, zone->apex, LDNS_RR_TYPE_SOA);
403  ods_log_assert(rrset);
404  rrset_print(fd, rrset, 1, &status);
405  }
406  return status;
407 }
408 
409 
415 adapi_printixfr(FILE* fd, zone_type* zone)
416 {
417  rrset_type* rrset = NULL;
418  ods_status status = ODS_STATUS_OK;
419  if (!fd || !zone || !zone->db || !zone->ixfr) {
420  ods_log_error("[%s] unable to print ixfr: file descriptor, zone or "
421  "name database missing", adapi_str);
422  return ODS_STATUS_ASSERT_ERR;
423  }
424  if (!zone->db->is_initialized) {
425  /* no ixfr yet */
426  return ODS_STATUS_OK;
427  }
428  rrset = zone_lookup_rrset(zone, zone->apex, LDNS_RR_TYPE_SOA);
429  ods_log_assert(rrset);
430  rrset_print(fd, rrset, 1, &status);
431  if (status != ODS_STATUS_OK) {
432  return status;
433  }
434  lock_basic_lock(&zone->ixfr->ixfr_lock);
435  ixfr_print(fd, zone->ixfr);
437  rrset_print(fd, rrset, 1, &status);
438  return status;
439 }