OpenDNSSEC-signer  1.3.9
util.c
Go to the documentation of this file.
1 /*
2  * $Id: util.c 4341 2011-01-31 15:21:09Z matthijs $
3  *
4  * Copyright (c) 2009 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 "shared/file.h"
36 #include "shared/log.h"
37 #include "shared/util.h"
38 
39 #include <time.h>
40 #include <ldns/ldns.h>
41 
42 static const char* util_str = "util";
43 
44 
49 int
50 util_is_dnssec_rr(ldns_rr* rr)
51 {
52  ldns_rr_type type = 0;
53 
54  if (!rr) {
55  return 0;
56  }
57 
58  type = ldns_rr_get_type(rr);
59  return (type == LDNS_RR_TYPE_RRSIG ||
60  type == LDNS_RR_TYPE_NSEC ||
61  type == LDNS_RR_TYPE_NSEC3 ||
62  type == LDNS_RR_TYPE_NSEC3PARAMS);
63 }
64 
65 
70 int
71 util_soa_compare_rdata(ldns_rr* rr1, ldns_rr* rr2)
72 {
73  size_t i = 0;
74  size_t rdata_count = SE_SOA_RDATA_MINIMUM;
75 
76  for (i = 0; i <= rdata_count; i++) {
77  if (i != SE_SOA_RDATA_SERIAL &&
78  ldns_rdf_compare(ldns_rr_rdf(rr1, i), ldns_rr_rdf(rr2, i)) != 0) {
79  return 1;
80  }
81  }
82  return 0;
83 }
84 
85 
90 int
91 util_soa_compare(ldns_rr* rr1, ldns_rr* rr2)
92 {
93  size_t rr1_len = 0;
94  size_t rr2_len = 0;
95  size_t offset = 0;
96 
97  if (!rr1 || !rr2) {
98  return 1;
99  }
100 
101  rr1_len = ldns_rr_uncompressed_size(rr1);
102  rr2_len = ldns_rr_uncompressed_size(rr2);
103  if (ldns_dname_compare(ldns_rr_owner(rr1), ldns_rr_owner(rr2)) != 0) {
104  return 1;
105  }
106  if (ldns_rr_get_class(rr1) != ldns_rr_get_class(rr2)) {
107  return 1;
108  }
109  if (ldns_rr_get_type(rr1) != LDNS_RR_TYPE_SOA) {
110  return 1;
111  }
112  if (ldns_rr_get_type(rr1) != ldns_rr_get_type(rr2)) {
113  return 1;
114  }
115  if (offset > rr1_len || offset > rr2_len) {
116  if (rr1_len == rr2_len) {
117  return util_soa_compare_rdata(rr1, rr2);
118  }
119  return 1;
120  }
121 
122  return util_soa_compare_rdata(rr1, rr2);
123 }
124 
125 
126 
131 ldns_status
132 util_dnssec_rrs_compare(ldns_rr* rr1, ldns_rr* rr2, int* cmp)
133 {
134  ldns_status status = LDNS_STATUS_OK;
135  size_t rr1_len;
136  size_t rr2_len;
137  ldns_buffer* rr1_buf;
138  ldns_buffer* rr2_buf;
139 
140  if (!rr1 || !rr2) {
141  return LDNS_STATUS_ERR;
142  }
143 
144  rr1_len = ldns_rr_uncompressed_size(rr1);
145  rr2_len = ldns_rr_uncompressed_size(rr2);
146  rr1_buf = ldns_buffer_new(rr1_len);
147  rr2_buf = ldns_buffer_new(rr2_len);
148 
149  /* name, class and type should already be equal */
150  status = ldns_rr2buffer_wire_canonical(rr1_buf, rr1, LDNS_SECTION_ANY);
151  if (status != LDNS_STATUS_OK) {
152  ldns_buffer_free(rr1_buf);
153  ldns_buffer_free(rr2_buf);
154  /* critical */
155  return status;
156  }
157  status = ldns_rr2buffer_wire_canonical(rr2_buf, rr2, LDNS_SECTION_ANY);
158  if (status != LDNS_STATUS_OK) {
159  ldns_buffer_free(rr1_buf);
160  ldns_buffer_free(rr2_buf);
161  /* critical */
162  return status;
163  }
164  *cmp = ldns_rr_compare_wire(rr1_buf, rr2_buf);
165  ldns_buffer_free(rr1_buf);
166  ldns_buffer_free(rr2_buf);
167  return LDNS_STATUS_OK;
168 }
169 
170 
175 ldns_status
176 util_dnssec_rrs_add_rr(ldns_dnssec_rrs *rrs, ldns_rr *rr)
177 {
178  int cmp = 0;
179  ldns_dnssec_rrs *new_rrs = NULL;
180  ldns_status status = LDNS_STATUS_OK;
181  uint32_t rr_ttl = 0;
182  uint32_t default_ttl = 0;
183 
184  if (!rrs || !rrs->rr || !rr) {
185  return LDNS_STATUS_ERR;
186  }
187 
188  rr_ttl = ldns_rr_ttl(rr);
189  status = util_dnssec_rrs_compare(rrs->rr, rr, &cmp);
190  if (status != LDNS_STATUS_OK) {
191  /* critical */
192  return status;
193  }
194 
195  if (cmp < 0) {
196  if (rrs->next) {
197  return util_dnssec_rrs_add_rr(rrs->next, rr);
198  } else {
199  new_rrs = ldns_dnssec_rrs_new();
200  new_rrs->rr = rr;
201  rrs->next = new_rrs;
202  default_ttl = ldns_rr_ttl(rrs->rr);
203  if (rr_ttl < default_ttl) {
204  ldns_rr_set_ttl(rrs->rr, rr_ttl);
205  } else {
206  ldns_rr_set_ttl(new_rrs->rr, default_ttl);
207  }
208  return LDNS_STATUS_OK;
209  }
210  } else if (cmp > 0) {
211  /* put the current old rr in the new next, put the new
212  rr in the current container */
213  new_rrs = ldns_dnssec_rrs_new();
214  new_rrs->rr = rrs->rr;
215  new_rrs->next = rrs->next;
216 
217  rrs->rr = rr;
218  rrs->next = new_rrs;
219 
220  default_ttl = ldns_rr_ttl(new_rrs->rr);
221  if (rr_ttl < default_ttl) {
222  ldns_rr_set_ttl(new_rrs->rr, rr_ttl);
223  } else {
224  ldns_rr_set_ttl(rrs->rr, default_ttl);
225  }
226 
227  return LDNS_STATUS_OK;
228  } else {
229  /* should we error on equal? or free memory of rr */
230  ods_log_warning("[%s] adding duplicate RR?", util_str);
231  return LDNS_STATUS_NO_DATA;
232  }
233  return LDNS_STATUS_OK;
234 }
235 
236 
241 int
242 util_write_pidfile(const char* pidfile, pid_t pid)
243 {
244  FILE* fd;
245  char pidbuf[32];
246  size_t result = 0, size = 0;
247 
248  ods_log_assert(pidfile);
249  ods_log_assert(pid);
250  ods_log_debug("[%s] writing pid %lu to pidfile %s", util_str,
251  (unsigned long) pid, pidfile);
252  snprintf(pidbuf, sizeof(pidbuf), "%lu\n", (unsigned long) pid);
253  fd = ods_fopen(pidfile, NULL, "w");
254  if (!fd) {
255  return -1;
256  }
257  size = strlen(pidbuf);
258  if (size == 0) {
259  result = 1;
260  } else {
261  result = fwrite((const void*) pidbuf, 1, size, fd);
262  }
263  if (result == 0) {
264  ods_log_error("[%s] write to pidfile %s failed: %s", util_str,
265  pidfile, strerror(errno));
266  } else if (result < size) {
267  ods_log_error("[%s] short write to pidfile %s: disk full?", util_str,
268  pidfile);
269  result = 0;
270  } else {
271  result = 1;
272  }
273  ods_fclose(fd);
274  if (!result) {
275  return -1;
276  }
277  return 0;
278 }