From: Tom Carpay Date: Mon, 15 Nov 2021 14:48:35 +0000 (+0000) Subject: Merge branch 'master' into features/rfc8914-ede X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=787d7a5952abad6e2a4a65cbeb44d4dc5d631d53;p=thirdparty%2Funbound.git Merge branch 'master' into features/rfc8914-ede --- 787d7a5952abad6e2a4a65cbeb44d4dc5d631d53 diff --cc daemon/worker.c index bd7567b34,5d2483cd2..5c05631ad --- a/daemon/worker.c +++ b/daemon/worker.c @@@ -485,8 -484,6 +484,8 @@@ answer_norec_from_cache(struct worker* msg->rep, LDNS_RCODE_SERVFAIL, edns, repinfo, worker->scratchpad, worker->env.now_tv)) return 0; - EDNS_OPT_APPEND_EDE(edns, worker->scratchpad, - LDNS_EDE_DNSSEC_BOGUS, ""); ++ EDNS_OPT_LIST_APPEND_EDE(&edns->opt_list_out, ++ worker->scratchpad, LDNS_EDE_DNSSEC_BOGUS, ""); error_encode(repinfo->c->buffer, LDNS_RCODE_SERVFAIL, &msg->qinfo, id, flags, edns); if(worker->stats.extended) { @@@ -502,8 -499,6 +501,9 @@@ secure = 1; break; case sec_status_indeterminate: - EDNS_OPT_APPEND_EDE(edns, worker->scratchpad, - LDNS_EDE_DNSSEC_INDETERMINATE, ""); ++ EDNS_OPT_LIST_APPEND_EDE(&edns->opt_list_out, ++ worker->scratchpad, LDNS_EDE_DNSSEC_INDETERMINATE, ""); ++ case sec_status_insecure: default: /* not secure */ @@@ -663,8 -654,6 +659,8 @@@ answer_from_cache(struct worker* worker LDNS_RCODE_SERVFAIL, edns, repinfo, worker->scratchpad, worker->env.now_tv)) goto bail_out; - EDNS_OPT_APPEND_EDE(edns, worker->scratchpad, - LDNS_EDE_DNSSEC_BOGUS, ""); ++ EDNS_OPT_LIST_APPEND_EDE(&edns->opt_list_out, ++ worker->scratchpad, LDNS_EDE_DNSSEC_BOGUS, ""); error_encode(repinfo->c->buffer, LDNS_RCODE_SERVFAIL, qinfo, id, flags, edns); rrset_array_unlock_touch(worker->env.rrset_cache, @@@ -1521,12 -1382,9 +1500,12 @@@ worker_handle_request(struct comm_point * ACLs allow the snooping. */ if(!(LDNS_RD_WIRE(sldns_buffer_begin(c->buffer))) && acl != acl_allow_snoop ) { + edns.opt_list = NULL; - EDNS_OPT_APPEND_EDE(&edns, worker->scratchpad, - LDNS_EDE_NOT_AUTHORITATIVE, ""); ++ EDNS_OPT_LIST_APPEND_EDE(&edns.opt_list_out, ++ worker->scratchpad, LDNS_EDE_NOT_AUTHORITATIVE, ""); error_encode(c->buffer, LDNS_RCODE_REFUSED, &qinfo, *(uint16_t*)(void *)sldns_buffer_begin(c->buffer), - sldns_buffer_read_u16_at(c->buffer, 2), NULL); + sldns_buffer_read_u16_at(c->buffer, 2), &edns); regional_free_all(worker->scratchpad); log_addr(VERB_ALGO, "refused nonrec (cache snoop) query from", &repinfo->addr, repinfo->addrlen); @@@ -1603,16 -1460,6 +1582,16 @@@ lookup_cache < *worker->env.now) leeway = 0; lock_rw_unlock(&e->lock); + + // // stale answer? + // if (worker->env.cfg->serve_expired && + // *worker->env.now >= ((struct reply_info*)e->data)->ttl) { + // // EDE Error Code 3 - Stale Answer - // EDNS_OPT_APPEND_EDE(&edns, worker->scratchpad, ++ // EDNS_OPT_LIST_APPEND_EDE(&edns.opt_list_out, worker->scratchpad, + // LDNS_EDE_STALE_ANSWER, ""); + // } + + // add EDNS struct? reply_and_prefetch(worker, lookup_qinfo, sldns_buffer_read_u16_at(c->buffer, 2), repinfo, leeway, diff --cc services/localzone.c index c6ed979fb,a69aef8fd..d74191f9a --- a/services/localzone.c +++ b/services/localzone.c @@@ -1281,48 -1286,6 +1286,48 @@@ local_encode(struct query_info* qinfo, return 1; } +/** encode answer consisting of 1 rrset (with EDE code) */ +static int +local_encode_ede(struct query_info* qinfo, struct module_env* env, + struct edns_data* edns, struct comm_reply* repinfo, sldns_buffer* buf, + struct regional* temp, struct ub_packed_rrset_key* rrset, int ansec, + int rcode, sldns_ede_code ede_code, const char* ede_txt) +{ + struct reply_info rep; + uint16_t udpsize; + /* make answer with time=0 for fixed TTL values */ + memset(&rep, 0, sizeof(rep)); + rep.flags = (uint16_t)((BIT_QR | BIT_AA | BIT_RA) | rcode); + rep.qdcount = 1; + if(ansec) + rep.an_numrrsets = 1; + else rep.ns_numrrsets = 1; + rep.rrset_count = 1; + rep.rrsets = &rrset; + udpsize = edns->udp_size; + edns->edns_version = EDNS_ADVERTISED_VERSION; + edns->udp_size = EDNS_ADVERTISED_SIZE; + edns->ext_rcode = 0; + edns->bits &= EDNS_DO; + if(!inplace_cb_reply_local_call(env, qinfo, NULL, &rep, rcode, edns, + repinfo, temp, env->now_tv)) { + error_encode(buf, (LDNS_RCODE_SERVFAIL|BIT_AA), qinfo, + *(uint16_t*)sldns_buffer_begin(buf), + sldns_buffer_read_u16_at(buf, 2), edns); + } else { - edns_opt_append_ede(edns, temp, ede_code, ede_txt); ++ edns_opt_list_append_ede(&edns->opt_list_out, temp, ede_code, ede_txt); + + if(!reply_info_answer_encode(qinfo, &rep, + *(uint16_t*)sldns_buffer_begin(buf), sldns_buffer_read_u16_at(buf, 2), + buf, 0, 0, temp, udpsize, edns, (int)(edns->bits&EDNS_DO), 0)) { + error_encode(buf, (LDNS_RCODE_SERVFAIL|BIT_AA), qinfo, + *(uint16_t*)sldns_buffer_begin(buf), + sldns_buffer_read_u16_at(buf, 2), edns); + } + } + return 1; +} + /** encode local error answer */ static void local_error_encode(struct query_info* qinfo, struct module_env* env, @@@ -1337,9 -1299,7 +1342,9 @@@ if(!inplace_cb_reply_local_call(env, qinfo, NULL, NULL, rcode, edns, repinfo, temp, env->now_tv)) - edns->opt_list = NULL; + edns->opt_list_inplace_cb_out = NULL; + if(ede_code >= 0 && env->cfg->local_data_do_ede) - edns_opt_append_ede(edns, temp, ede_code, ede_txt); ++ edns_opt_list_append_ede(&edns->opt_list_out, temp, ede_code, ede_txt); error_encode(buf, r, qinfo, *(uint16_t*)sldns_buffer_begin(buf), sldns_buffer_read_u16_at(buf, 2), edns); } @@@ -1651,13 -1618,15 +1667,15 @@@ local_zones_zone_answer(struct local_zo */ int rcode = (ld || lz_type == local_zone_redirect || lz_type == local_zone_inform_redirect || - lz_type == local_zone_always_nodata)? + lz_type == local_zone_always_nodata || + lz_type == local_zone_truncate)? LDNS_RCODE_NOERROR:LDNS_RCODE_NXDOMAIN; - if(z->soa && z->soa_negative) + rcode = (lz_type == local_zone_truncate ? (rcode|BIT_TC) : rcode); + if(z != NULL && z->soa && z->soa_negative) return local_encode(qinfo, env, edns, repinfo, buf, temp, z->soa_negative, 0, rcode); - local_error_encode(qinfo, env, edns, repinfo, buf, temp, rcode, - (rcode|BIT_AA)); + local_error_encode(qinfo, env, edns, repinfo, buf, temp, + rcode, (rcode|BIT_AA), LDNS_EDE_BLOCKED, ""); return 1; } else if(lz_type == local_zone_typetransparent || lz_type == local_zone_always_transparent) { @@@ -1711,12 -1679,11 +1729,12 @@@ * does not, then we should make this noerror/nodata */ if(ld && ld->rrsets) { int rcode = LDNS_RCODE_NOERROR; - if(z->soa && z->soa_negative) + if(z != NULL && z->soa && z->soa_negative) return local_encode(qinfo, env, edns, repinfo, buf, temp, z->soa_negative, 0, rcode); + /* NODATA: No EDE needed */ local_error_encode(qinfo, env, edns, repinfo, buf, temp, rcode, - (rcode|BIT_AA)); + (rcode|BIT_AA), -1, NULL); return 1; } diff --cc services/mesh.c index 4f1cb83d9,d2a1c6856..fae8bee78 --- a/services/mesh.c +++ b/services/mesh.c @@@ -1269,24 -1288,8 +1288,24 @@@ mesh_send_reply(struct mesh_state* m, i } else { if(!inplace_cb_reply_call(m->s.env, &m->s.qinfo, &m->s, rep, rcode, &r->edns, &r->query_reply, m->s.region, &r->start_time)) - r->edns.opt_list = NULL; + r->edns.opt_list_inplace_cb_out = NULL; } + /* Send along EDE BOGUS EDNS0 option when answer is bogus */ + if(rcode == LDNS_RCODE_SERVFAIL && + m->s.env->need_to_validate && (!(r->qflags&BIT_CD) || + m->s.env->cfg->ignore_cd) && rep && + (rep->security <= sec_status_bogus || + rep->security == sec_status_secure_sentinel_fail)) { + + char *reason = m->s.env->cfg->val_log_level >= 2 + ? errinf_to_str_bogus(&m->s) : NULL; + sldns_ede_code reason_bogus = rep->reason_bogus != LDNS_EDE_DNSSEC_BOGUS + ? rep->reason_bogus : errinf_to_reason_bogus(&m->s); + - edns_opt_append_ede(&r->edns, m->s.region, ++ edns_opt_list_append_ede(&r->edns.opt_list_out, m->s.region, + reason_bogus, reason); + free(reason); + } error_encode(r_buffer, rcode, &m->s.qinfo, r->qid, r->qflags, &r->edns); m->reply_list = NULL; @@@ -1312,8 -1312,7 +1328,8 @@@ { if(!inplace_cb_reply_servfail_call(m->s.env, &m->s.qinfo, &m->s, rep, LDNS_RCODE_SERVFAIL, &r->edns, &r->query_reply, m->s.region, &r->start_time)) - r->edns.opt_list = NULL; + r->edns.opt_list_inplace_cb_out = NULL; + // @TODO EDE? error_encode(r_buffer, LDNS_RCODE_SERVFAIL, &m->s.qinfo, r->qid, r->qflags, &r->edns); } diff --cc util/data/msgparse.h index 981f53d46,4c0559a73..860e8ff05 --- a/util/data/msgparse.h +++ b/util/data/msgparse.h @@@ -281,17 -290,9 +290,17 @@@ int parse_packet(struct sldns_buffer* p * @return: 0 on success. or an RCODE on an error. * RCODE formerr if OPT in wrong section, and so on. */ - int parse_extract_edns(struct msg_parse* msg, struct edns_data* edns, - struct regional* region); + int parse_extract_edns_from_response_msg(struct msg_parse* msg, + struct edns_data* edns, struct regional* region); +/** + * Skip RRs from packet + * @param pkt:the packet. position at start must be right after the query + * section. At end, right after EDNS data or no movement if failed. + * @param num: Limit of the number of records we want to parse. + * @return: 0 on success, 1 on failure*/ +int skip_pkt_rrs(struct sldns_buffer* pkt, int num); + /** * If EDNS data follows a query section, extract it and initialize edns struct. * @param pkt: the packet. position at start must be right after the query diff --cc util/data/msgreply.c index 0947a495c,ec46e4724..69427d455 --- a/util/data/msgreply.c +++ b/util/data/msgreply.c @@@ -960,63 -989,6 +990,35 @@@ parse_reply_in_temp_region(sldns_buffer return rep; } - int edns_opt_append(struct edns_data* edns, struct regional* region, - uint16_t code, size_t len, uint8_t* data) - { - struct edns_option** prevp; - struct edns_option* opt; - - /* allocate new element */ - opt = (struct edns_option*)regional_alloc(region, sizeof(*opt)); - if(!opt) - return 0; - opt->next = NULL; - opt->opt_code = code; - opt->opt_len = len; - opt->opt_data = NULL; - if(len > 0) { - opt->opt_data = regional_alloc_init(region, data, len); - if(!opt->opt_data) - return 0; - } - - /* append at end of list */ - prevp = &edns->opt_list; - while(*prevp != NULL) - prevp = &((*prevp)->next); - *prevp = opt; - return 1; - } - - int edns_opt_append_ede(struct edns_data* edns, struct regional* region, ++int edns_opt_list_append_ede(struct edns_option** list, struct regional* region, + sldns_ede_code code, const char *txt) +{ + struct edns_option** prevp; + struct edns_option* opt; + size_t txt_len = txt ? strlen(txt) : 0; + + /* allocate new element */ + opt = (struct edns_option*)regional_alloc(region, sizeof(*opt)); + if(!opt) + return 0; + opt->next = NULL; + opt->opt_code = LDNS_EDNS_EDE; + opt->opt_len = txt_len + sizeof(uint16_t); + opt->opt_data = regional_alloc(region, txt_len + sizeof(uint16_t)); + if(!opt->opt_data) + return 0; + sldns_write_uint16(opt->opt_data, (uint16_t)code); + if (txt_len) + memmove(opt->opt_data + 2, txt, txt_len); + + /* append at end of list */ - prevp = &edns->opt_list; ++ prevp = list; + while(*prevp != NULL) + prevp = &((*prevp)->next); + *prevp = opt; + return 1; +} + int edns_opt_list_append(struct edns_option** list, uint16_t code, size_t len, uint8_t* data, struct regional* region) { diff --cc util/data/msgreply.h index 1fbcbac45,81c763fc7..88e37f5b3 --- a/util/data/msgreply.h +++ b/util/data/msgreply.h @@@ -516,52 -524,12 +530,41 @@@ void log_query_info(enum verbosity_valu * @param code: the edns option's code. * @param len: the edns option's length. * @param data: the edns option's data. + * @param region: region to allocate the new edns option. * @return false on failure. */ - int edns_opt_append(struct edns_data* edns, struct regional* region, - uint16_t code, size_t len, uint8_t* data); + int edns_opt_list_append(struct edns_option** list, uint16_t code, size_t len, + uint8_t* data, struct regional* region); +/** + * Append edns EDE option to edns options list - * @param EDNS: the edns data structure to append the edns option to. ++ * @param LIST: the edns option list to append the edns option to. + * @param REGION: region to allocate the new edns option. + * @param CODE: the EDE code. + * @param TXT: Additional text for the option + */ - #define EDNS_OPT_APPEND_EDE(EDNS, REGION, CODE, TXT) \ ++#define EDNS_OPT_LIST_APPEND_EDE(LIST, REGION, CODE, TXT) \ + do { \ + struct { \ + uint16_t code; \ + char text[sizeof(TXT) - 1]; \ + } ede = { htons(CODE), TXT }; \ - edns_opt_append((EDNS), (REGION), LDNS_EDNS_EDE, \ ++ edns_opt_list_append((LIST), (REGION), LDNS_EDNS_EDE, \ + sizeof(uint16_t) + sizeof(TXT) - 1, \ + (void *)&ede); \ + } while(0) + +/** + * Append edns EDE option to edns options list - * @param edns: the edns data structure to append the edns option to. ++ * @param list: the edns option list to append the edns option to. + * @param region: region to allocate the new edns option. + * @param code: the EDE code. + * @param txt: Additional text for the option + * @return false on failure. + */ - int edns_opt_append_ede(struct edns_data* edns, struct regional* region, ++int edns_opt_append_ede(struct edns_option* list, struct regional* region, + sldns_ede_code code, const char *txt); + - /** - * Append edns option to edns option list - * @param list: the edns option list to append the edns option to. - * @param code: the edns option's code. - * @param len: the edns option's length. - * @param data: the edns option's data. - * @param region: region to allocate the new edns option. - * @return false on failure. - */ - int edns_opt_list_append(struct edns_option** list, uint16_t code, size_t len, - uint8_t* data, struct regional* region); - /** * Remove any option found on the edns option list that matches the code. * @param list: the list of edns options.