diff --git a/.gitignore b/.gitignore index d4521779db00d2cf43f7d71ec299dad3cd1c58c9..dd362beafa091fc713f22cd4104e49f838b15664 100644 --- a/.gitignore +++ b/.gitignore @@ -78,10 +78,12 @@ /src/khost /src/knsupdate /src/knsec3hash + +# Code coverage *.gcda *.gcno -/*.info -/*coverage/ +/coverage.info +/coverage.html # sphinx documentation /doc/_build/ diff --git a/Makefile.am b/Makefile.am index 33f9e2beeaff20a1e4be2198b6408afd2fade645..f572c0d73c438071eda05fb6015a343977a294b1 100644 --- a/Makefile.am +++ b/Makefile.am @@ -4,6 +4,13 @@ SUBDIRS = libtap src tests samples doc man patches AM_DISTCHECK_CONFIGURE_FLAGS = \ --disable-code-coverage +CODE_COVERAGE_INFO = coverage.info +CODE_COVERAGE_HTML = coverage.html +CODE_COVERAGE_DIRS = \ + src/common src/knot src/libknot \ + src/knot/conf \ + src/zscanner + code_coverage_quiet = --quiet check-code-coverage: @@ -20,31 +27,13 @@ endif code-coverage-initial: if CODE_COVERAGE_ENABLED $(LCOV) $(code_coverage_quiet) \ - --directory $(top_builddir)/src/common \ - --directory $(top_builddir)/src/knot \ - --directory $(top_builddir)/src/libknot \ - --capture --initial \ - --ignore-errors source \ - --base-directory $(top_builddir)/src \ - --output-file "$(PACKAGE_NAME)-$(PACKAGE_VERSION)-src_base.info" \ - --test-name "$(PACKAGE_NAME)-$(PACKAGE_VERSION)" \ - --no-checksum --compat-libtool - $(LCOV) $(code_coverage_quiet) \ - --directory $(top_builddir)/src/knot/conf \ + --no-external \ + $(foreach dir, $(CODE_COVERAGE_DIRS), --directory $(top_builddir)/$(dir)) \ --capture --initial \ --ignore-errors source \ - --base-directory $(top_builddir)/src/knot/conf \ - --output-file "$(PACKAGE_NAME)-$(PACKAGE_VERSION)-conf_base.info" \ - --test-name "$(PACKAGE_NAME)-$(PACKAGE_VERSION)" \ - --no-checksum --compat-libtool - $(LCOV) $(code_coverage_quiet) \ - --directory $(top_builddir)/src/zscanner \ - --capture --initial \ - --ignore-errors source \ - --base-directory $(top_builddir)/src/zscanner \ - --output-file "$(PACKAGE_NAME)-$(PACKAGE_VERSION)-zscanner_base.info" \ - --test-name "$(PACKAGE_NAME)-$(PACKAGE_VERSION)" \ - --no-checksum --compat-libtool + --no-checksum \ + --compat-libtool \ + --output-file $(CODE_COVERAGE_INFO) else @echo "You need to run configure with --enable-code-coverage to enable code coverage" endif @@ -52,39 +41,13 @@ endif code-coverage-capture: if CODE_COVERAGE_ENABLED $(LCOV) $(code_coverage_quiet) \ - --directory $(top_builddir)/src/common \ - --directory $(top_builddir)/src/knot \ - --directory $(top_builddir)/src/libknot \ + --no-external \ + $(foreach dir, $(CODE_COVERAGE_DIRS), --directory $(builddir)/$(dir)) \ --capture \ --ignore-errors source \ - --base-directory $(top_builddir)/src \ - --output-file "$(PACKAGE_NAME)-$(PACKAGE_VERSION)-src_capture.info" \ - --test-name "$(PACKAGE_NAME)-$(PACKAGE_VERSION)" \ - --no-checksum --compat-libtool - $(LCOV) $(code_coverage_quiet) \ - --directory $(top_builddir)/src/knot/conf \ - --capture \ - --ignore-errors source \ - --base-directory $(top_builddir)/src/knot/conf \ - --output-file "$(PACKAGE_NAME)-$(PACKAGE_VERSION)-conf_capture.info" \ - --test-name "$(PACKAGE_NAME)-$(PACKAGE_VERSION)" \ - --no-checksum --compat-libtool - $(LCOV) $(code_coverage_quiet) \ - --directory $(top_builddir)/src/zscanner \ - --capture \ - --ignore-errors source \ - --base-directory $(top_builddir)/src/zscanner \ - --output-file "$(PACKAGE_NAME)-$(PACKAGE_VERSION)-zscanner_capture.info" \ - --test-name "$(PACKAGE_NAME)-$(PACKAGE_VERSION)" \ - --no-checksum --compat-libtool - $(LCOV) $(code_coverage_quiet) \ - --add-tracefile "$(PACKAGE_NAME)-$(PACKAGE_VERSION)-src_base.info" \ - --add-tracefile "$(PACKAGE_NAME)-$(PACKAGE_VERSION)-conf_base.info" \ - --add-tracefile "$(PACKAGE_NAME)-$(PACKAGE_VERSION)-zscanner_base.info" \ - --add-tracefile "$(PACKAGE_NAME)-$(PACKAGE_VERSION)-src_capture.info" \ - --add-tracefile "$(PACKAGE_NAME)-$(PACKAGE_VERSION)-conf_capture.info" \ - --add-tracefile "$(PACKAGE_NAME)-$(PACKAGE_VERSION)-zscanner_capture.info" \ - --output-file "$(PACKAGE_NAME)-$(PACKAGE_VERSION)-coverage.info" + --no-checksum \ + --compat-libtool \ + --output-file $(CODE_COVERAGE_INFO) else @echo "You need to run configure with --enable-code-coverage to enable code coverage" endif @@ -93,7 +56,12 @@ code-coverage-html: if CODE_COVERAGE_ENABLED @echo "Generating code coverage HTML report (this might take a while)" @cp src/knot/conf/cf-lex.l src/knot/conf/cf-parse.y src/ - LANG=C $(GENHTML) $(code_coverage_quiet) --prefix $(top_builddir) --output-directory "$(PACKAGE_NAME)-$(PACKAGE_VERSION)-coverage" --title "$(PACKAGE_NAME)-$(PACKAGE_VERSION) Code Coverage" --legend --show-details "$(PACKAGE_NAME)-$(PACKAGE_VERSION)-coverage.info" --ignore-errors source + LANG=C $(GENHTML) $(code_coverage_quiet) \ + --output-directory $(CODE_COVERAGE_HTML) \ + --title "Knot DNS $(PACKAGE_VERSION) Code Coverage" \ + --legend --show-details \ + --ignore-errors source \ + $(CODE_COVERAGE_INFO) -@rm src/cf-lex.l src/cf-parse.y else @echo "You need to run configure with --enable-code-coverage to enable code coverage" @@ -102,7 +70,7 @@ endif code-coverage-summary: if CODE_COVERAGE_ENABLED $(LCOV) \ - --summary "$(PACKAGE_NAME)-$(PACKAGE_VERSION)-coverage.info" + --summary $(CODE_COVERAGE_INFO) else @echo "You need to run configure with --enable-code-coverage to enable code coverage" endif @@ -112,10 +80,7 @@ clean-local: code-coverage-clean -find . -name "*.gcno" -delete code-coverage-clean: -$(LCOV) --directory $(top_builddir) -z - -rm -rf $(PACKAGE_NAME)-$(PACKAGE_VERSION)-*_base.info \ - $(PACKAGE_NAME)-$(PACKAGE_VERSION)-*_capture.info \ - $(PACKAGE_NAME)-$(PACKAGE_VERSION)-coverage.info \ - $(PACKAGE_NAME)-$(PACKAGE_VERSION)-coverage/ + -rm -rf $(CODE_COVERAGE_INFO) $(CODE_COVERAGE_HTML) -find . -name "*.gcda" -o -name "*.gcov" -delete endif diff --git a/configure.ac b/configure.ac index 1c463f8cac996d33d4eb83026b1e58cdbf781c8b..c7eaf264566374c8a25bfb5e495829d244444caf 100644 --- a/configure.ac +++ b/configure.ac @@ -28,7 +28,7 @@ AM_PROG_CC_C_O AC_PROG_CPP_WERROR # Default compiler flags -CFLAGS="$CFLAGS -Wall -Werror=format-security" +CFLAGS="$CFLAGS -Wall -Werror=format-security -Werror=implicit" # Checks for programs. m4_ifdef([AM_PROG_AR], [AM_PROG_AR]) # call AM_PROG_AR only if available diff --git a/src/common/log.c b/src/common/log.c index 7eb73ccff6e96aa8fc6a38a148762d90d456438a..22338702d72e062182e9bae8dfbefa78fba9fef1 100644 --- a/src/common/log.c +++ b/src/common/log.c @@ -14,7 +14,6 @@ along with this program. If not, see <http://www.gnu.org/licenses/>. */ -#define _BSD_SOURCE #include <stdarg.h> #include <stdio.h> #include <string.h> diff --git a/src/dnstap/dnstap.c b/src/dnstap/dnstap.c index 41d42e7b4cf0bfd39a091ee2c2186fd639e86cd1..cf3770c765ea87e4a3571bf77b2f2192e6ccc43b 100644 --- a/src/dnstap/dnstap.c +++ b/src/dnstap/dnstap.c @@ -23,7 +23,7 @@ uint8_t* dt_pack(const Dnstap__Dnstap *d, uint8_t **buf, size_t *sz) { - ProtobufCBufferSimple sbuf; + ProtobufCBufferSimple sbuf = {0}; sbuf.base.append = protobuf_c_buffer_simple_append; sbuf.len = 0; diff --git a/src/knot/conf/conf.c b/src/knot/conf/conf.c index 8c7fd7fceb6d27208c8bfa45d584822d34fae208..a3fb94bb2eb79ad883d0a81c732d1401d459cd8c 100644 --- a/src/knot/conf/conf.c +++ b/src/knot/conf/conf.c @@ -784,7 +784,7 @@ int conf_open(const char* path) /* Open zone timers db. */ nconf->timers_db = open_timers_db(nconf->storage); if (nconf->timers_db == NULL) { - log_warning("cannot open timers db\n"); + log_warning("cannot open timers db"); } /* Replace current config. */ diff --git a/src/knot/ctl/remote.c b/src/knot/ctl/remote.c index 2fe8e2bfdd3ae7a89e8a35915e8fa9e491c2c01a..067f39bfb8ee68faaf9f40f5eb571848bc1f9a7c 100644 --- a/src/knot/ctl/remote.c +++ b/src/knot/ctl/remote.c @@ -727,7 +727,7 @@ static int zones_verify_tsig_query(const knot_pkt_t *query, * or some other error. */ *rcode = KNOT_RCODE_NOTAUTH; - *tsig_rcode = KNOT_RCODE_BADKEY; + *tsig_rcode = KNOT_TSIG_ERR_BADKEY; return KNOT_TSIG_EBADKEY; } @@ -741,7 +741,7 @@ static int zones_verify_tsig_query(const knot_pkt_t *query, if (!(key && kname && knot_dname_cmp(key->name, kname) == 0 && key->algorithm == alg)) { *rcode = KNOT_RCODE_NOTAUTH; - *tsig_rcode = KNOT_RCODE_BADKEY; + *tsig_rcode = KNOT_TSIG_ERR_BADKEY; return KNOT_TSIG_EBADKEY; } @@ -780,15 +780,15 @@ static int zones_verify_tsig_query(const knot_pkt_t *query, *rcode = KNOT_RCODE_NOERROR; break; case KNOT_TSIG_EBADKEY: - *tsig_rcode = KNOT_RCODE_BADKEY; + *tsig_rcode = KNOT_TSIG_ERR_BADKEY; *rcode = KNOT_RCODE_NOTAUTH; break; case KNOT_TSIG_EBADSIG: - *tsig_rcode = KNOT_RCODE_BADSIG; + *tsig_rcode = KNOT_TSIG_ERR_BADSIG; *rcode = KNOT_RCODE_NOTAUTH; break; case KNOT_TSIG_EBADTIME: - *tsig_rcode = KNOT_RCODE_BADTIME; + *tsig_rcode = KNOT_TSIG_ERR_BADTIME; // store the time signed from the query *tsig_prev_time_signed = tsig_rdata_time_signed(query->tsig_rr); *rcode = KNOT_RCODE_NOTAUTH; diff --git a/src/knot/nameserver/internet.c b/src/knot/nameserver/internet.c index 5214f158d07c4c3ae73320500637b9e2272adadb..17c13d8e1f589c806ba94603a7306835d1eec81c 100644 --- a/src/knot/nameserver/internet.c +++ b/src/knot/nameserver/internet.c @@ -121,7 +121,7 @@ static bool dname_cname_cannot_synth(const knot_rrset_t *rrset, const knot_dname static bool have_dnssec(struct query_data *qdata) { return knot_pkt_has_dnssec(qdata->query) && - qdata->rcode_ext != KNOT_EDNS_RCODE_BADVERS && + qdata->rcode_ext != KNOT_RCODE_BADVERS && zone_contents_is_signed(qdata->zone->contents); } diff --git a/src/knot/nameserver/process_query.c b/src/knot/nameserver/process_query.c index 9fc7152ca9fad6e1a86799809e509718f4f87c5e..37cb93d2b0f67e9aba38af2ba86d5068442bfd96 100644 --- a/src/knot/nameserver/process_query.c +++ b/src/knot/nameserver/process_query.c @@ -230,7 +230,7 @@ static int answer_edns_init(const knot_pkt_t *query, knot_pkt_t *resp, /* Check supported version. */ if (knot_edns_get_version(query->opt_rr) != KNOT_EDNS_VERSION) { - qdata->rcode_ext = KNOT_EDNS_RCODE_BADVERS; + qdata->rcode_ext = KNOT_RCODE_BADVERS; } /* Set DO bit if set (DNSSEC requested). */ @@ -313,6 +313,11 @@ static int prepare_answer(const knot_pkt_t *query, knot_pkt_t *resp, knot_proces return ret; } + /* If Extended RCODE is set, do not continue with query processing. */ + if (qdata->rcode_ext != 0) { + return KNOT_ERROR; + } + /* Update maximal answer size. */ bool has_limit = qdata->param->proc_flags & NS_QUERY_LIMIT_SIZE; if (has_limit) { @@ -484,7 +489,8 @@ static int process_query_out(knot_pkt_t *pkt, knot_process_t *ctx) finish: /* Default RCODE is SERVFAIL if not specified otherwise. */ - if (next_state == NS_PROC_FAIL && qdata->rcode == KNOT_RCODE_NOERROR) { + if (next_state == NS_PROC_FAIL && qdata->rcode == KNOT_RCODE_NOERROR + && qdata->rcode_ext == 0) { qdata->rcode = KNOT_RCODE_SERVFAIL; } @@ -527,7 +533,7 @@ bool process_query_acl_check(list_t *acl, struct query_data *qdata) if (match == NULL || (match->key && match->key->algorithm != key_alg)) { dbg_ns("%s: no ACL match => NOTAUTH\n", __func__); qdata->rcode = KNOT_RCODE_NOTAUTH; - qdata->rcode_tsig = KNOT_RCODE_BADKEY; + qdata->rcode_tsig = KNOT_TSIG_ERR_BADKEY; return false; } @@ -566,15 +572,15 @@ int process_query_verify(struct query_data *qdata) break; case KNOT_TSIG_EBADKEY: qdata->rcode = KNOT_RCODE_NOTAUTH; - qdata->rcode_tsig = KNOT_RCODE_BADKEY; + qdata->rcode_tsig = KNOT_TSIG_ERR_BADKEY; break; case KNOT_TSIG_EBADSIG: qdata->rcode = KNOT_RCODE_NOTAUTH; - qdata->rcode_tsig = KNOT_RCODE_BADSIG; + qdata->rcode_tsig = KNOT_TSIG_ERR_BADSIG; break; case KNOT_TSIG_EBADTIME: qdata->rcode = KNOT_RCODE_NOTAUTH; - qdata->rcode_tsig = KNOT_RCODE_BADTIME; + qdata->rcode_tsig = KNOT_TSIG_ERR_BADTIME; ctx->tsig_time_signed = tsig_rdata_time_signed(query->tsig_rr); break; case KNOT_EMALF: diff --git a/src/libknot/consts.c b/src/libknot/consts.c index 23e3e28ca0d8a3677a2d4c50f3bf6181413d219d..694d47dd899963b116b7acf23b2e6c09cb4f4b07 100644 --- a/src/libknot/consts.c +++ b/src/libknot/consts.c @@ -37,13 +37,22 @@ knot_lookup_table_t knot_rcode_names[] = { { KNOT_RCODE_NXRRSET, "NXRRSET" }, { KNOT_RCODE_NOTAUTH, "NOTAUTH" }, { KNOT_RCODE_NOTZONE, "NOTZONE" }, - { KNOT_RCODE_BADSIG, "BADSIG" }, - { KNOT_RCODE_BADKEY, "BADKEY" }, - { KNOT_RCODE_BADTIME, "BADTIME" }, - { KNOT_RCODE_BADMODE, "BADMODE" }, - { KNOT_RCODE_BADNAME, "BADNAME" }, - { KNOT_RCODE_BADALG, "BADALG" }, - { KNOT_RCODE_BADTRUNC, "BADTRUNC" }, + { KNOT_RCODE_BADVERS, "BADVERS" }, + { 0, NULL } +}; + +knot_lookup_table_t knot_tsig_err_names[] = { + { KNOT_TSIG_ERR_BADSIG, "BADSIG" }, + { KNOT_TSIG_ERR_BADKEY, "BADKEY" }, + { KNOT_TSIG_ERR_BADTIME, "BADTIME" }, + { KNOT_TSIG_ERR_BADTRUNC, "BADTRUNC" }, + { 0, NULL } +}; + +knot_lookup_table_t knot_tkey_err_names[] = { + { KNOT_TKEY_ERR_BADMODE, "BADMODE" }, + { KNOT_TKEY_ERR_BADNAME, "BADNAME" }, + { KNOT_TKEY_ERR_BADALG, "BADALG" }, { 0, NULL } }; diff --git a/src/libknot/consts.h b/src/libknot/consts.h index 6bd94da895d6e9fc3c92196c1331fb35fa8807b9..1bac3ac783493a98a874ede6d883336e2259fe96 100644 --- a/src/libknot/consts.h +++ b/src/libknot/consts.h @@ -65,6 +65,10 @@ typedef enum { * \brief DNS reply codes (RCODEs). * * http://www.iana.org/assignments/dns-parameters/dns-parameters.xml + * + * \note Here, only RCODEs present in Header or as an Extended RCODE in + * OPT + Header are listed. Other codes are used in dedicated fields of + * other RRs. */ typedef enum { KNOT_RCODE_NOERROR = 0, /*!< No error. */ @@ -76,17 +80,24 @@ typedef enum { KNOT_RCODE_YXDOMAIN = 6, /*!< Name should not exist. */ KNOT_RCODE_YXRRSET = 7, /*!< RR set should not exist. */ KNOT_RCODE_NXRRSET = 8, /*!< RR set does not exist. */ - KNOT_RCODE_NOTAUTH = 9, /*!< Server not authoritative. */ + KNOT_RCODE_NOTAUTH = 9, /*!< Server not authoritative. / Query not authorized. */ KNOT_RCODE_NOTZONE = 10, /*!< Name is not inside zone. */ - KNOT_RCODE_BADSIG = 16, /*!< TSIG signature failed. */ - KNOT_RCODE_BADKEY = 17, /*!< Key is not supported. */ - KNOT_RCODE_BADTIME = 18, /*!< Signature out of time window. */ - KNOT_RCODE_BADMODE = 19, /*!< Bad TKEY mode. */ - KNOT_RCODE_BADNAME = 20, /*!< Duplicate key name. */ - KNOT_RCODE_BADALG = 21, /*!< Algorithm not supported. */ - KNOT_RCODE_BADTRUNC = 22 /*!< Bad truncation. */ + KNOT_RCODE_BADVERS = 16 /*!< Bad OPT Version. */ } knot_rcode_t; +typedef enum { + KNOT_TSIG_ERR_BADSIG = 16, /*!< TSIG signature failed. */ + KNOT_TSIG_ERR_BADKEY = 17, /*!< Key is not supported. */ + KNOT_TSIG_ERR_BADTIME = 18, /*!< Signature out of time window. */ + KNOT_TSIG_ERR_BADTRUNC = 22 /*!< Bad truncation. */ +} knot_tsig_error_t; + +typedef enum { + KNOT_TKEY_ERR_BADMODE = 19, /*!< Bad TKEY mode. */ + KNOT_TKEY_ERR_BADNAME = 20, /*!< Duplicate key name. */ + KNOT_TKEY_ERR_BADALG = 21 /*!< Algorithm not supported. */ +} knot_tkey_error_t; + /*! * \brief DNS packet section identifiers. */ diff --git a/src/libknot/packet/pkt.c b/src/libknot/packet/pkt.c index cb04b33c18776a016b1c37d2233611d8ebfaafc0..9168d0aa5964812b1ba70d13c9cfa006fc15d5c1 100644 --- a/src/libknot/packet/pkt.c +++ b/src/libknot/packet/pkt.c @@ -759,3 +759,19 @@ int knot_pkt_parse_payload(knot_pkt_t *pkt, unsigned flags) return KNOT_EOK; } + +uint16_t knot_pkt_get_ext_rcode(const knot_pkt_t *pkt) +{ + if (pkt == NULL) { + return 0; + } + + uint8_t rcode = knot_wire_get_rcode(pkt->wire); + + if (pkt->opt_rr) { + uint8_t opt_rcode = knot_edns_get_ext_rcode(pkt->opt_rr); + return knot_edns_whole_rcode(opt_rcode, rcode); + } else { + return rcode; + } +} diff --git a/src/libknot/packet/pkt.h b/src/libknot/packet/pkt.h index 42adf6df8e8368e61493fbb2059b112029fc12e1..f37b0c6149a48a3b4d48c6a62390819897eda2ed 100644 --- a/src/libknot/packet/pkt.h +++ b/src/libknot/packet/pkt.h @@ -294,6 +294,19 @@ int knot_pkt_parse_section(knot_pkt_t *pkt, unsigned flags); */ int knot_pkt_parse_payload(knot_pkt_t *pkt, unsigned flags); +/*! + * \brief Get the Extended RCODE from the packet. + * + * Extended RCODE is created by using the Extended RCODE field from OPT RR as + * higher 8 bits and the RCODE from DNS Header as the lower 4 bits, resulting + * in a 12-bit unsigned integer. (See RFC 6891, Section 6.1.3). + * + * \param pkt Packet to get the response code from. + * + * \return Whole extended RCODE (0 if pkt == NULL). + */ +uint16_t knot_pkt_get_ext_rcode(const knot_pkt_t *pkt); + /*! * \brief Checks if there is an OPT RR in the packet. */ diff --git a/src/libknot/rrtype/opt.h b/src/libknot/rrtype/opt.h index 816469e925bba9058ff47f4aab02d37f4a0d8dc3..ab13ba287223143ae8d1202cfcb84063c078c1f5 100644 --- a/src/libknot/rrtype/opt.h +++ b/src/libknot/rrtype/opt.h @@ -138,6 +138,25 @@ void knot_edns_set_payload(knot_rrset_t *opt_rr, uint16_t payload); */ uint8_t knot_edns_get_ext_rcode(const knot_rrset_t *opt_rr); +/*! + * \brief Concatenates OPT RR Extended RCODE field and normal RCODE to get the + * whole Extended RCODE. + * + * Extended RCODE is created by using the Extended RCODE field from OPT RR as + * higher 8 bits and the RCODE from DNS Header as the lower 4 bits, resulting + * in a 12-bit unsigned integer. (See RFC 6891, Section 6.1.3). + * + * \param ext_rcode Extended RCODE field from OPT RR. + * \param rcode RCODE from DNS Header. + * + * \return 12-bit Extended RCODE. + */ +static inline uint16_t knot_edns_whole_rcode(uint8_t ext_rcode, uint8_t rcode) +{ + uint16_t high = ext_rcode; + return (high << 4) | rcode; +} + /*! * \brief Sets the Extended RCODE field in the OPT RR. * diff --git a/src/libknot/rrtype/tsig.c b/src/libknot/rrtype/tsig.c index 7722d3a1d47de58d42800ec65542936cee350190..ee2b99871f9a5e260025d75b9018adc5be0c4616 100644 --- a/src/libknot/rrtype/tsig.c +++ b/src/libknot/rrtype/tsig.c @@ -132,7 +132,7 @@ int tsig_create_rdata(knot_rrset_t *rr, const knot_dname_t *alg, uint16_t maclen /* We already checked rr and know rdlen > 0, no need to check rets. */ int alg_len = knot_dname_size(alg); size_t rdlen = alg_len + TSIG_FIXED_RDLEN + maclen; - if (tsig_err != KNOT_RCODE_BADTIME) { + if (tsig_err != KNOT_TSIG_ERR_BADTIME) { rdlen -= TSIG_OTHER_MAXLEN; } uint8_t rd[rdlen]; diff --git a/src/libknot/tsig-op.c b/src/libknot/tsig-op.c index 2d91e2db75eccfccbaf61c6754bb04f1766ac322..b3a8a81e29fe36bc308794a85362508ba4d0b704 100644 --- a/src/libknot/tsig-op.c +++ b/src/libknot/tsig-op.c @@ -460,13 +460,13 @@ int knot_tsig_sign(uint8_t *msg, size_t *msg_len, /* Create rdata for TSIG RR. */ uint16_t rdata_rcode = 0; - if (tsig_rcode == KNOT_RCODE_BADTIME) + if (tsig_rcode == KNOT_TSIG_ERR_BADTIME) rdata_rcode = tsig_rcode; tsig_create_rdata(tmp_tsig, tsig_alg_to_dname(key->algorithm), knot_tsig_digest_length(key->algorithm), rdata_rcode); /* Distinguish BADTIME response. */ - if (tsig_rcode == KNOT_RCODE_BADTIME) { + if (tsig_rcode == KNOT_TSIG_ERR_BADTIME) { /* Set client's time signed into the time signed field. */ tsig_rdata_set_time_signed(tmp_tsig, request_time_signed); @@ -799,7 +799,7 @@ int knot_tsig_add(uint8_t *msg, size_t *msg_len, size_t msg_max_len, return KNOT_ENOMEM; } - assert(tsig_rcode != KNOT_RCODE_BADTIME); + assert(tsig_rcode != KNOT_TSIG_ERR_BADTIME); tsig_create_rdata(tmp_tsig, tsig_rdata_alg_name(tsig_rr), 0, tsig_rcode); tsig_rdata_set_time_signed(tmp_tsig, tsig_rdata_time_signed(tsig_rr)); diff --git a/src/libknot/tsig-op.h b/src/libknot/tsig-op.h index 17bf4dbd68fa667f55dda6e78d3a5741f0800df3..b6bb4cd5cf5447f0171ef67a7ff4de332bc607ff 100644 --- a/src/libknot/tsig-op.h +++ b/src/libknot/tsig-op.h @@ -169,7 +169,7 @@ int knot_tsig_append(uint8_t *msg, size_t *msg_len, size_t msg_max_len, /*! \brief Return true if the TSIG RCODE allows signing the packet. */ static inline bool knot_tsig_can_sign(uint16_t tsig_rcode) { - return (tsig_rcode == KNOT_RCODE_NOERROR || tsig_rcode == KNOT_RCODE_BADTIME); + return (tsig_rcode == KNOT_RCODE_NOERROR || tsig_rcode == KNOT_TSIG_ERR_BADTIME); } /*! @} */ diff --git a/src/utils/common/exec.c b/src/utils/common/exec.c index d516518aff7e90fb24b17504ebdb98e44e2a4908..1fa4b5010a3562de5f260f95a673053dbb32d578 100644 --- a/src/utils/common/exec.c +++ b/src/utils/common/exec.c @@ -49,21 +49,22 @@ static knot_lookup_table_t rtypes[] = { { 0, NULL } }; -static void print_header(const knot_pkt_t *packet, const style_t *style) +static void print_header(const knot_pkt_t *packet, const style_t *style, + const uint16_t ext_rcode) { char flags[64] = ""; - uint8_t rcode_id, opcode_id; - const char *rcode_str = "NULL"; - const char *opcode_str = "NULL"; + uint8_t opcode_id; + const char *rcode_str = "Unknown"; + const char *opcode_str = "Unknown"; knot_lookup_table_t *rcode, *opcode; - // Get codes. - rcode_id = knot_wire_get_rcode(packet->wire); - rcode = knot_lookup_by_id(knot_rcode_names, rcode_id); + // Get RCODE from Header and check for Extended RCODE from OPT RR. + rcode = knot_lookup_by_id(knot_rcode_names, ext_rcode); if (rcode != NULL) { rcode_str = rcode->name; } + // Get OPCODE. opcode_id = knot_wire_get_opcode(packet->wire); opcode = knot_lookup_by_id(knot_opcode_names, opcode_id); if (opcode != NULL) { @@ -213,18 +214,23 @@ static void print_edns_client_subnet(const uint8_t *data, const uint16_t len) printf("%s/%u/%u\n", addr_str, src_mask, dst_mask); } -static void print_section_opt(const knot_rrset_t *rr) +static void print_section_opt(const knot_rrset_t *rr, const uint8_t rcode) { - uint8_t ext_rcode_id = knot_edns_get_ext_rcode(rr); - const char *ext_rcode_str = "NULL"; + uint8_t ercode = knot_edns_get_ext_rcode(rr); + uint16_t ext_rcode_id = knot_edns_whole_rcode(ercode, rcode); + const char *ext_rcode_str = "Unused"; knot_lookup_table_t *ext_rcode; - ext_rcode = knot_lookup_by_id(knot_rcode_names, ext_rcode_id); - if (ext_rcode != NULL) { - ext_rcode_str = ext_rcode->name; + if (ercode > 0) { + ext_rcode = knot_lookup_by_id(knot_rcode_names, ext_rcode_id); + if (ext_rcode != NULL) { + ext_rcode_str = ext_rcode->name; + } else { + ext_rcode_str = "Unknown"; + } } - printf("Version: %u; flags: %s; UDP size: %u B, status: %s\n", + printf("Version: %u; flags: %s; UDP size: %u B; ext-rcode: %s\n", knot_edns_get_version(rr), (knot_edns_do(rr) != 0) ? "do" : "", knot_edns_get_payload(rr), @@ -422,12 +428,12 @@ static void print_section_host(const knot_rrset_t *rrsets, free(buf); } -static void print_error_host(const uint8_t code, +static void print_error_host(const uint16_t code, const knot_pkt_t *packet, const style_t *style) { - const char *rcode_str = "NULL"; - char type[32] = "NULL"; + const char *rcode_str = "Unknown"; + char type[32] = "Unknown"; char *owner; knot_lookup_table_t *rcode; @@ -436,6 +442,7 @@ static void print_error_host(const uint8_t code, if (style->style.ascii_to_idn != NULL) { style->style.ascii_to_idn(&owner); } + rcode = knot_lookup_by_id(knot_rcode_names, code); if (rcode != NULL) { rcode_str = rcode->name; @@ -567,12 +574,14 @@ void print_packet(const knot_pkt_t *packet, const knot_pktsection_t *additional = knot_pkt_section(packet, KNOT_ADDITIONAL); - uint8_t rcode = knot_wire_get_rcode(packet->wire); uint16_t qdcount = knot_wire_get_qdcount(packet->wire); uint16_t ancount = knot_wire_get_ancount(packet->wire); uint16_t nscount = knot_wire_get_nscount(packet->wire); uint16_t arcount = knot_wire_get_arcount(packet->wire); + // Get Extended RCODE from the packet. + uint16_t rcode = knot_pkt_get_ext_rcode(packet); + // Disable additionals printing if there are no other records. // OPT record may be placed anywhere within additionals! if (knot_pkt_has_edns(packet) && arcount == 1) { @@ -581,13 +590,14 @@ void print_packet(const knot_pkt_t *packet, // Print packet information header. if (style->show_header) { - print_header(packet, style); + print_header(packet, style, rcode); } // Print EDNS section. if (style->show_edns && knot_pkt_has_edns(packet)) { printf("\n;; EDNS PSEUDOSECTION:\n;; "); - print_section_opt(packet->opt_rr); + print_section_opt(packet->opt_rr, + knot_wire_get_rcode(packet->wire)); } // Print DNS sections. diff --git a/src/zscanner/scanner.c.g2 b/src/zscanner/scanner.c.g2 index 1814ab63595c03a914e7e3114073da10a7c52239..342a717bd2292853042121dfb39d569e898df65b 100644 --- a/src/zscanner/scanner.c.g2 +++ b/src/zscanner/scanner.c.g2 @@ -73156,6 +73156,13 @@ int zs_scanner_parse_file(zs_scanner_t *s, return -1; } + // Check for empty file. + if (file_stat.st_size == 0) { + close(s->file.descriptor); + free(s->file.name); + return 0; + } + // Block size adjustment to multiple of page size. default_block_size = (BLOCK_SIZE / page_size) * page_size; diff --git a/src/zscanner/scanner.c.t0 b/src/zscanner/scanner.c.t0 index 1b6e8248b81a6bf66eeaec5b3b40f62815328828..e793fb8330e85af8212c52e85423ec437f6a7158 100644 --- a/src/zscanner/scanner.c.t0 +++ b/src/zscanner/scanner.c.t0 @@ -7477,6 +7477,13 @@ int zs_scanner_parse_file(zs_scanner_t *s, return -1; } + // Check for empty file. + if (file_stat.st_size == 0) { + close(s->file.descriptor); + free(s->file.name); + return 0; + } + // Block size adjustment to multiple of page size. default_block_size = (BLOCK_SIZE / page_size) * page_size; diff --git a/src/zscanner/scanner.rl b/src/zscanner/scanner.rl index 3a36dd4b3ed94f025d67aae0faec0e3adbad88a9..e53e041c0c5e3ae520e21972d3269e72a1c51a93 100644 --- a/src/zscanner/scanner.rl +++ b/src/zscanner/scanner.rl @@ -324,6 +324,13 @@ int zs_scanner_parse_file(zs_scanner_t *s, return -1; } + // Check for empty file. + if (file_stat.st_size == 0) { + close(s->file.descriptor); + free(s->file.name); + return 0; + } + // Block size adjustment to multiple of page size. default_block_size = (BLOCK_SIZE / page_size) * page_size; diff --git a/tests-extra/tests/edns/version/test.py b/tests-extra/tests/edns/version/test.py index 69dacb4b561721a2394f66c4bc88a801297e5af9..736f32ea9820fba184adb86340f206c10475e8a1 100644 --- a/tests-extra/tests/edns/version/test.py +++ b/tests-extra/tests/edns/version/test.py @@ -3,6 +3,7 @@ '''Test for EDNS version''' from dnstest.test import Test +from dnstest.utils import * t = Test() @@ -20,5 +21,9 @@ resp.check(rcode="NOERROR", edns_version=0) # Unsupported EDNS version 1. resp = server.dig("example.com", "SOA", edns=1) resp.check(rcode="BADVERS", edns_version=0) +compare(resp.count(section="answer"), 0, "Answer count") +compare(resp.count(section="authority"), 0, "Authority count") +compare(resp.count(section="additional"), 0, "Additional count") + t.end() diff --git a/tests-extra/tests/events/soa/test.py b/tests-extra/tests/events/soa/test.py index 37e976188c139c47c0bd84562aba8d8ccd965b95..45a23d6465ab5202fe0e5ee57e9ee5b51606c706 100644 --- a/tests-extra/tests/events/soa/test.py +++ b/tests-extra/tests/events/soa/test.py @@ -22,19 +22,27 @@ def test_expire(slave): resp = slave.dig("example.", "SOA") resp.check(rcode="SERVFAIL") -def test_run(t, action): - master = t.server("bind") - master.disable_notify = True +def create_servers(t): + servers = [] + for _ in range(3): + master = t.server("bind") + master.disable_notify = True - slave = t.server("knot") - slave.disable_notify = True - slave.max_conn_idle = "1s" + slave = t.server("knot") + slave.disable_notify = True + slave.max_conn_idle = "1s" - # this zone has refresh = 1s, retry = 1s and expire = 1s + 2s for connection timeouts - zone = t.zone("example.", storage=".") + t.link(zone, master, slave) - t.link(zone, master, slave) - t.start() + servers.append((master, slave)) + + return servers + +def test_run(t, servers, zone, action): + master, slave = servers + + master.start() + slave.start() slave.zone_wait(zone) action(t, slave) # action should keep the event intact @@ -86,8 +94,6 @@ def test_run(t, action): detail_log("Expire - roles switch 2") test_expire(slave) - t.stop() - def reload_server(t, s): s.reload() t.sleep(1) @@ -106,8 +112,24 @@ t = Test() random.seed() -test_run(t, reload_server) -test_run(t, restart_server) -test_run(t, reload_or_restart) +# this zone has refresh = 1s, retry = 1s and expire = 1s + 2s for connection timeouts +zone = t.zone("example.", storage=".") + +servers = create_servers(t) + +t.start() + +#stop the servers so that the zone does not expire +for server_pair in servers: + server_pair[0].stop() + server_pair[1].stop() + +test_run(t, servers[0], zone, reload_server) +test_run(t, servers[1], zone, restart_server) +test_run(t, servers[2], zone, reload_or_restart) + +t.stop() + + diff --git a/tests/.gitignore b/tests/.gitignore index e3fa8d791e4bedfbb1fccd5e194ba7d0c9db0657..1dc26d1ba89200dd5922b1c110c54396418851f3 100644 --- a/tests/.gitignore +++ b/tests/.gitignore @@ -21,6 +21,7 @@ fdset hattrie hhash journal +namedb node pkt process_answer @@ -38,6 +39,7 @@ wire worker_pool worker_queue zone_events +zone_timers zone_update zonedb ztree diff --git a/tests/dname.c b/tests/dname.c index 1b3d6df9b59fc410c3c50b8e8bc098ab3b9101bd..57c619b489495d007b290777eeffe9dc66ee3a62 100644 --- a/tests/dname.c +++ b/tests/dname.c @@ -104,7 +104,7 @@ static void test_str(const char *in_str, const char *in_bin, size_t bin_len) { int main(int argc, char *argv[]) { - plan(285); + plan_lazy(); knot_dname_t *d = NULL, *d2 = NULL; const char *w = NULL, *t = NULL; @@ -303,10 +303,12 @@ int main(int argc, char *argv[]) } /* incomplete dname */ + /* ASAN: global-buffer-overflow w = "\x08" "dddd"; s = knot_dname_to_str_alloc((const uint8_t *)w); ok(s != NULL, "dname_to_str: incomplete dname"); free(s); + */ /* non-fqdn */ w = "\x02" "ab"; diff --git a/tests/namedb.c b/tests/namedb.c index f008a5be924fa17f39ba92aac8eb6d3dcd2d20c2..67a61f517fc2731d36be9d33567f311f7a30f143 100644 --- a/tests/namedb.c +++ b/tests/namedb.c @@ -16,6 +16,7 @@ #include <string.h> #include <time.h> +#include <unistd.h> #include <tap/basic.h> #include "libknot/common.h"