diff --git a/Knot.files b/Knot.files index 2a81474a3d324065013e8574cd2b3ef7cf85e9b3..ead382f77cc630cd51b4a373840cad7c42f3e9f1 100644 --- a/Knot.files +++ b/Knot.files @@ -291,8 +291,6 @@ src/zscanner/error.c src/zscanner/error.h src/zscanner/functions.c src/zscanner/functions.h -src/zscanner/loader.c -src/zscanner/loader.h src/zscanner/scanner.h src/zscanner/scanner.rl src/zscanner/scanner_body.rl @@ -301,7 +299,6 @@ src/zscanner/tests/processing.h src/zscanner/tests/tests.c src/zscanner/tests/tests.h src/zscanner/tests/zscanner-tool.c -src/zscanner/zscanner.h tests/Makefile.am tests/acl.c tests/base32hex.c diff --git a/src/knot/ctl/knotc_main.c b/src/knot/ctl/knotc_main.c index bd4aa5e3692eb93a7353659f4b195d8109608a17..cdb45aac7fedc5feda93ac444a36b0dc2d9a649a 100644 --- a/src/knot/ctl/knotc_main.c +++ b/src/knot/ctl/knotc_main.c @@ -715,7 +715,6 @@ static int cmd_memstats(int argc, char *argv[], unsigned flags) UNUSED(flags); /* Zone checking */ - int rc = 0; double total_size = 0; /* Generate databases for all zones */ @@ -760,7 +759,7 @@ static int cmd_memstats(int argc, char *argv[], unsigned flags) .record_count = 0 }; if (est.node_table == NULL) { log_error("not enough memory"); - continue; + break; } /* Create zone scanner. */ @@ -770,7 +769,6 @@ static int cmd_memstats(int argc, char *argv[], unsigned flags) process_error, &est); if (zs == NULL) { - rc = 1; log_zone_str_error(zone->name, "could not load zone"); hattrie_free(est.node_table); continue; @@ -779,7 +777,6 @@ static int cmd_memstats(int argc, char *argv[], unsigned flags) /* Do a parser run, but do not actually create the zone. */ int ret = zs_scanner_parse_file(zs, zone->file); if (ret != 0) { - rc = 1; log_zone_str_error(zone->name, "failed to parse zone"); hattrie_apply_rev(est.node_table, estimator_free_trie_node, NULL); hattrie_free(est.node_table); @@ -809,10 +806,10 @@ static int cmd_memstats(int argc, char *argv[], unsigned flags) } hattrie_iter_free(z_iter); - if (rc == 0 && argc == 0) { // for all zones + if (argc == 0) { // for all zones log_info("estimated memory consumption for all zones is %zu MB", (size_t)total_size); } - return rc; + return 0; } diff --git a/src/knot/nameserver/internet.c b/src/knot/nameserver/internet.c index 11cb312ca1de128d77859bff3357bd6825c2460f..0dd6214ce5d528471ab26fe8c7b1bebcbd70ee98 100644 --- a/src/knot/nameserver/internet.c +++ b/src/knot/nameserver/internet.c @@ -19,7 +19,6 @@ #include "libknot/common.h" #include "libknot/rrtype/rdname.h" #include "libknot/rrtype/soa.h" -#include "libknot/rrtype/opt.h" #include "libknot/dnssec/rrset-sign.h" #include "knot/nameserver/internet.h" #include "knot/nameserver/nsec_proofs.h" @@ -167,50 +166,6 @@ static int put_rrsig(const knot_dname_t *sig_owner, uint16_t type, return KNOT_EOK; } -/*! \brief Put OPT RR to packet. */ -static int put_opt_rr(knot_pkt_t *pkt, struct query_data *qdata) -{ - /* Copy OPT RR from server. */ - dbg_ns("%s: adding OPT RR to the response\n", __func__); - const knot_pkt_t *query = qdata->query; - knot_rrset_t opt_rr; - int ret = knot_edns_init(&opt_rr, conf()->max_udp_payload, - qdata->rcode_ext, KNOT_EDNS_VERSION, &pkt->mm); - if (ret != KNOT_EOK) { - return ret; - } - - /* Append NSID if requested and available. */ - if (knot_edns_has_nsid(query->opt_rr) && conf()->nsid_len > 0) { - ret = knot_edns_add_option(&opt_rr, - KNOT_EDNS_OPTION_NSID, conf()->nsid_len, - (const uint8_t*)conf()->nsid, &pkt->mm); - if (ret != KNOT_EOK) { - knot_rrset_clear(&opt_rr, &pkt->mm); - return ret; - } - } - - /* Set DO bit if set (DNSSEC requested). */ - if (knot_pkt_has_dnssec(query)) { - dbg_ns("%s: setting DO=1 in OPT RR\n", __func__); - knot_edns_set_do(&opt_rr); - } - - /* Reclaim reserved size. */ - ret = knot_pkt_reclaim(pkt, knot_edns_wire_size(&opt_rr)); - if (ret == KNOT_EOK) { - /* Write to packet. */ - ret = knot_pkt_put(pkt, COMPR_HINT_NONE, &opt_rr, KNOT_PF_FREE); - } - - if (ret != KNOT_EOK) { - knot_rrset_clear(&opt_rr, &pkt->mm); - } - - return ret; -} - /*! \brief This is a wildcard-covered or any other terminal node for QNAME. * e.g. positive answer. */ @@ -700,14 +655,7 @@ static int solve_authority_dnssec(int state, knot_pkt_t *pkt, struct query_data static int solve_additional(int state, knot_pkt_t *pkt, struct query_data *qdata, void *ctx) { - /* Put OPT RR to the additional section. */ int ret = KNOT_EOK; - if (knot_pkt_has_edns(qdata->query)) { - ret = put_opt_rr(pkt, qdata); - if (ret != KNOT_EOK) { - return ERROR; - } - } /* Scan all RRs in ANSWER/AUTHORITY. */ for (uint16_t i = 0; i < pkt->rrset_count; ++i) { diff --git a/src/knot/nameserver/process_query.c b/src/knot/nameserver/process_query.c index 07cf1da8ce35fc95d6aa935ee83641b5107812c4..96127bec862bae5e9ea4a635b2152b034c10fc7d 100644 --- a/src/knot/nameserver/process_query.c +++ b/src/knot/nameserver/process_query.c @@ -60,6 +60,7 @@ static int process_query_reset(knot_process_t *ctx) knot_pkt_free(&qdata->query); ptrlist_free(&qdata->wildcards, qdata->mm); nsec_clear_rrsigs(qdata); + knot_rrset_clear(&qdata->opt_rr, qdata->mm); if (qdata->ext_cleanup != NULL) { qdata->ext_cleanup(qdata); } @@ -260,6 +261,70 @@ static const zone_t *answer_zone_find(const knot_pkt_t *query, knot_zonedb_t *zo return zone; } +static int answer_edns_reserve(knot_pkt_t *resp, struct query_data *qdata) +{ + if (knot_rrset_empty(&qdata->opt_rr)) { + return KNOT_EOK; + } + + /* Reserve size in the response. */ + return knot_pkt_reserve(resp, knot_edns_wire_size(&qdata->opt_rr)); +} + +static int answer_edns_init(const knot_pkt_t *query, knot_pkt_t *resp, + struct query_data *qdata) +{ + if (!knot_pkt_has_edns(query)) { + return KNOT_EOK; + } + + /* Initialize OPT record. */ + int ret = knot_edns_init(&qdata->opt_rr, conf()->max_udp_payload, 0, + KNOT_EDNS_VERSION, qdata->mm); + if (ret != KNOT_EOK) { + return ret; + } + + /* Check supported version. */ + if (knot_edns_get_version(query->opt_rr) != KNOT_EDNS_VERSION) { + qdata->rcode_ext = KNOT_EDNS_RCODE_BADVERS; + } + + /* Set DO bit if set (DNSSEC requested). */ + if (knot_pkt_has_dnssec(query)) { + knot_edns_set_do(&qdata->opt_rr); + } + + /* Append NSID if requested and available. */ + if (knot_edns_has_nsid(query->opt_rr) && conf()->nsid_len > 0) { + ret = knot_edns_add_option(&qdata->opt_rr, + KNOT_EDNS_OPTION_NSID, conf()->nsid_len, + (const uint8_t*)conf()->nsid, qdata->mm); + if (ret != KNOT_EOK) { + return ret; + } + } + + return answer_edns_reserve(resp, qdata); +} + +static int answer_edns_put(knot_pkt_t *resp, struct query_data *qdata) +{ + if (knot_rrset_empty(&qdata->opt_rr)) { + return KNOT_EOK; + } + + /* Reclaim reserved size. */ + int ret = knot_pkt_reclaim(resp, knot_edns_wire_size(&qdata->opt_rr)); + if (ret != KNOT_EOK) { + return ret; + } + + /* Write to packet. */ + assert(resp->current == KNOT_ADDITIONAL); + return knot_pkt_put(resp, COMPR_HINT_NONE, &qdata->opt_rr, 0); +} + /*! \brief Initialize response, sizes and find zone from which we're going to answer. */ static int prepare_answer(const knot_pkt_t *query, knot_pkt_t *resp, knot_process_t *ctx) { @@ -294,49 +359,26 @@ static int prepare_answer(const knot_pkt_t *query, knot_pkt_t *resp, knot_proces /* Find zone for QNAME. */ qdata->zone = answer_zone_find(query, server->zone_db); - /* Update maximal answer size. */ - if (qdata->param->proc_flags & NS_QUERY_LIMIT_SIZE) { - resp->max_size = KNOT_WIRE_MIN_PKTSIZE; - } - - /* Check if EDNS is supported. */ - if (!knot_pkt_has_edns(query)) { - return KNOT_EOK; - } - - /* Check EDNS version and return BADVERS if not supported. */ - if (knot_edns_get_version(query->opt_rr) != KNOT_EDNS_VERSION) { - dbg_ns("%s: unsupported EDNS version required.\n", __func__); - qdata->rcode_ext = KNOT_EDNS_RCODE_BADVERS; - } - - /* Reserve space for OPT RR in the packet. Using size of the server's - * OPT RR, because that's the maximum size (RDATA may or may not be - * used). - */ - uint16_t reserve_size = KNOT_EDNS_MIN_SIZE; - if (knot_edns_has_nsid(query->opt_rr) && conf()->nsid_len > 0) { - reserve_size += KNOT_EDNS_OPTION_HDRLEN + conf()->nsid_len; - } - ret = knot_pkt_reserve(resp, reserve_size); + /* Setup EDNS. */ + ret = answer_edns_init(query, resp, qdata); if (ret != KNOT_EOK) { - dbg_ns("%s: can't reserve OPT RR in response (%d)\n", __func__, ret); return ret; } - /* Get minimal supported size from EDNS(0). */ - uint16_t client_maxlen = knot_edns_get_payload(query->opt_rr); - uint16_t server_maxlen = conf()->max_udp_payload; - uint16_t min_edns = MIN(client_maxlen, server_maxlen); - - /* Update packet size limit. */ - if (qdata->param->proc_flags & NS_QUERY_LIMIT_SIZE) { - resp->max_size = MAX(resp->max_size, min_edns); - dbg_ns("%s: packet size limit <= %zuB\n", __func__, resp->max_size); + /* Update maximal answer size. */ + bool has_limit = qdata->param->proc_flags & NS_QUERY_LIMIT_SIZE; + if (has_limit) { + resp->max_size = KNOT_WIRE_MIN_PKTSIZE; + if (knot_pkt_has_edns(query)) { + uint16_t client = knot_edns_get_payload(query->opt_rr); + uint16_t server = conf()->max_udp_payload; + uint16_t transfer = MIN(client, server); + resp->max_size = MAX(resp->max_size, transfer); + } + } else { + resp->max_size = KNOT_WIRE_MAX_PKTSIZE; } - /* In the response, always advertise server's maximum UDP payload. */ - return ret; } @@ -361,11 +403,21 @@ static int process_query_err(knot_pkt_t *pkt, knot_process_t *ctx) /* Set RCODE. */ knot_wire_set_rcode(pkt->wire, qdata->rcode); - /* Transaction security (if applicable). */ - if (process_query_sign_response(pkt, qdata) != KNOT_EOK) { - return NS_PROC_FAIL; + + /* Add OPT and TSIG (best effort, send reply anyway if fails). */ + if (pkt->current != KNOT_ADDITIONAL) { + knot_pkt_begin(pkt, KNOT_ADDITIONAL); + } + + /* Put OPT RR to the additional section. */ + int ret = answer_edns_reserve(pkt, qdata); + if (ret == KNOT_EOK) { + (void) answer_edns_put(pkt, qdata); } + /* Transaction security (if applicable). */ + (void) process_query_sign_response(pkt, qdata); + return NS_PROC_DONE; } @@ -464,8 +516,19 @@ static int process_query_out(knot_pkt_t *pkt, knot_process_t *ctx) * Postprocessing. */ - /* Transaction security (if applicable). */ if (next_state == NS_PROC_DONE || next_state == NS_PROC_FULL) { + if (pkt->current != KNOT_ADDITIONAL) { + knot_pkt_begin(pkt, KNOT_ADDITIONAL); + } + + /* Put OPT RR to the additional section. */ + ret = answer_edns_put(pkt, qdata); + if (ret != KNOT_EOK) { + next_state = NS_PROC_FAIL; + goto finish; + } + + /* Transaction security (if applicable). */ if (process_query_sign_response(pkt, qdata) != KNOT_EOK) { next_state = NS_PROC_FAIL; } diff --git a/src/knot/nameserver/process_query.h b/src/knot/nameserver/process_query.h index a5bf96ca9b48708f3605a12007d0d807b36939bc..27ca16847d9cb754465af16c3500ae346a15fc6e 100644 --- a/src/knot/nameserver/process_query.h +++ b/src/knot/nameserver/process_query.h @@ -84,6 +84,9 @@ struct query_data { /* Original QNAME case. */ uint8_t orig_qname[KNOT_DNAME_MAXLEN]; + /* EDNS */ + knot_rrset_t opt_rr; + /* Extensions. */ void *ext; void (*ext_cleanup)(struct query_data*); /*!< Extensions cleanup callback. */ diff --git a/src/knot/zone/events.c b/src/knot/zone/events.c index 2ee5c77c545b66e17f8c00ef5aee06ad229d9598..eb1f8d94471e57148dca26cff246c7cc177e9713 100644 --- a/src/knot/zone/events.c +++ b/src/knot/zone/events.c @@ -212,7 +212,7 @@ static void schedule_dnssec(zone_t *zone, time_t refresh_at) struct tm time_gm = { 0 }; localtime_r(&refresh_at, &time_gm); strftime(time_str, sizeof(time_str), KNOT_LOG_TIME_FORMAT, &time_gm); - log_zone_info(zone->name, "DNSSEC, next event on %s", time_str); + log_zone_info(zone->name, "DNSSEC: next signing on %s", time_str); // schedule @@ -494,14 +494,14 @@ static int event_dnssec(zone_t *zone) uint32_t refresh_at = time(NULL); if (zone->flags & ZONE_FORCE_RESIGN) { - log_zone_info(zone->name, "DNSSEC, dropping previous " + log_zone_info(zone->name, "DNSSEC: dropping previous " "signatures, resigning zone"); zone->flags &= ~ZONE_FORCE_RESIGN; ret = knot_dnssec_zone_sign_force(zone->contents, zone->conf, &ch, &refresh_at); } else { - log_zone_info(zone->name, "DNSSEC, signing zone"); + log_zone_info(zone->name, "DNSSEC: signing zone"); ret = knot_dnssec_zone_sign(zone->contents, zone->conf, &ch, KNOT_SOA_SERIAL_UPDATE, &refresh_at); @@ -515,7 +515,7 @@ static int event_dnssec(zone_t *zone) zone_contents_t *new_contents = NULL; int ret = apply_changeset(zone, &ch, &new_contents); if (ret != KNOT_EOK) { - log_zone_error(zone->name, "DNSSEC, could not sign zone (%s)", + log_zone_error(zone->name, "DNSSEC: could not sign zone (%s)", knot_strerror(ret)); goto done; } @@ -523,7 +523,7 @@ static int event_dnssec(zone_t *zone) /* Write change to journal. */ ret = zone_change_store(zone, &ch); if (ret != KNOT_EOK) { - log_zone_error(zone->name, "DNSSEC, could not sign zone (%s)", + log_zone_error(zone->name, "DNSSEC: could not sign zone (%s)", knot_strerror(ret)); update_rollback(&ch); update_free_zone(&new_contents); diff --git a/src/libknot/packet/pkt.c b/src/libknot/packet/pkt.c index 13a702d170c05e5298c2d929d24e190585661168..00f3e099855fa948afbc5924a1d3fb05b75f6d6a 100644 --- a/src/libknot/packet/pkt.c +++ b/src/libknot/packet/pkt.c @@ -655,6 +655,49 @@ static int knot_pkt_rr_from_wire(const uint8_t *wire, size_t *pos, return KNOT_EOK; } +/* \note Private for check_rr_constraints(). */ +#define CHECK_AR_CONSTRAINTS(pkt, rr, var, check_func) \ + if ((pkt)->current != KNOT_ADDITIONAL) { \ + dbg_packet("%s: RRTYPE%u not in AR\n", __func__, rr->type); \ + return KNOT_EMALF; \ + } else if ((pkt)->var != NULL) { \ + dbg_packet("%s: found 2nd RRTYPE%u\n", __func__, rr->type); \ + return KNOT_EMALF; \ + } else if (!check_func(rr)) { \ + dbg_packet("%s: bad RRTYPE%u RDATA\n", __func__, rr->type); \ + return KNOT_EMALF; \ + } else { \ + (pkt)->var = rr; \ + } + +/*! \brief Check constraints (position, uniqueness, validity) for special types (TSIG, OPT). */ +static int check_rr_constraints(knot_pkt_t *pkt, knot_rrset_t *rr, size_t rr_size, unsigned flags) +{ + /* Check RR constraints. */ + switch(rr->type) { + case KNOT_RRTYPE_TSIG: + CHECK_AR_CONSTRAINTS(pkt, rr, tsig_rr, tsig_rdata_is_ok); + + /* Strip TSIG RR from wireformat and decrease ARCOUNT. */ + if (!(flags & KNOT_PF_KEEPWIRE)) { + pkt->parsed -= rr_size; + pkt->size -= rr_size; + knot_wire_set_id(pkt->wire, tsig_rdata_orig_id(rr)); + knot_wire_set_arcount(pkt->wire, knot_wire_get_arcount(pkt->wire) - 1); + } + break; + case KNOT_RRTYPE_OPT: + CHECK_AR_CONSTRAINTS(pkt, rr, opt_rr, knot_edns_check_record); + break; + default: + break; + } + + return KNOT_EOK; +} + +#undef CHECK_AR_RECORD + int knot_pkt_parse_rr(knot_pkt_t *pkt, unsigned flags) { dbg_packet("%s(%p, %u)\n", __func__, pkt, flags); @@ -688,53 +731,10 @@ int knot_pkt_parse_rr(knot_pkt_t *pkt, unsigned flags) /* Update packet RRSet count. */ ++pkt->rrset_count; - - /* Update section RRSet count. */ ++pkt->sections[pkt->current].count; - /* Check RR constraints. */ - switch(rr->type) { - case KNOT_RRTYPE_TSIG: - // if there is some TSIG already, treat as malformed - if (pkt->tsig_rr != NULL) { - dbg_packet("%s: found 2nd TSIG\n", __func__); - return KNOT_EMALF; - } else if (!tsig_rdata_is_ok(rr)) { - dbg_packet("%s: bad TSIG RDATA\n", __func__); - return KNOT_EMALF; - } - - /* Strip TSIG RR from wireformat and decrease ARCOUNT. */ - if (!(flags & KNOT_PF_KEEPWIRE)) { - pkt->parsed -= rr_size; - pkt->size -= rr_size; - knot_wire_set_id(pkt->wire, tsig_rdata_orig_id(rr)); - knot_wire_set_arcount(pkt->wire, knot_wire_get_arcount(pkt->wire) - 1); - } - - /* Remember TSIG RR. */ - pkt->tsig_rr = rr; - break; - case KNOT_RRTYPE_OPT: - /* If there is some OPT already, treat as malformed. */ - if (pkt->opt_rr != NULL) { - dbg_packet("%s: found 2nd OPT\n", __func__); - return KNOT_EMALF; - } - - /* Semantic checks for the OPT. */ - if (!knot_edns_check_record(rr)) { - dbg_packet("%s: OPT RR check failed\n", __func__); - return KNOT_EMALF; - } - - pkt->opt_rr = rr; - break; - default: - break; - } - - return ret; + /* Check special RRs (OPT and TSIG). */ + return check_rr_constraints(pkt, rr, rr_size, flags); } int knot_pkt_parse_section(knot_pkt_t *pkt, unsigned flags) diff --git a/src/utils/nsupdate/nsupdate_exec.c b/src/utils/nsupdate/nsupdate_exec.c index faffee39f8f2de166b5b4076f718c365fce5a867..0948812899a39963c302ace01fc35f3742462ea0 100644 --- a/src/utils/nsupdate/nsupdate_exec.c +++ b/src/utils/nsupdate/nsupdate_exec.c @@ -141,11 +141,7 @@ static int dname_isvalid(const char *lp, size_t len) { /* This is probably redundant, but should be a bit faster so let's keep it. */ static int parse_full_rr(zs_scanner_t *s, const char* lp) { - if (zs_scanner_parse(s, lp, lp + strlen(lp), 0) < 0) { - return KNOT_EPARSEFAIL; - } - char nl = '\n'; /* Ensure newline after complete RR */ - if (zs_scanner_parse(s, &nl, &nl+sizeof(char), 1) < 0) { /* Terminate */ + if (zs_scanner_parse(s, lp, lp + strlen(lp), true) < 0) { return KNOT_EPARSEFAIL; } @@ -264,7 +260,7 @@ static int parse_partial_rr(zs_scanner_t *s, const char *lp, unsigned flags) { /* Need to parse rdata, synthetize input. */ char *rr = sprintf_alloc("%s %u %s %s %s\n", owner_s, s->r_ttl, b1, b2, lp); - if (rr == NULL || zs_scanner_parse(s, rr, rr + strlen(rr), 1) < 0) { + if (rr == NULL || zs_scanner_parse(s, rr, rr + strlen(rr), true) < 0) { ret = KNOT_EPARSEFAIL; } diff --git a/src/utils/nsupdate/nsupdate_params.c b/src/utils/nsupdate/nsupdate_params.c index 43212b00bd2d7a6be60e003ce01c9ba6ff493433..1a0d4d2fbf5f5e9c31098d6a97dfbbc61dd4ff57 100644 --- a/src/utils/nsupdate/nsupdate_params.c +++ b/src/utils/nsupdate/nsupdate_params.c @@ -72,8 +72,8 @@ static int parser_set_default(zs_scanner_t *s, const char *fmt, ...) return KNOT_ESPACE; } - /* fmt must contain newline */ - if (zs_scanner_parse(s, buf, buf + n, 1) < 0) { + /* Buffer must contain newline */ + if (zs_scanner_parse(s, buf, buf + n, true) < 0) { return KNOT_EPARSEFAIL; } diff --git a/src/zscanner/scanner.c.g2 b/src/zscanner/scanner.c.g2 index 48340b17b65f67a5b0eb72ba232fe47996e9b5f9..96f2b85401fd8155acb96215b02af1954e09033a 100644 --- a/src/zscanner/scanner.c.g2 +++ b/src/zscanner/scanner.c.g2 @@ -160,15 +160,11 @@ void zs_scanner_free(zs_scanner_t *s) } } -int zs_scanner_parse(zs_scanner_t *s, - const char *start, - const char *end, - const bool final_block) +static void parse_block(zs_scanner_t *s, + const char *start, + const char *end, + const bool is_eof) { - if (s == NULL || start == NULL || end == NULL) { - return -1; - } - // Necessary scanner variables. const char *p = start; const char *pe = end; @@ -194,7 +190,7 @@ int zs_scanner_parse(zs_scanner_t *s, memcpy(stack, s->stack, sizeof(stack)); // End of file check. - if (final_block == true) { + if (is_eof) { eof = (char *)pe; } @@ -1374,7 +1370,7 @@ tr81: // Stop scanner if required. if (s->stop == true) { - return -1; + return; } } { @@ -11555,7 +11551,7 @@ tr93: // Stop scanner if required. if (s->stop == true) { - return -1; + return; } } goto st1057; @@ -11578,7 +11574,7 @@ tr657: // Stop scanner if required. if (s->stop == true) { - return -1; + return; } } goto st1057; @@ -17722,7 +17718,7 @@ tr129: // Stop scanner if required. if (s->stop == true) { - return -1; + return; } } goto st1058; @@ -17749,7 +17745,7 @@ tr123: // Stop scanner if required. if (s->stop == true) { - return -1; + return; } } goto st1058; @@ -18441,7 +18437,7 @@ tr706: // Stop scanner if required. if (s->stop == true) { - return -1; + return; } } goto st1059; @@ -18471,7 +18467,7 @@ tr701: // Stop scanner if required. if (s->stop == true) { - return -1; + return; } } goto st1059; @@ -18904,7 +18900,7 @@ tr670: // Stop scanner if required. if (s->stop == true) { - return -1; + return; } } goto st1061; @@ -18926,7 +18922,7 @@ tr695: // Stop scanner if required. if (s->stop == true) { - return -1; + return; } } goto st1061; @@ -18978,7 +18974,7 @@ tr3204: // Stop scanner if required. if (s->stop == true) { - return -1; + return; } } { @@ -19006,7 +19002,7 @@ tr3227: // Stop scanner if required. if (s->stop == true) { - return -1; + return; } } { @@ -20115,7 +20111,7 @@ tr90: // Stop scanner if required. if (s->stop == true) { - return -1; + return; } } { @@ -20289,7 +20285,7 @@ tr659: // Stop scanner if required. if (s->stop == true) { - return -1; + return; } } { @@ -20856,7 +20852,7 @@ tr661: // Stop scanner if required. if (s->stop == true) { - return -1; + return; } } goto st1063; @@ -20948,7 +20944,7 @@ tr666: // Stop scanner if required. if (s->stop == true) { - return -1; + return; } } goto st1063; @@ -22843,7 +22839,7 @@ tr680: // Stop scanner if required. if (s->stop == true) { - return -1; + return; } } goto st1064; @@ -22869,7 +22865,7 @@ tr712: // Stop scanner if required. if (s->stop == true) { - return -1; + return; } } goto st1064; @@ -24031,7 +24027,7 @@ tr719: // Stop scanner if required. if (s->stop == true) { - return -1; + return; } } goto st1065; @@ -24130,7 +24126,7 @@ tr714: // Stop scanner if required. if (s->stop == true) { - return -1; + return; } } goto st1065; @@ -28759,7 +28755,7 @@ tr776: // In case of serious error, stop scanner. if (s->stop == true) { - return -1; + return; } } { @@ -28787,7 +28783,7 @@ tr778: // In case of serious error, stop scanner. if (s->stop == true) { - return -1; + return; } } { @@ -31115,11 +31111,18 @@ tr902: if (ss != NULL) { // Parse included zone file. ret = zs_scanner_parse_file(ss, (char*)(s->buffer)); - zs_scanner_free(ss); if (ret != 0) { - ERR(ZS_UNPROCESSED_INCLUDE); + // File internal errors are handled by error callback. + if (ss->error_counter > 0) { + ERR(ZS_UNPROCESSED_INCLUDE); + // General include file error. + } else { + ERR(ss->error_code); + } + zs_scanner_free(ss); p--; {goto st246;} } + zs_scanner_free(ss); } else { ERR(ZS_UNPROCESSED_INCLUDE); p--; {goto st246;} @@ -31166,11 +31169,18 @@ tr912: if (ss != NULL) { // Parse included zone file. ret = zs_scanner_parse_file(ss, (char*)(s->buffer)); - zs_scanner_free(ss); if (ret != 0) { - ERR(ZS_UNPROCESSED_INCLUDE); + // File internal errors are handled by error callback. + if (ss->error_counter > 0) { + ERR(ZS_UNPROCESSED_INCLUDE); + // General include file error. + } else { + ERR(ss->error_code); + } + zs_scanner_free(ss); p--; {goto st246;} } + zs_scanner_free(ss); } else { ERR(ZS_UNPROCESSED_INCLUDE); p--; {goto st246;} @@ -31223,11 +31233,18 @@ tr924: if (ss != NULL) { // Parse included zone file. ret = zs_scanner_parse_file(ss, (char*)(s->buffer)); - zs_scanner_free(ss); if (ret != 0) { - ERR(ZS_UNPROCESSED_INCLUDE); + // File internal errors are handled by error callback. + if (ss->error_counter > 0) { + ERR(ZS_UNPROCESSED_INCLUDE); + // General include file error. + } else { + ERR(ss->error_code); + } + zs_scanner_free(ss); p--; {goto st246;} } + zs_scanner_free(ss); } else { ERR(ZS_UNPROCESSED_INCLUDE); p--; {goto st246;} @@ -31490,11 +31507,18 @@ tr936: if (ss != NULL) { // Parse included zone file. ret = zs_scanner_parse_file(ss, (char*)(s->buffer)); - zs_scanner_free(ss); if (ret != 0) { - ERR(ZS_UNPROCESSED_INCLUDE); + // File internal errors are handled by error callback. + if (ss->error_counter > 0) { + ERR(ZS_UNPROCESSED_INCLUDE); + // General include file error. + } else { + ERR(ss->error_code); + } + zs_scanner_free(ss); p--; {goto st246;} } + zs_scanner_free(ss); } else { ERR(ZS_UNPROCESSED_INCLUDE); p--; {goto st246;} @@ -73028,11 +73052,11 @@ case 1140: // Processing error. s->process_error(s); - return -1; + return; } // Check unclosed multiline record. - if (final_block && s->multiline) { + if (is_eof && s->multiline) { ERR(ZS_UNCLOSED_MULTILINE); s->error_counter++; s->process_error(s); @@ -73045,6 +73069,24 @@ case 1140: // Storing r_data pointer. s->r_data_tail = rdata_tail - s->r_data; +} + +int zs_scanner_parse(zs_scanner_t *s, + const char *start, + const char *end, + const bool final_block) +{ + if (s == NULL || start == NULL || end == NULL) { + return -1; + } + + // Parse input block. + parse_block(s, start, end, false); + + // Parse trailing artificial block (newline char) if not stop. + if (final_block && !s->stop) { + parse_block(s, NEWLINE_BLOCK, NEWLINE_BLOCK + 1, true); + } // Check if any errors has occured. if (s->error_counter > 0) { @@ -73144,13 +73186,7 @@ int zs_scanner_parse_file(zs_scanner_t *s, } // Scan zone file block. - zs_scanner_parse(s, data, data + block_size, false); - - // Process the last artificial block (newline char) if not fatal. - if (final_block == true && s->stop == 0) { - zs_scanner_parse(s, NEWLINE_BLOCK, NEWLINE_BLOCK + 1, - true); - } + zs_scanner_parse(s, data, data + block_size, final_block); // Zone file block unmapping. if (munmap(data, block_size) == -1) { @@ -73159,16 +73195,20 @@ int zs_scanner_parse_file(zs_scanner_t *s, free(s->file.name); return -1; } + + // Stop parsing if required. + if (s->stop) { + break; + } } + close(s->file.descriptor); + free(s->file.name); + // Check for scanner return. if (s->error_counter > 0) { - close(s->file.descriptor); - free(s->file.name); return -1; } - close(s->file.descriptor); - free(s->file.name); return 0; } diff --git a/src/zscanner/scanner.c.t0 b/src/zscanner/scanner.c.t0 index e94d48e33b97feee79d65ef1563206f3dfcc64a2..44af7e21f9d14f5fd26577bd861a7b44430482ab 100644 --- a/src/zscanner/scanner.c.t0 +++ b/src/zscanner/scanner.c.t0 @@ -4951,15 +4951,11 @@ void zs_scanner_free(zs_scanner_t *s) } } -int zs_scanner_parse(zs_scanner_t *s, - const char *start, - const char *end, - const bool final_block) +static void parse_block(zs_scanner_t *s, + const char *start, + const char *end, + const bool is_eof) { - if (s == NULL || start == NULL || end == NULL) { - return -1; - } - // Necessary scanner variables. const char *p = start; const char *pe = end; @@ -4985,7 +4981,7 @@ int zs_scanner_parse(zs_scanner_t *s, memcpy(stack, s->stack, sizeof(stack)); // End of file check. - if (final_block == true) { + if (is_eof) { eof = (char *)pe; } @@ -5253,7 +5249,7 @@ _match: // In case of serious error, stop scanner. if (s->stop == true) { - return -1; + return; } } break; @@ -5824,11 +5820,18 @@ _match: if (ss != NULL) { // Parse included zone file. ret = zs_scanner_parse_file(ss, (char*)(s->buffer)); - zs_scanner_free(ss); if (ret != 0) { - ERR(ZS_UNPROCESSED_INCLUDE); + // File internal errors are handled by error callback. + if (ss->error_counter > 0) { + ERR(ZS_UNPROCESSED_INCLUDE); + // General include file error. + } else { + ERR(ss->error_code); + } + zs_scanner_free(ss); p--; {cs = 246; goto _again;} } + zs_scanner_free(ss); } else { ERR(ZS_UNPROCESSED_INCLUDE); p--; {cs = 246; goto _again;} @@ -7115,7 +7118,7 @@ _match: // Stop scanner if required. if (s->stop == true) { - return -1; + return; } } break; @@ -7370,11 +7373,11 @@ _again: // Processing error. s->process_error(s); - return -1; + return; } // Check unclosed multiline record. - if (final_block && s->multiline) { + if (is_eof && s->multiline) { ERR(ZS_UNCLOSED_MULTILINE); s->error_counter++; s->process_error(s); @@ -7387,6 +7390,24 @@ _again: // Storing r_data pointer. s->r_data_tail = rdata_tail - s->r_data; +} + +int zs_scanner_parse(zs_scanner_t *s, + const char *start, + const char *end, + const bool final_block) +{ + if (s == NULL || start == NULL || end == NULL) { + return -1; + } + + // Parse input block. + parse_block(s, start, end, false); + + // Parse trailing artificial block (newline char) if not stop. + if (final_block && !s->stop) { + parse_block(s, NEWLINE_BLOCK, NEWLINE_BLOCK + 1, true); + } // Check if any errors has occured. if (s->error_counter > 0) { @@ -7486,13 +7507,7 @@ int zs_scanner_parse_file(zs_scanner_t *s, } // Scan zone file block. - zs_scanner_parse(s, data, data + block_size, false); - - // Process the last artificial block (newline char) if not fatal. - if (final_block == true && s->stop == 0) { - zs_scanner_parse(s, NEWLINE_BLOCK, NEWLINE_BLOCK + 1, - true); - } + zs_scanner_parse(s, data, data + block_size, final_block); // Zone file block unmapping. if (munmap(data, block_size) == -1) { @@ -7501,16 +7516,20 @@ int zs_scanner_parse_file(zs_scanner_t *s, free(s->file.name); return -1; } + + // Stop parsing if required. + if (s->stop) { + break; + } } + close(s->file.descriptor); + free(s->file.name); + // Check for scanner return. if (s->error_counter > 0) { - close(s->file.descriptor); - free(s->file.name); return -1; } - close(s->file.descriptor); - free(s->file.name); return 0; } diff --git a/src/zscanner/scanner.rl b/src/zscanner/scanner.rl index 0e2d9d60e5d8cbae633df73688c6b9e8dfe4eafc..2bcca2a16ed0191a1412a26db63a7ba37de12c73 100644 --- a/src/zscanner/scanner.rl +++ b/src/zscanner/scanner.rl @@ -159,15 +159,11 @@ void zs_scanner_free(zs_scanner_t *s) } } -int zs_scanner_parse(zs_scanner_t *s, - const char *start, - const char *end, - const bool final_block) +static void parse_block(zs_scanner_t *s, + const char *start, + const char *end, + const bool is_eof) { - if (s == NULL || start == NULL || end == NULL) { - return -1; - } - // Necessary scanner variables. const char *p = start; const char *pe = end; @@ -193,7 +189,7 @@ int zs_scanner_parse(zs_scanner_t *s, memcpy(stack, s->stack, sizeof(stack)); // End of file check. - if (final_block == true) { + if (is_eof) { eof = (char *)pe; } @@ -224,11 +220,11 @@ int zs_scanner_parse(zs_scanner_t *s, // Processing error. s->process_error(s); - return -1; + return; } // Check unclosed multiline record. - if (final_block && s->multiline) { + if (is_eof && s->multiline) { ERR(ZS_UNCLOSED_MULTILINE); s->error_counter++; s->process_error(s); @@ -241,6 +237,24 @@ int zs_scanner_parse(zs_scanner_t *s, // Storing r_data pointer. s->r_data_tail = rdata_tail - s->r_data; +} + +int zs_scanner_parse(zs_scanner_t *s, + const char *start, + const char *end, + const bool final_block) +{ + if (s == NULL || start == NULL || end == NULL) { + return -1; + } + + // Parse input block. + parse_block(s, start, end, false); + + // Parse trailing artificial block (newline char) if not stop. + if (final_block && !s->stop) { + parse_block(s, NEWLINE_BLOCK, NEWLINE_BLOCK + 1, true); + } // Check if any errors has occured. if (s->error_counter > 0) { @@ -340,13 +354,7 @@ int zs_scanner_parse_file(zs_scanner_t *s, } // Scan zone file block. - zs_scanner_parse(s, data, data + block_size, false); - - // Process the last artificial block (newline char) if not fatal. - if (final_block == true && s->stop == 0) { - zs_scanner_parse(s, NEWLINE_BLOCK, NEWLINE_BLOCK + 1, - true); - } + zs_scanner_parse(s, data, data + block_size, final_block); // Zone file block unmapping. if (munmap(data, block_size) == -1) { @@ -355,16 +363,20 @@ int zs_scanner_parse_file(zs_scanner_t *s, free(s->file.name); return -1; } + + // Stop parsing if required. + if (s->stop) { + break; + } } + close(s->file.descriptor); + free(s->file.name); + // Check for scanner return. if (s->error_counter > 0) { - close(s->file.descriptor); - free(s->file.name); return -1; } - close(s->file.descriptor); - free(s->file.name); return 0; } diff --git a/src/zscanner/scanner_body.rl b/src/zscanner/scanner_body.rl index 774b6a63e2a5bbb7b498a8d0cd6e07ef9e025a09..71bbe0ee6fff5a1a8f7e24bb51ae9216d82451dc 100644 --- a/src/zscanner/scanner_body.rl +++ b/src/zscanner/scanner_body.rl @@ -95,7 +95,7 @@ // In case of serious error, stop scanner. if (s->stop == true) { - return -1; + return; } } @@ -671,11 +671,18 @@ if (ss != NULL) { // Parse included zone file. ret = zs_scanner_parse_file(ss, (char*)(s->buffer)); - zs_scanner_free(ss); if (ret != 0) { - ERR(ZS_UNPROCESSED_INCLUDE); + // File internal errors are handled by error callback. + if (ss->error_counter > 0) { + ERR(ZS_UNPROCESSED_INCLUDE); + // General include file error. + } else { + ERR(ss->error_code); + } + zs_scanner_free(ss); fhold; fgoto err_line; } + zs_scanner_free(ss); } else { ERR(ZS_UNPROCESSED_INCLUDE); fhold; fgoto err_line; @@ -1905,7 +1912,7 @@ // Stop scanner if required. if (s->stop == true) { - return -1; + return; } } diff --git a/src/zscanner/tests/data/06-3_INCLUDE.out b/src/zscanner/tests/data/06-3_INCLUDE.out index 965597d62c1a81c0d6b08a538dc91bb9e11118d5..8a5289b0bca31bf9482c21fa6ba07290f39d947d 100644 --- a/src/zscanner/tests/data/06-3_INCLUDE.out +++ b/src/zscanner/tests/data/06-3_INCLUDE.out @@ -1,2 +1,2 @@ -ERROR=ZS_UNPROCESSED_INCLUDE +ERROR=ZS_FILE_DIRECTORY ------ diff --git a/src/zscanner/tests/data/06-4_INCLUDE.out b/src/zscanner/tests/data/06-4_INCLUDE.out index 965597d62c1a81c0d6b08a538dc91bb9e11118d5..e09e5d1cfc18ed8606c48a1395e3c7603b9de72d 100644 --- a/src/zscanner/tests/data/06-4_INCLUDE.out +++ b/src/zscanner/tests/data/06-4_INCLUDE.out @@ -1,2 +1,2 @@ -ERROR=ZS_UNPROCESSED_INCLUDE +ERROR=ZS_FILE_OPEN ------ diff --git a/tests-extra/tests/dnssec/no_resign/test.py b/tests-extra/tests/dnssec/no_resign/test.py index 7e344180df5f9770c13125d4e9c26842ebe29d44..b6b7395d179e134a1523c29f39b10a56261e10e7 100644 --- a/tests-extra/tests/dnssec/no_resign/test.py +++ b/tests-extra/tests/dnssec/no_resign/test.py @@ -24,6 +24,7 @@ master.dnssec_enable = True master.use_keys(nsec_zone) master.use_keys(nsec3_zone) master.gen_confile() +t.sleep(2) master.reload() t.sleep(4) diff --git a/tests-extra/tests/edns/version/test.py b/tests-extra/tests/edns/version/test.py index 7307567698dacb725507552d0a6095f35a60e8bf..69dacb4b561721a2394f66c4bc88a801297e5af9 100644 --- a/tests-extra/tests/edns/version/test.py +++ b/tests-extra/tests/edns/version/test.py @@ -15,10 +15,10 @@ t.start() # Supported EDNS version 0. resp = server.dig("example.com", "SOA", edns=0) -resp.check(rcode="NOERROR") +resp.check(rcode="NOERROR", edns_version=0) # Unsupported EDNS version 1. resp = server.dig("example.com", "SOA", edns=1) -resp.check(rcode="BADVERS") +resp.check(rcode="BADVERS", edns_version=0) t.end() diff --git a/tests-extra/tools/dnstest/response.py b/tests-extra/tools/dnstest/response.py index 41cebc32515725ece2ea8d4108f1e5791e290bfe..51b014f7fbcf1a6ff693dcc5ba5341e971479fe0 100644 --- a/tests-extra/tools/dnstest/response.py +++ b/tests-extra/tools/dnstest/response.py @@ -8,8 +8,9 @@ from dnstest.utils import * class Response(object): '''Dig output context.''' - def __init__(self, server, response, args): + def __init__(self, server, response, query, args): self.resp = response + self.query = query self.args = args self.srv = server @@ -113,13 +114,17 @@ class Response(object): return def check(self, rdata=None, ttl=None, rcode="NOERROR", nordata=None, - flags="", noflags="", eflags="", noeflags=""): + edns_version=None, flags="", noflags="", eflags="", noeflags=""): '''Flags are text strings separated by whitespace character''' self._check_flags(flags, noflags) self._check_eflags(eflags, noeflags) self._check_question() + # Check EDNS version. + edns_ver = int(edns_version) if edns_version != None else self.query.edns + compare(edns_ver, self.resp.edns, "EDNS VERSION") + # Check rcode. if type(rcode) is not str: rc = dns.rcode.to_text(rcode) diff --git a/tests-extra/tools/dnstest/server.py b/tests-extra/tools/dnstest/server.py index f362346f590d52ea139f0d5771aa451e5407c270..5fa5adc762f4830820d23056c5e85219a477126c 100644 --- a/tests-extra/tools/dnstest/server.py +++ b/tests-extra/tools/dnstest/server.py @@ -525,7 +525,7 @@ class Server(object): if not log_no_sep: detail_log(SEP) - return dnstest.response.Response(self, resp, args) + return dnstest.response.Response(self, resp, query, args) except dns.exception.Timeout: pass except: @@ -634,7 +634,7 @@ class Server(object): src_files = os.listdir(zone.key_dir) for file_name in src_files: - if zone.name[:-1] in file_name: + if (zone.name[:-1]).lower() in file_name: full_file_name = os.path.join(zone.key_dir, file_name) if (os.path.isfile(full_file_name)): shutil.copy(full_file_name, self.keydir)