00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00034 #include "config.h"
00035 #include "adapter/adapi.h"
00036 #include "adapter/adfile.h"
00037 #include "adapter/adutil.h"
00038 #include "shared/duration.h"
00039 #include "shared/file.h"
00040 #include "shared/log.h"
00041 #include "shared/status.h"
00042 #include "shared/util.h"
00043 #include "signer/zone.h"
00044
00045 #include <ldns/ldns.h>
00046 #include <stdio.h>
00047 #include <stdlib.h>
00048
00049 static const char* adapter_str = "adapter";
00050 static ods_status adfile_read_file(FILE* fd, zone_type* zone);
00051
00052
00057 ods_status
00058 adfile_init(void)
00059 {
00060
00061 return ODS_STATUS_OK;
00062 }
00063
00064
00069 static ldns_rr*
00070 adfile_read_rr(FILE* fd, zone_type* zone, char* line, ldns_rdf** orig,
00071 ldns_rdf** prev, uint32_t* ttl, ldns_status* status, unsigned int* l)
00072 {
00073 ldns_rr* rr = NULL;
00074 ldns_rdf* tmp = NULL;
00075 FILE* fd_include = NULL;
00076 int len = 0;
00077 ods_status s = ODS_STATUS_OK;
00078 uint32_t new_ttl = 0;
00079 const char *endptr;
00080 int offset = 0;
00081
00082 adfile_read_line:
00083 if (ttl) {
00084 new_ttl = *ttl;
00085 }
00086
00087 len = adutil_readline_frm_file(fd, line, l);
00088 adutil_rtrim_line(line, &len);
00089
00090 if (len >= 0) {
00091 switch (line[0]) {
00092
00093 case '$':
00094 if (strncmp(line, "$ORIGIN", 7) == 0 && isspace(line[7])) {
00095
00096 if (*orig) {
00097 ldns_rdf_deep_free(*orig);
00098 *orig = NULL;
00099 }
00100 offset = 8;
00101 while (isspace(line[offset])) {
00102 offset++;
00103 }
00104 tmp = ldns_rdf_new_frm_str(LDNS_RDF_TYPE_DNAME,
00105 line + offset);
00106 if (!tmp) {
00107
00108 *status = LDNS_STATUS_SYNTAX_DNAME_ERR;
00109 return NULL;
00110 }
00111 *orig = tmp;
00112
00113 goto adfile_read_line;
00114 break;
00115 } else if (strncmp(line, "$TTL", 4) == 0 &&
00116 isspace(line[4])) {
00117
00118 offset = 5;
00119 while (isspace(line[offset])) {
00120 offset++;
00121 }
00122 if (ttl) {
00123 *ttl = ldns_str2period(line + offset, &endptr);
00124 new_ttl = *ttl;
00125 }
00126 goto adfile_read_line;
00127 break;
00128 } else if (strncmp(line, "$INCLUDE", 8) == 0 &&
00129 isspace(line[8])) {
00130
00131 offset = 9;
00132 while (isspace(line[offset])) {
00133 offset++;
00134 }
00135 fd_include = ods_fopen(line + offset, NULL, "r");
00136 if (fd_include) {
00137 s = adfile_read_file(fd_include, zone);
00138 ods_fclose(fd_include);
00139 } else {
00140 ods_log_error("[%s] unable to open include file %s",
00141 adapter_str, (line+offset));
00142 *status = LDNS_STATUS_SYNTAX_ERR;
00143 return NULL;
00144 }
00145 if (s != ODS_STATUS_OK) {
00146 *status = LDNS_STATUS_SYNTAX_ERR;
00147 ods_log_error("[%s] error in include file %s",
00148 adapter_str, (line+offset));
00149 return NULL;
00150 }
00151
00152 if (ttl) {
00153 *ttl = new_ttl;
00154 }
00155 goto adfile_read_line;
00156 break;
00157 }
00158 goto adfile_read_rr;
00159 break;
00160
00161 case ';':
00162 case '\n':
00163 goto adfile_read_line;
00164 break;
00165
00166 default:
00167 adfile_read_rr:
00168 if (adutil_whitespace_line(line, len)) {
00169 goto adfile_read_line;
00170 break;
00171 }
00172
00173 *status = ldns_rr_new_frm_str(&rr, line, new_ttl, *orig, prev);
00174 if (*status == LDNS_STATUS_OK) {
00175 ldns_rr2canonical(rr);
00176 return rr;
00177 } else if (*status == LDNS_STATUS_SYNTAX_EMPTY) {
00178 if (rr) {
00179 ldns_rr_free(rr);
00180 rr = NULL;
00181 }
00182 *status = LDNS_STATUS_OK;
00183 goto adfile_read_line;
00184 break;
00185 } else {
00186 ods_log_error("[%s] error parsing RR at line %i (%s): %s",
00187 adapter_str, l&&*l?*l:0,
00188 ldns_get_errorstr_by_id(*status), line);
00189 while (len >= 0) {
00190 len = adutil_readline_frm_file(fd, line, l);
00191 }
00192 if (rr) {
00193 ldns_rr_free(rr);
00194 rr = NULL;
00195 }
00196 return NULL;
00197 }
00198 break;
00199 }
00200 }
00201
00202
00203 *status = LDNS_STATUS_OK;
00204 return NULL;
00205 }
00206
00207
00212 static ods_status
00213 adfile_read_file(FILE* fd, zone_type* zone)
00214 {
00215 ods_status result = ODS_STATUS_OK;
00216 ldns_rr* rr = NULL;
00217 ldns_rdf* prev = NULL;
00218 ldns_rdf* orig = NULL;
00219 ldns_rdf* dname = NULL;
00220 uint32_t ttl = 0;
00221 ldns_status status = LDNS_STATUS_OK;
00222 char line[SE_ADFILE_MAXLINE];
00223 unsigned int line_update_interval = 100000;
00224 unsigned int line_update = line_update_interval;
00225 unsigned int l = 0;
00226
00227 ods_log_assert(fd);
00228 ods_log_assert(zone);
00229
00230
00231 dname = adapi_get_origin(zone);
00232 if (!dname) {
00233 ods_log_error("[%s] error getting default value for $ORIGIN",
00234 adapter_str);
00235 return ODS_STATUS_ERR;
00236 }
00237 orig = ldns_rdf_clone(dname);
00238 if (!orig) {
00239 ods_log_error("[%s] error setting default value for $ORIGIN",
00240 adapter_str);
00241 return ODS_STATUS_ERR;
00242 }
00243
00244
00245 ttl = adapi_get_ttl(zone);
00246
00247
00248 while ((rr = adfile_read_rr(fd, zone, line, &orig, &prev, &ttl,
00249 &status, &l)) != NULL) {
00250
00251 if (status != LDNS_STATUS_OK) {
00252 ods_log_error("[%s] error reading RR at line %i (%s): %s",
00253 adapter_str, l, ldns_get_errorstr_by_id(status), line);
00254 result = ODS_STATUS_ERR;
00255 break;
00256 }
00257
00258 if (l > line_update) {
00259 ods_log_debug("[%s] ...at line %i: %s", adapter_str, l, line);
00260 line_update += line_update_interval;
00261 }
00262
00263
00264 if (util_is_dnssec_rr(rr)) {
00265 ldns_rr_free(rr);
00266 rr = NULL;
00267 continue;
00268 }
00269
00270
00271 result = adapi_add_rr(zone, rr);
00272 if (result != ODS_STATUS_OK) {
00273 ods_log_error("[%s] error adding RR at line %i: %s",
00274 adapter_str, l, line);
00275 break;
00276 }
00277 }
00278
00279
00280 if (orig) {
00281 ldns_rdf_deep_free(orig);
00282 orig = NULL;
00283 }
00284 if (prev) {
00285 ldns_rdf_deep_free(prev);
00286 prev = NULL;
00287 }
00288
00289 if (result == ODS_STATUS_OK && status != LDNS_STATUS_OK) {
00290 ods_log_error("[%s] error reading RR at line %i (%s): %s",
00291 adapter_str, l, ldns_get_errorstr_by_id(status), line);
00292 result = ODS_STATUS_ERR;
00293 }
00294 return result;
00295 }
00296
00297
00302 ods_status
00303 adfile_read(struct zone_struct* zone, const char* filename)
00304 {
00305 FILE* fd = NULL;
00306 zone_type* adzone = (zone_type*) zone;
00307 ods_status status = ODS_STATUS_OK;
00308 uint32_t new_serial = 0;
00309 ldns_rr* rr = NULL;
00310
00311
00312 if (!adzone) {
00313 ods_log_error("[%s] unable to read file: no zone (or no name given)",
00314 adapter_str);
00315 return ODS_STATUS_ASSERT_ERR;
00316 }
00317 ods_log_assert(adzone);
00318 if (!filename) {
00319 ods_log_error("[%s] unable to read file: no filename given",
00320 adapter_str);
00321 return ODS_STATUS_ASSERT_ERR;
00322 }
00323 ods_log_assert(filename);
00324
00325
00326
00327 fd = ods_fopen(filename, NULL, "r");
00328 if (fd) {
00329
00330 rr = adutil_lookup_soa_rr(fd);
00331 if (rr) {
00332 new_serial =
00333 ldns_rdf2native_int32(ldns_rr_rdf(rr, SE_SOA_RDATA_SERIAL));
00334 }
00335 ldns_rr_free(rr);
00336 rewind(fd);
00337
00338 status = adfile_read_file(fd, adzone);
00339 ods_fclose(fd);
00340 } else {
00341 status = ODS_STATUS_FOPEN_ERR;
00342 }
00343 if (status != ODS_STATUS_OK) {
00344 ods_log_error("[%s] unable to read file %s: %s", adapter_str,
00345 filename, ods_status2str(status));
00346 return status;
00347 }
00348
00349
00350
00351 status = adapi_trans_full(adzone);
00352 if (status != ODS_STATUS_OK) {
00353 ods_log_error("[%s] unable to read file: start transaction failed",
00354 adapter_str);
00355 return status;
00356 }
00357
00358
00359
00360 status = zone_examine(adzone);
00361 if (status != ODS_STATUS_OK) {
00362 ods_log_error("[%s] unable to read file: zonefile contains errors",
00363 adapter_str);
00364 return status;
00365 }
00366
00367 adapi_set_serial(adzone, new_serial);
00368 return ODS_STATUS_OK;
00369 }
00370
00371
00376 ods_status
00377 adbackup_read(struct zone_struct* zone, const char* filename)
00378 {
00379 FILE* fd = NULL;
00380 zone_type* adzone = (zone_type*) zone;
00381 ods_status status = ODS_STATUS_OK;
00382
00383
00384 if (!adzone) {
00385 ods_log_error("[%s] unable to read file: no zone (or no name given)",
00386 adapter_str);
00387 return ODS_STATUS_ASSERT_ERR;
00388 }
00389 ods_log_assert(adzone);
00390 if (!filename) {
00391 ods_log_error("[%s] unable to read file: no filename given",
00392 adapter_str);
00393 return ODS_STATUS_ASSERT_ERR;
00394 }
00395 ods_log_assert(filename);
00396
00397
00398
00399 fd = ods_fopen(filename, NULL, "r");
00400 if (fd) {
00401 status = adfile_read_file(fd, adzone);
00402 ods_fclose(fd);
00403 } else {
00404 status = ODS_STATUS_FOPEN_ERR;
00405 }
00406 if (status != ODS_STATUS_OK) {
00407 ods_log_error("[%s] unable to recover file: %s", adapter_str,
00408 ods_status2str(status));
00409 return status;
00410 }
00411
00412
00413
00414 status = adapi_trans_full(adzone);
00415 if (status != ODS_STATUS_OK) {
00416 ods_log_error("[%s] unable to recover file: start transaction failed",
00417 adapter_str);
00418 return status;
00419 }
00420
00421 return ODS_STATUS_OK;
00422 }
00423
00424
00429 ods_status
00430 adfile_write(struct zone_struct* zone, const char* filename)
00431 {
00432 FILE* fd = NULL;
00433 zone_type* adzone = (zone_type*) zone;
00434 ods_status status = ODS_STATUS_OK;
00435
00436
00437 if (!adzone) {
00438 ods_log_error("[%s] unable to write file: no zone (or no "
00439 "name given)", adapter_str);
00440 return ODS_STATUS_ASSERT_ERR;
00441 }
00442 ods_log_assert(adzone);
00443 if (!filename) {
00444 ods_log_error("[%s] unable to write file: no filename given",
00445 adapter_str);
00446 return ODS_STATUS_ERR;
00447 }
00448 ods_log_assert(filename);
00449
00450
00451
00452 fd = ods_fopen(filename, NULL, "w");
00453 if (fd) {
00454 status = zone_print(fd, adzone);
00455 ods_fclose(fd);
00456 } else {
00457 status = ODS_STATUS_FOPEN_ERR;
00458 }
00459
00460
00461 return status;
00462 }