summaryrefslogtreecommitdiff
path: root/src/zcompile/zcompile.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/zcompile/zcompile.c')
-rw-r--r--src/zcompile/zcompile.c694
1 files changed, 0 insertions, 694 deletions
diff --git a/src/zcompile/zcompile.c b/src/zcompile/zcompile.c
deleted file mode 100644
index 636a877..0000000
--- a/src/zcompile/zcompile.c
+++ /dev/null
@@ -1,694 +0,0 @@
-/*!
- * \file zcompile.c
- *
- * \author Jan Kadlec <jan.kadlec@nic.cz>. Minor portions of code taken from
- * NSD.
- *
- * \brief Zone compiler.
- *
- * \addtogroup zoneparser
- * @{
- */
-
-/* Copyright (C) 2011 CZ.NIC, z.s.p.o. <knot-dns@labs.nic.cz>
-
- This program is free software: you can redistribute it and/or modify
- it under the terms of the GNU General Public License as published by
- the Free Software Foundation, either version 3 of the License, or
- (at your option) any later version.
-
- This program is distributed in the hope that it will be useful,
- but WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- GNU General Public License for more details.
-
- You should have received a copy of the GNU General Public License
- along with this program. If not, see <http://www.gnu.org/licenses/>.
- */
-
-#include <config.h>
-#include <assert.h>
-#include <ctype.h>
-#include <stdio.h>
-#include <string.h>
-#include <stdlib.h>
-#include <assert.h>
-#include <sys/stat.h>
-
-#include "common/base32hex.h"
-#include "common/log.h"
-#include "knot/other/debug.h"
-#include "zcompile/zcompile.h"
-#include "zcompile/parser-util.h"
-#include "zcompile/zcompile-error.h"
-#include "knot/zone/zone-dump.h"
-#include "libknot/zone/zone-diff.h"
-#include "libknot/libknot.h"
-#include "libknot/util/utils.h"
-
-/* Some global flags... */
-static int vflag = 0;
-/* if -v then print progress each 'progress' RRs */
-static int progress = 10000;
-
-/* Total errors counter */
-static long int totalerrors = 0;
-static long int totalrrs = 0;
-
-extern FILE *zp_get_in(void *scanner);
-
-/*!
- * \brief Adds RRSet to list.
- *
- * \param head Head of list.
- * \param rrsig RRSet to be added.
- */
-static int rrset_list_add(rrset_list_t **head, knot_rrset_t *rrsig)
-{
- if (*head == NULL) {
- *head = malloc(sizeof(rrset_list_t));
- if (*head == NULL) {
- ERR_ALLOC_FAILED;
- return KNOTDZCOMPILE_ENOMEM;
- }
- (*head)->next = NULL;
- (*head)->data = rrsig;
- } else {
- rrset_list_t *tmp = malloc(sizeof(*tmp));
- if (tmp == NULL) {
- ERR_ALLOC_FAILED;
- return KNOTDZCOMPILE_ENOMEM;
- }
- tmp->next = *head;
- tmp->data = rrsig;
- *head = tmp;
- }
-
- dbg_zp_verb("zp: rrset_add: Added RRSIG %p to list.\n", rrsig);
-
- return KNOTDZCOMPILE_EOK;
-}
-
-/*!
- * \brief Deletes RRSet list. Sets pointer to NULL.
- *
- * \param head Head of list to be deleted.
- */
-static void rrset_list_delete(rrset_list_t **head)
-{
- rrset_list_t *tmp;
- if (*head == NULL) {
- return;
- }
-
- while (*head != NULL) {
- tmp = *head;
- *head = (*head)->next;
- free(tmp);
- }
-
- *head = NULL;
-
- dbg_zp("zp: list_delete: List deleleted.\n");
-}
-
-static int find_rrset_for_rrsig_in_node(knot_zone_contents_t *zone,
- knot_node_t *node,
- knot_rrset_t *rrsig)
-{
- assert(rrsig != NULL);
- assert(rrsig->rdata->items[0].raw_data);
- assert(node);
-
- assert(knot_dname_compare(rrsig->owner, node->owner) == 0);
-
- knot_rrset_t *tmp_rrset =
- knot_node_get_rrset(node, rrsig_type_covered(rrsig));
-
- int ret;
-
- if (tmp_rrset == NULL) {
- dbg_zp("zp: find_rr_for_sig_in_node: Node does not contain "
- "RRSet of type %s.\n",
- knot_rrtype_to_string(rrsig_type_covered(rrsig)));
- tmp_rrset = knot_rrset_new(rrsig->owner,
- rrsig_type_covered(rrsig),
- rrsig->rclass,
- rrsig->ttl);
- if (tmp_rrset == NULL) {
- dbg_zp("zp: find_rr_for_sig_in_node: Cannot create "
- "dummy RRSet.\n");
- return KNOT_ERROR;
- }
-
- ret = knot_zone_contents_add_rrset(zone, tmp_rrset, &node,
- KNOT_RRSET_DUPL_MERGE, 1);
- assert(ret <= 0);
- if (ret < 0) {
- dbg_zp("zp: Failed to add new dummy RRSet to the zone."
- "\n");
- return KNOT_ERROR;
- }
- }
-
- assert(tmp_rrset);
-
- if (tmp_rrset->ttl != rrsig->ttl) {
- char *name = knot_dname_to_str(tmp_rrset->owner);
- assert(name);
- log_zone_warning("RRSIG owned by: %s cannot be added to "
- "its RRSet, because their TTLs differ. "
- "Changing TTL to value=%d.\n",
- name, tmp_rrset->ttl);
- free(name);
- }
-
- ret = knot_zone_contents_add_rrsigs(zone, rrsig, &tmp_rrset, &node,
- KNOT_RRSET_DUPL_MERGE, 1);
- if (ret < 0) {
- dbg_zp("zp: find_rr_for_sig: Cannot add RRSIG.\n");
- return KNOTDZCOMPILE_EINVAL;
- } else if (ret > 0) {
- knot_rrset_free(&rrsig);
- }
-
- assert(tmp_rrset->rrsigs != NULL);
-
- return KNOTDZCOMPILE_EOK;
-}
-
-static knot_node_t *create_node(knot_zone_contents_t *zone,
- knot_rrset_t *current_rrset,
- int (*node_add_func)(knot_zone_contents_t *zone, knot_node_t *node,
- int create_parents, uint8_t, int),
- knot_node_t *(*node_get_func)(const knot_zone_contents_t *zone,
- const knot_dname_t *owner))
-{
- dbg_zp_verb("zp: create_node: Creating node using RRSet: %p.\n",
- current_rrset);
- knot_node_t *node =
- knot_node_new(current_rrset->owner, NULL, 0);
- if (node_add_func(zone, node, 1, 0, 1) != 0) {
- return NULL;
- }
-
- current_rrset->owner = node->owner;
-
- return node;
-}
-
-static void process_rrsigs_in_node(knot_zone_contents_t *zone,
- knot_node_t *node)
-{
- dbg_zp_verb("zp: process_rrsigs: Processing RRSIGS in node: %p.\n",
- node);
- rrset_list_t *tmp = parser->node_rrsigs;
- while (tmp != NULL) {
- if (find_rrset_for_rrsig_in_node(zone, node,
- tmp->data) != KNOT_EOK) {
- zc_error_prev_line("Could not add RRSIG to zone!\n");
- return;
- }
- tmp = tmp->next;
- }
-}
-
-int process_rr(void)
-{
- knot_zone_t *zone = parser->current_zone;
- assert(zone != NULL);
- knot_zone_contents_t *contents = knot_zone_get_contents(zone);
- assert(contents != NULL);
- knot_rrset_t *current_rrset = parser->current_rrset;
- knot_rrset_t *rrset;
- knot_rrtype_descriptor_t *descriptor =
- knot_rrtype_descriptor_by_type(current_rrset->type);
-
-dbg_zp_exec_detail(
- char *name = knot_dname_to_str(parser->current_rrset->owner);
- dbg_zp_detail("zp: process_rr: Processing RR owned by: %s .\n",
- name);
- free(name);
-);
- dbg_zp_verb("zp: process_rr: Processing type: %s.\n",
- knot_rrtype_to_string(parser->current_rrset->type));
- dbg_zp_verb("zp: process_rr: RDATA count: %d.\n",\
- parser->current_rrset->rdata->count);
-
- if (descriptor->fixed_items) {
- assert(current_rrset->rdata->count == descriptor->length);
- }
-
-
- assert(current_rrset->rdata->count > 0);
- assert(knot_dname_is_fqdn(current_rrset->owner));
-
- int (*node_add_func)(knot_zone_contents_t *, knot_node_t *, int,
- uint8_t, int);
- knot_node_t *(*node_get_func)(const knot_zone_contents_t *,
- const knot_dname_t *);
-
-
- /* If we have RRSIG of NSEC3 type first node will have
- * to be created in NSEC3 part of the zone */
-
- uint16_t type_covered = 0;
- if (current_rrset->type == KNOT_RRTYPE_RRSIG) {
- type_covered = rrsig_type_covered(current_rrset);
- }
-
- if (current_rrset->type != KNOT_RRTYPE_NSEC3 &&
- type_covered != KNOT_RRTYPE_NSEC3) {
- node_add_func = &knot_zone_contents_add_node;
- node_get_func = &knot_zone_contents_get_node;
- } else {
- node_add_func = &knot_zone_contents_add_nsec3_node;
- node_get_func = &knot_zone_contents_get_nsec3_node;
- }
-
- if ((current_rrset->type == KNOT_RRTYPE_SOA) && (zone != NULL)) {
- if (knot_node_rrset(knot_zone_contents_apex(contents),
- KNOT_RRTYPE_SOA) != NULL) {
- /* Receiving another SOA. */
- if (!knot_rrset_match(current_rrset,
- knot_node_rrset(knot_zone_contents_apex(contents),
- KNOT_RRTYPE_SOA), KNOT_RRSET_COMPARE_WHOLE)) {
- return KNOTDZCOMPILE_ESOA;
- } else {
- zc_warning_prev_line("encountered identical "
- "extra SOA record");
- return KNOTDZCOMPILE_EOK;
- }
- }
- }
-
- /*!< \todo Make sure the maximum RDLENGTH does not exceed 65535 bytes.*/
-
- if (current_rrset->type == KNOT_RRTYPE_SOA) {
- if (knot_dname_compare(current_rrset->owner,
- parser->origin_from_config) != 0) {
- zc_error_prev_line("SOA record has a different "
- "owner than the one specified "
- "in config! \n");
- /* Such SOA cannot even be added, because
- * it would not be in the zone apex. */
- return KNOTDZCOMPILE_EBADSOA;
- }
- }
-
- if (current_rrset->type == KNOT_RRTYPE_RRSIG) {
- /*!< \todo Use deep copy function here! */
- knot_rrset_t *tmp_rrsig =
- knot_rrset_new(current_rrset->owner,
- KNOT_RRTYPE_RRSIG,
- current_rrset->rclass,
- current_rrset->ttl);
- if (tmp_rrsig == NULL) {
- dbg_zp("zp: process_rr: Cannot create tmp RRSIG.\n");
- return KNOTDZCOMPILE_ENOMEM;
- }
-
- if (knot_rrset_add_rdata(tmp_rrsig,
- current_rrset->rdata) != KNOT_EOK) {
- knot_rrset_free(&tmp_rrsig);
- dbg_zp("zp: process_rr: Cannot add data to tmp"
- " RRSIG.\n");
- return KNOTDZCOMPILE_EBRDATA;
- }
-
- if (parser->last_node &&
- knot_dname_compare(parser->last_node->owner,
- current_rrset->owner) != 0) {
- /* RRSIG is first in the node, so we have to create it
- * before we return
- */
- if (parser->node_rrsigs != NULL) {
- process_rrsigs_in_node(contents,
- parser->last_node);
- rrset_list_delete(&parser->node_rrsigs);
- }
-
- /* The node might however been created previously. */
- parser->last_node =
- knot_zone_contents_get_node(contents,
- knot_rrset_owner(current_rrset));
-
- if (parser->last_node == NULL) {
- /* Try NSEC3 tree. */
- parser->last_node =
- knot_zone_contents_get_nsec3_node(
- contents,
- knot_rrset_owner(
- current_rrset));
- }
-
- if (parser->last_node == NULL) {
- /* Still NULL, node has to be created. */
- if ((parser->last_node = create_node(contents,
- current_rrset, node_add_func,
- node_get_func)) == NULL) {
- knot_rrset_free(&tmp_rrsig);
- dbg_zp("zp: process_rr: Cannot "
- "create new node.\n");
- return KNOTDZCOMPILE_EBADNODE;
- }
- }
- }
-
- if (rrset_list_add(&parser->node_rrsigs, tmp_rrsig) != 0) {
- dbg_zp("zp: process_rr: Cannot "
- "create new node.\n");
- return KNOTDZCOMPILE_ENOMEM;
- }
-
- dbg_zp_verb("zp: process_rr: RRSIG proccesed successfully.\n");
- return KNOTDZCOMPILE_EOK;
- }
-
- /*! \todo Move RRSIG and RRSet handling to funtions. */
- assert(current_rrset->type != KNOT_RRTYPE_RRSIG);
-
- knot_node_t *node = NULL;
- /* \note this could probably be much simpler */
- if (parser->last_node && current_rrset->type != KNOT_RRTYPE_SOA &&
- knot_dname_compare(parser->last_node->owner,
- current_rrset->owner) ==
- 0) {
- node = parser->last_node;
- } else {
- if (parser->last_node && parser->node_rrsigs) {
- process_rrsigs_in_node(contents,
- parser->last_node);
- }
-
- rrset_list_delete(&parser->node_rrsigs);
-
- /* new node */
- node = node_get_func(contents, current_rrset->owner);
- }
-
- if (node == NULL) {
- if (parser->last_node && parser->node_rrsigs) {
- process_rrsigs_in_node(contents,
- parser->last_node);
- }
-
- if ((node = create_node(contents, current_rrset,
- node_add_func,
- node_get_func)) == NULL) {
- dbg_zp("zp: process_rr: Cannot "
- "create new node.\n");
- return KNOTDZCOMPILE_EBADNODE;
- }
- }
-
- rrset = knot_node_get_rrset(node, current_rrset->type);
- if (!rrset) {
- rrset = knot_rrset_new(current_rrset->owner,
- current_rrset->type,
- current_rrset->rclass,
- current_rrset->ttl);
- if (rrset == NULL) {
- dbg_zp("zp: process_rr: Cannot "
- "create new RRSet.\n");
- return KNOTDZCOMPILE_ENOMEM;
- }
-
- if (knot_rrset_add_rdata(rrset, current_rrset->rdata) != 0) {
- knot_rrset_free(&rrset);
- dbg_zp("zp: process_rr: Cannot "
- "add RDATA to RRSet.\n");
- return KNOTDZCOMPILE_EBRDATA;
- }
-
- /* Selected merge option does not really matter here. */
- if (knot_zone_contents_add_rrset(contents, rrset, &node,
- KNOT_RRSET_DUPL_MERGE, 1) < 0) {
- knot_rrset_free(&rrset);
- dbg_zp("zp: process_rr: Cannot "
- "add RDATA to RRSet.\n");
- return KNOTDZCOMPILE_EBRDATA;
- }
- } else {
- if (current_rrset->type !=
- KNOT_RRTYPE_RRSIG && rrset->ttl !=
- current_rrset->ttl) {
- zc_warning_prev_line(
- "TTL does not match the TTL of the RRSet. "
- "Changing to %lu.\n", rrset->ttl);
- }
-
- if (knot_zone_contents_add_rrset(contents, current_rrset,
- &node,
- KNOT_RRSET_DUPL_MERGE, 1) < 0) {
- dbg_zp("zp: process_rr: Cannot "
- "merge RRSets.\n");
- return KNOTDZCOMPILE_EBRDATA;
- }
- }
-
- if (vflag > 1 && totalrrs > 0 && (totalrrs % progress == 0)) {
- zc_error_prev_line("Total errors: %ld\n", totalrrs);
- }
-
- parser->last_node = node;
- ++totalrrs;
-
- dbg_zp_verb("zp: process_rr: RRSet %p processed successfully.\n",
- parser->current_rrset);
- return KNOTDZCOMPILE_EOK;
-}
-
-static int zone_open(const char *filename, uint32_t ttl, uint16_t rclass,
- knot_node_t *origin, void *scanner, knot_dname_t *origin_from_config)
-{
- /*!< \todo #1676 Implement proper locking. */
- zparser_init(filename, ttl, rclass, origin, origin_from_config);
-
-
- /* Open the zone file... */
- if (strcmp(filename, "-") == 0) {
- zp_set_in(stdin, scanner);
- filename = "<stdin>";
- } else {
- FILE *f = fopen(filename, "r");
- if (f == NULL) {
- return 0;
- }
- zp_set_in(f, scanner);
- if (zp_get_in(scanner) == 0) {
- return 0;
- }
- }
-
- return 1;
-}
-
-int zone_read(const char *name, const char *zonefile, const char *outfile,
- int semantic_checks)
-{
- if (!outfile) {
- zc_error_prev_line("Missing output file for '%s'\n",
- zonefile);
- return KNOTDZCOMPILE_EINVAL;
- }
-
- dbg_zp("zp: zone_read: Reading zone: %s.\n", zonefile);
-
- /* Check that we can write to outfile. */
- FILE *f = fopen(outfile, "wb");
- if (f == NULL) {
- log_zone_error("Cannot write zone db to file '%s' (%s).\n",
- outfile, strerror(errno));
- return KNOTDZCOMPILE_EINVAL;
- }
- fclose(f);
-
- knot_dname_t *dname =
- knot_dname_new_from_str(name, strlen(name), NULL);
- if (dname == NULL) {
- return KNOTDZCOMPILE_ENOMEM;
- }
-
- if (!knot_dname_is_fqdn(dname)) {
- log_zone_error("Error: given zone origin is not FQDN.\n");
- knot_dname_release(dname);
- return KNOTDZCOMPILE_EINVAL;
- }
-
- knot_node_t *origin_node = knot_node_new(dname, NULL, 0);
- knot_dname_release(dname); /* Stored in node or should be freed. */
- if (origin_node == NULL) {
- return KNOTDZCOMPILE_ENOMEM;
- }
-
- assert(knot_node_parent(origin_node) == NULL);
-
- /*!< \todo Another copy is probably not needed. */
- knot_dname_t *origin_from_config =
- knot_dname_new_from_str(name, strlen(name), NULL);
- if (origin_from_config == NULL) {
- knot_node_free(&origin_node);
- return KNOTDZCOMPILE_ENOMEM;
- }
-
- void *scanner = NULL;
- zp_lex_init(&scanner);
- if (scanner == NULL) {
- knot_dname_release(origin_from_config);
- knot_node_free(&origin_node);
- return KNOTDZCOMPILE_ENOMEM;
- }
-
- if (!zone_open(zonefile, 3600, KNOT_CLASS_IN, origin_node, scanner,
- origin_from_config)) {
- zc_error_prev_line("Cannot open '%s' (%s).",
- zonefile, strerror(errno));
- zp_lex_destroy(scanner);
- knot_dname_release(origin_from_config);
-// knot_node_free(&origin_node, 0);
- return KNOTDZCOMPILE_EZONEINVAL;
- }
-
- /* Lock zone file. There should not be any modifications. */
- struct flock lock;
- lock.l_type = F_RDLCK;
- lock.l_start = 0;
- lock.l_whence = SEEK_SET;
- lock.l_len = 0;
- lock.l_pid = getpid();
- if (fcntl(fileno(zp_get_in(scanner)), F_SETLK, &lock) == -1) {
- log_zone_error("Cannot obtain zone source file lock (%d).\n",
- errno);
- FILE *in_file = (FILE *)zp_get_in(scanner);
- fclose(in_file);
- zp_lex_destroy(scanner);
- knot_dname_release(origin_from_config);
- return KNOTDZCOMPILE_EINVAL;
- }
-
- /* Change lock type to unlock rigth away. */
- lock.l_type = F_UNLCK;
-
- if (zp_parse(scanner) != 0) {
- log_zone_error("Parse failed.\n");
- FILE *in_file = (FILE *)zp_get_in(scanner);
- fclose(in_file);
- knot_dname_release(origin_from_config);
-// knot_node_free(&origin_node, 0);
- /* Release file lock. */
- if (fcntl(fileno(zp_get_in(scanner)), F_SETLK, &lock) == -1) {
- log_zone_error("Cannot release zone source file "
- "lock (%d).\n",
- errno);
- }
- zp_lex_destroy(scanner);
- return KNOTDZCOMPILE_ESYNT;
- }
-
- knot_zone_contents_t *contents =
- knot_zone_get_contents(parser->current_zone);
-
- /* Release file lock. */
- if (fcntl(fileno(zp_get_in(scanner)), F_SETLK, &lock) == -1) {
- log_zone_error("Cannot release zone source file lock (%d).\n",
- errno);
- }
-
- FILE *in_file = (FILE *)zp_get_in(scanner);
- fclose(in_file);
- zp_lex_destroy(scanner);
-
- dbg_zp("zp: zone_read: Parse complete for %s.\n",
- zonefile);
-
- if (parser->last_node && parser->node_rrsigs != NULL) {
- /* assign rrsigs to last node in the zone*/
- process_rrsigs_in_node(contents,
- parser->last_node);
- rrset_list_delete(&parser->node_rrsigs);
- }
-
- dbg_zp("zp: zone_read: RRSIGs processed.\n");
-
- if (!(parser->current_zone &&
- knot_node_rrset(parser->current_zone->contents->apex,
- KNOT_RRTYPE_SOA))) {
- zc_error_prev_line("Zone file does not contain SOA record!\n");
-// knot_zone_deep_free(&parser->current_zone, 1);
- knot_dname_release(origin_from_config);
-// knot_node_free(&origin_node, 0);
- return KNOTDZCOMPILE_EZONEINVAL;
- }
-
- int ret = knot_zone_contents_adjust(contents);
- if (ret != KNOT_EOK) {
- fprintf(stderr, "Zone could not be adjusted, error: %s.\n",
- knot_strerror(ret));
- parser->errors++;
- }
-
- dbg_zp("zp: zone_read: Zone adjusted.\n");
-
- if (parser->errors != 0) {
- log_zone_error("Parser finished with %d error(s), "
- "not dumping the zone!\n",
- parser->errors);
- } else {
- int fd = open(outfile, O_RDWR | O_CREAT | O_TRUNC, S_IRWXU | S_IRWXG);
- if (fd < 0) {
- log_zone_error("Could not open destination file for db: %s.\n",
- outfile);
- totalerrors++;
- } else {
- crc_t crc;
- int ret = knot_zdump_binary(contents, fd,
- semantic_checks,
- zonefile, &crc);
- if (ret != KNOT_EOK) {
- log_zone_error("Could not dump zone, reason: "
- "%s.\n", knot_strerror(ret));
- if (remove(outfile) != 0) {
- log_zone_error("Could not remove "
- "db file!\n");
- }
- totalerrors++;
- } else {
- /* Write CRC file. */
- char *crc_path = knot_zdump_crc_file(outfile);
- if (crc_path == NULL) {
- log_zone_error(
- "Could not get crc file path.\n");
- remove(outfile);
- totalerrors++;
- } else {
- FILE *f_crc = fopen(crc_path, "w");
- if (f_crc == NULL) {
- log_zone_error(
- "Could not open crc file \n");
- remove(outfile);
- totalerrors++;
- } else {
- fprintf(f_crc,
- "%lu",
- (unsigned long)crc);
- fclose(f_crc);
- }
- }
- free(crc_path);
- }
- }
-
-
- dbg_zp("zp: zone_read: Zone %s dumped successfully.\n",
- zonefile);
- }
-
- fflush(stdout);
- totalerrors += parser->errors;
- knot_dname_release(origin_from_config);
-
- return totalerrors;
-}
-
-/*! @} */