OpenDNSSEC-signer  2.1.7
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 
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 }
71 
72 
77 ldns_rdf*
79 {
80  if (!zone) {
81  return NULL;
82  }
83  return zone->apex;
84 }
85 
86 
91 uint32_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  */
105 void
106 adapi_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  */
142 void
143 adapi_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 
179 static ods_status
180 adapi_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 
257 static void
258 adapi_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 
276 static ods_status
277 adapi_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 
358 ods_status
359 adapi_add_rr(zone_type* zone, ldns_rr* rr, int backup)
360 {
361  return adapi_process_rr(zone, rr, 1, backup);
362 }
363 
364 
369 ods_status
370 adapi_del_rr(zone_type* zone, ldns_rr* rr, int backup)
371 {
372  return adapi_process_rr(zone, rr, 0, backup);
373 }
374 
375 
380 ods_status
381 adapi_printzone(FILE* fd, zone_type* zone)
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 
398 ods_status
399 adapi_printaxfr(FILE* fd, zone_type* zone)
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 
422 ods_status
423 adapi_printixfr(FILE* fd, zone_type* zone)
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 }
zone_struct::default_ttl
uint32_t default_ttl
Definition: zone.h:63
adapi_del_rr
ods_status adapi_del_rr(zone_type *zone, ldns_rr *rr, int backup)
Definition: adapi.c:370
signconf_struct::soa_min
duration_type * soa_min
Definition: signconf.h:67
signconf_struct::soa_ttl
duration_type * soa_ttl
Definition: signconf.h:66
namedb_diff
void namedb_diff(namedb_type *db, unsigned is_ixfr, unsigned more_coming)
Definition: namedb.c:811
adapi_get_ttl
uint32_t adapi_get_ttl(zone_type *zone)
Definition: adapi.c:92
adapi.h
zone_struct
Definition: zone.h:60
signconf_struct::soa_serial
const char * soa_serial
Definition: signconf.h:68
rrset_struct
Definition: rrset.h:59
zone.h
zone_add_rr
ods_status zone_add_rr(zone_type *zone, ldns_rr *rr, int do_stats)
Definition: zone.c:531
zone_struct::apex
ldns_rdf * apex
Definition: zone.h:61
zone_struct::name
const char * name
Definition: zone.h:69
namedb_struct::intserial
uint32_t intserial
Definition: namedb.h:54
adapi_printaxfr
ods_status adapi_printaxfr(FILE *fd, zone_type *zone)
Definition: adapi.c:399
adapi_set_serial
void adapi_set_serial(zone_type *zone, uint32_t serial)
Definition: adapi.c:64
rrset_print
void rrset_print(FILE *fd, rrset_type *rrset, int skip_rrsigs, ods_status *status)
Definition: rrset.c:871
ixfr_print
int ixfr_print(FILE *fd, ixfr_type *ixfr)
Definition: ixfr.c:216
zone_lookup_rrset
rrset_type * zone_lookup_rrset(zone_type *zone, ldns_rdf *owner, ldns_rr_type type)
Definition: zone.c:512
stats_struct::start_time
time_t start_time
Definition: stats.h:61
namedb_struct::inbserial
uint32_t inbserial
Definition: namedb.h:53
adapi_add_rr
ods_status adapi_add_rr(zone_type *zone, ldns_rr *rr, int backup)
Definition: adapi.c:359
stats_struct::nsec_time
time_t nsec_time
Definition: stats.h:55
adapi_get_origin
ldns_rdf * adapi_get_origin(zone_type *zone)
Definition: adapi.c:78
rrset_type2str
const char * rrset_type2str(ldns_rr_type type)
Definition: rrset.c:158
zone_struct::signconf
signconf_type * signconf
Definition: zone.h:77
namedb_export
void namedb_export(FILE *fd, namedb_type *db, ods_status *status)
Definition: namedb.c:1025
signconf_struct::max_zone_ttl
duration_type * max_zone_ttl
Definition: signconf.h:70
namedb_struct::serial_updated
unsigned serial_updated
Definition: namedb.h:58
adapi_trans_full
void adapi_trans_full(zone_type *zone, unsigned more_coming)
Definition: adapi.c:106
namedb_update_serial
ods_status namedb_update_serial(namedb_type *db, const char *zone_name, const char *format, uint32_t inbound_serial)
Definition: namedb.c:193
namedb_nsecify
void namedb_nsecify(namedb_type *db, uint32_t *num_added)
Definition: namedb.c:872
stats_struct::nsec_count
uint32_t nsec_count
Definition: stats.h:54
namedb_struct::is_initialized
unsigned is_initialized
Definition: namedb.h:57
zone_struct::db
namedb_type * db
Definition: zone.h:79
zone_struct::stats
stats_type * stats
Definition: zone.h:85
signconf_struct::dnskey_ttl
duration_type * dnskey_ttl
Definition: signconf.h:62
zone_del_rr
ods_status zone_del_rr(zone_type *zone, ldns_rr *rr, int do_stats)
Definition: zone.c:613
adapi_get_serial
uint32_t adapi_get_serial(zone_type *zone)
Definition: adapi.c:50
stats_struct::stats_lock
pthread_mutex_t stats_lock
Definition: stats.h:63
zone_struct::ixfr
ixfr_type * ixfr
Definition: zone.h:80
zone_struct::adoutbound
adapter_type * adoutbound
Definition: zone.h:75
adapi_trans_diff
void adapi_trans_diff(zone_type *zone, unsigned more_coming)
Definition: adapi.c:143
adapi_printzone
ods_status adapi_printzone(FILE *fd, zone_type *zone)
Definition: adapi.c:381
adapter_struct::error
unsigned error
Definition: adapter.h:63
ixfr_struct::ixfr_lock
pthread_mutex_t ixfr_lock
Definition: ixfr.h:64
adapi_printixfr
ods_status adapi_printixfr(FILE *fd, zone_type *zone)
Definition: adapi.c:423