From: Tom Carpay Date: Mon, 1 Nov 2021 12:48:40 +0000 (+0000) Subject: split edns_data.opt_list in opt_list_in and opt_list_out X-Git-Tag: release-1.14.0rc1~27^2~10 X-Git-Url: http://git.ipfire.org/?a=commitdiff_plain;h=89d747653902798af8703e0723ebf6d44aa53e7d;p=thirdparty%2Funbound.git split edns_data.opt_list in opt_list_in and opt_list_out opt_list_in for parsed (incoming) edns options, and opt_list_out for outgoing (to be encoded) edns options --- diff --git a/daemon/worker.c b/daemon/worker.c index 7965a1881..abfb84fbe 100644 --- a/daemon/worker.c +++ b/daemon/worker.c @@ -1003,7 +1003,8 @@ answer_notify(struct worker* w, struct query_info* qinfo, edns->udp_size = EDNS_ADVERTISED_SIZE; edns->ext_rcode = 0; edns->bits &= EDNS_DO; - edns->opt_list = NULL; + edns->opt_list_in = NULL; + edns->opt_list_out = NULL; edns->opt_list_modules_out = NULL; error_encode(pkt, rcode, qinfo, *(uint16_t*)(void *)sldns_buffer_begin(pkt), @@ -1262,7 +1263,8 @@ worker_handle_request(struct comm_point* c, void* arg, int error, edns.edns_version = EDNS_ADVERTISED_VERSION; edns.udp_size = EDNS_ADVERTISED_SIZE; edns.bits &= EDNS_DO; - edns.opt_list = NULL; + edns.opt_list_in = NULL; + edns.opt_list_out = NULL; edns.opt_list_modules_out = NULL; edns.padding_block_size = 0; verbose(VERB_ALGO, "query with bad edns version."); @@ -1284,13 +1286,15 @@ worker_handle_request(struct comm_point* c, void* arg, int error, edns.udp_size = NORMAL_UDP_SIZE; } if(c->type != comm_udp) { - edns_opt = edns_opt_list_find(edns.opt_list, LDNS_EDNS_KEEPALIVE); + /* @TODO reuse what we found at parse time */ + edns_opt = edns_opt_list_find(edns.opt_list_in, LDNS_EDNS_KEEPALIVE); if(edns_opt && edns_opt->opt_len > 0) { edns.ext_rcode = 0; edns.edns_version = EDNS_ADVERTISED_VERSION; edns.udp_size = EDNS_ADVERTISED_SIZE; edns.bits &= EDNS_DO; - edns.opt_list = NULL; + edns.opt_list_in = NULL; + edns.opt_list_out = NULL; edns.opt_list_modules_out = NULL; verbose(VERB_ALGO, "query with bad edns keepalive."); log_addr(VERB_CLIENT,"from",&repinfo->addr, repinfo->addrlen); @@ -1455,7 +1459,7 @@ lookup_cache: * this is a two-pass operation, and lookup_qinfo is different for * each pass. We should still pass the original qinfo to * answer_from_cache(), however, since it's used to build the reply. */ - if(!edns_bypass_cache_stage(edns.opt_list, &worker->env)) { + if(!edns_bypass_cache_stage(edns.opt_list_in, &worker->env)) { is_expired_answer = 0; is_secure_answer = 0; h = query_info_hash(lookup_qinfo, sldns_buffer_read_u16_at(c->buffer, 2)); diff --git a/iterator/iterator.c b/iterator/iterator.c index 45e9f7bf4..64a0602d5 100644 --- a/iterator/iterator.c +++ b/iterator/iterator.c @@ -3859,8 +3859,8 @@ process_response(struct module_qstate* qstate, struct iter_qstate* iq, } /* Copy the edns options we may got from the back end */ - if(edns.opt_list) { - qstate->edns_opts_back_in = edns_opt_copy_region(edns.opt_list, + if(edns.opt_list_in) { + qstate->edns_opts_back_in = edns_opt_copy_region(edns.opt_list_in, qstate->region); if(!qstate->edns_opts_back_in) { log_err("out of memory on incoming message"); diff --git a/libunbound/libworker.c b/libunbound/libworker.c index c4ed660f3..b43bd9604 100644 --- a/libunbound/libworker.c +++ b/libunbound/libworker.c @@ -600,7 +600,8 @@ setup_qinfo_edns(struct libworker* w, struct ctx_query* q, edns->ext_rcode = 0; edns->edns_version = 0; edns->bits = EDNS_DO; - edns->opt_list = NULL; + edns->opt_list_in = NULL; + edns->opt_list_out = NULL; edns->opt_list_modules_out = NULL; edns->padding_block_size = 0; if(sldns_buffer_capacity(w->back->udp_buff) < 65535) diff --git a/services/authzone.c b/services/authzone.c index 58056a13b..d59573881 100644 --- a/services/authzone.c +++ b/services/authzone.c @@ -5358,7 +5358,8 @@ xfr_transfer_lookup_host(struct auth_xfer* xfr, struct module_env* env) edns.ext_rcode = 0; edns.edns_version = 0; edns.bits = EDNS_DO; - edns.opt_list = NULL; + edns.opt_list_in = NULL; + edns.opt_list_out = NULL; edns.opt_list_modules_out = NULL; edns.padding_block_size = 0; if(sldns_buffer_capacity(buf) < 65535) @@ -6548,7 +6549,8 @@ xfr_probe_lookup_host(struct auth_xfer* xfr, struct module_env* env) edns.ext_rcode = 0; edns.edns_version = 0; edns.bits = EDNS_DO; - edns.opt_list = NULL; + edns.opt_list_in = NULL; + edns.opt_list_out = NULL; edns.opt_list_modules_out = NULL; edns.padding_block_size = 0; if(sldns_buffer_capacity(buf) < 65535) @@ -8324,7 +8326,8 @@ zonemd_lookup_dnskey(struct auth_zone* z, struct module_env* env) edns.ext_rcode = 0; edns.edns_version = 0; edns.bits = EDNS_DO; - edns.opt_list = NULL; + edns.opt_list_in = NULL; + edns.opt_list_out = NULL; edns.opt_list_modules_out = NULL; if(sldns_buffer_capacity(buf) < 65535) edns.udp_size = (uint16_t)sldns_buffer_capacity(buf); diff --git a/services/mesh.c b/services/mesh.c index df99f891c..0bfa152ee 100644 --- a/services/mesh.c +++ b/services/mesh.c @@ -461,7 +461,7 @@ void mesh_new_client(struct mesh_area* mesh, struct query_info* qinfo, struct edns_data* edns, struct comm_reply* rep, uint16_t qid) { struct mesh_state* s = NULL; - int unique = unique_mesh_state(edns->opt_list, mesh->env); + int unique = unique_mesh_state(edns->opt_list_in, mesh->env); int was_detached = 0; int was_noreply = 0; int added = 0; @@ -514,8 +514,8 @@ void mesh_new_client(struct mesh_area* mesh, struct query_info* qinfo, if(unique) mesh_state_make_unique(s); /* copy the edns options we got from the front */ - if(edns->opt_list) { - s->s.edns_opts_front_in = edns_opt_copy_region(edns->opt_list, + if(edns->opt_list_in) { + s->s.edns_opts_front_in = edns_opt_copy_region(edns->opt_list_in, s->s.region); if(!s->s.edns_opts_front_in) { log_err("mesh_state_create: out of memory; SERVFAIL"); @@ -609,7 +609,7 @@ mesh_new_callback(struct mesh_area* mesh, struct query_info* qinfo, uint16_t qid, mesh_cb_func_type cb, void* cb_arg) { struct mesh_state* s = NULL; - int unique = unique_mesh_state(edns->opt_list, mesh->env); + int unique = unique_mesh_state(edns->opt_list_in, mesh->env); int timeout = mesh->env->cfg->serve_expired? mesh->env->cfg->serve_expired_client_timeout:0; int was_detached = 0; @@ -632,8 +632,8 @@ mesh_new_callback(struct mesh_area* mesh, struct query_info* qinfo, } if(unique) mesh_state_make_unique(s); - if(edns->opt_list) { - s->s.edns_opts_front_in = edns_opt_copy_region(edns->opt_list, + if(edns->opt_list_in) { + s->s.edns_opts_front_in = edns_opt_copy_region(edns->opt_list_in, s->s.region); if(!s->s.edns_opts_front_in) { return 0; @@ -1266,8 +1266,9 @@ mesh_send_reply(struct mesh_state* m, int rcode, struct reply_info* rep, prev->edns.edns_present == r->edns.edns_present && prev->edns.bits == r->edns.bits && prev->edns.udp_size == r->edns.udp_size && - edns_opt_list_compare(prev->edns.opt_list, r->edns.opt_list) - == 0) { + edns_opt_list_compare(prev->edns.opt_list_out, r->edns.opt_list_out) == 0 && + edns_opt_list_compare(prev->edns.opt_list_modules_out, r->edns.opt_list_modules_out) == 0 + ) { /* if the previous reply is identical to this one, fix ID */ if(prev_buffer != r_buffer) sldns_buffer_copy(r_buffer, prev_buffer); @@ -1502,10 +1503,18 @@ int mesh_state_add_cb(struct mesh_state* s, struct edns_data* edns, r->cb = cb; r->cb_arg = cb_arg; r->edns = *edns; - if(edns->opt_list) { - r->edns.opt_list = edns_opt_copy_region(edns->opt_list, + if(edns->opt_list_in || edns->opt_list_out || edns->opt_list_modules_out) { + r->edns.opt_list_in = edns_opt_copy_region(edns->opt_list_in, s->s.region); - if(!r->edns.opt_list) + if(!r->edns.opt_list_in) + return 0; + r->edns.opt_list_out = edns_opt_copy_region(edns->opt_list_out, + s->s.region); + if(!r->edns.opt_list_out) + return 0; + r->edns.opt_list_modules_out = edns_opt_copy_region(edns->opt_list_modules_out, + s->s.region); + if(!r->edns.opt_list_modules_out) return 0; } r->qid = qid; @@ -1526,10 +1535,18 @@ int mesh_state_add_reply(struct mesh_state* s, struct edns_data* edns, return 0; r->query_reply = *rep; r->edns = *edns; - if(edns->opt_list) { - r->edns.opt_list = edns_opt_copy_region(edns->opt_list, + if(edns->opt_list_in || edns->opt_list_out || edns->opt_list_modules_out) { + r->edns.opt_list_in = edns_opt_copy_region(edns->opt_list_in, + s->s.region); + if(!r->edns.opt_list_in) + return 0; + r->edns.opt_list_out = edns_opt_copy_region(edns->opt_list_out, + s->s.region); + if(!r->edns.opt_list_out) + return 0; + r->edns.opt_list_modules_out = edns_opt_copy_region(edns->opt_list_modules_out, s->s.region); - if(!r->edns.opt_list) + if(!r->edns.opt_list_modules_out) return 0; } r->qid = qid; diff --git a/services/outside_network.c b/services/outside_network.c index 666e46f98..d5443ad44 100644 --- a/services/outside_network.c +++ b/services/outside_network.c @@ -2709,7 +2709,9 @@ serviced_encode(struct serviced_query* sq, sldns_buffer* buff, int with_edns) edns.edns_present = 1; edns.ext_rcode = 0; edns.edns_version = EDNS_ADVERTISED_VERSION; - edns.opt_list = sq->opt_list; + edns.opt_list_in = NULL; + edns.opt_list_out = sq->opt_list; + edns.opt_list_modules_out = NULL; if(sq->status == serviced_query_UDP_EDNS_FRAG) { if(addr_is_ip6(&sq->addr, sq->addrlen)) { if(EDNS_FRAG_SIZE_IP6 < EDNS_ADVERTISED_SIZE) @@ -2732,8 +2734,8 @@ serviced_encode(struct serviced_query* sq, sldns_buffer* buff, int with_edns) padding_option.opt_code = LDNS_EDNS_PADDING; padding_option.opt_len = 0; padding_option.opt_data = NULL; - padding_option.next = edns.opt_list; - edns.opt_list = &padding_option; + padding_option.next = edns.opt_list_out; + edns.opt_list_out = &padding_option; edns.padding_block_size = sq->padding_block_size; } attach_edns_record(buff, &edns); diff --git a/testcode/fake_event.c b/testcode/fake_event.c index 5f81b9eb8..6b0fed2f4 100644 --- a/testcode/fake_event.c +++ b/testcode/fake_event.c @@ -1244,7 +1244,9 @@ struct serviced_query* outnet_serviced_query(struct outside_network* outnet, client_string_addr->string_len, client_string_addr->string, qstate->region); } - edns.opt_list = qstate->edns_opts_back_out; + edns.opt_list_in = NULL; + edns.opt_list_out = qstate->edns_opts_back_out; + edns.opt_list_modules_out = NULL; attach_edns_record(pend->buffer, &edns); } memcpy(&pend->addr, addr, addrlen); diff --git a/util/data/msgencode.c b/util/data/msgencode.c index 5f297b551..05c0d1a99 100644 --- a/util/data/msgencode.c +++ b/util/data/msgencode.c @@ -796,7 +796,10 @@ calc_edns_field_size(struct edns_data* edns) struct edns_option* opt; if(!edns || !edns->edns_present) return 0; - for(opt = edns->opt_list; opt; opt = opt->next) { + for(opt = edns->opt_list_modules_out; opt; opt = opt->next) { + rdatalen += 4 + opt->opt_len; + } + for(opt = edns->opt_list_out; opt; opt = opt->next) { rdatalen += 4 + opt->opt_len; } /* domain root '.' + type + class + ttl + rdatalen */ @@ -827,7 +830,13 @@ attach_edns_record_max_msg_sz(sldns_buffer* pkt, struct edns_data* edns, rdatapos = sldns_buffer_position(pkt); sldns_buffer_write_u16(pkt, 0); /* rdatalen */ /* write rdata */ - for(opt=edns->opt_list; opt; opt=opt->next) { + for(opt=edns->opt_list_modules_out; opt; opt=opt->next) { + sldns_buffer_write_u16(pkt, opt->opt_code); + sldns_buffer_write_u16(pkt, opt->opt_len); + if(opt->opt_len != 0) + sldns_buffer_write(pkt, opt->opt_data, opt->opt_len); + } + for(opt=edns->opt_list_out; opt; opt=opt->next) { if (opt->opt_code == LDNS_EDNS_PADDING) { padding_option = opt; continue; @@ -860,8 +869,7 @@ attach_edns_record_max_msg_sz(sldns_buffer* pkt, struct edns_data* edns, sldns_buffer_skip(pkt, pad_sz); } } - if(edns->opt_list) - sldns_buffer_write_u16_at(pkt, rdatapos, + sldns_buffer_write_u16_at(pkt, rdatapos, sldns_buffer_position(pkt)-rdatapos-2); sldns_buffer_flip(pkt); } diff --git a/util/data/msgparse.c b/util/data/msgparse.c index fb50c9165..b3ff35341 100644 --- a/util/data/msgparse.c +++ b/util/data/msgparse.c @@ -952,8 +952,8 @@ parse_edns_options(uint8_t* rdata_ptr, size_t rdata_len, rdata_len -= 4; if(opt_len > rdata_len) break; /* option code partial */ - if(!edns_opt_append(edns, region, opt_code, opt_len, - rdata_ptr)) { + if(!edns_opt_list_append(&edns->opt_list_in, opt_code, opt_len, + rdata_ptr, region)) { log_err("out of memory"); return 0; } @@ -1019,7 +1019,8 @@ parse_extract_edns(struct msg_parse* msg, struct edns_data* edns, edns->edns_version = found->rr_last->ttl_data[1]; edns->bits = sldns_read_uint16(&found->rr_last->ttl_data[2]); edns->udp_size = ntohs(found->rrset_class); - edns->opt_list = NULL; + edns->opt_list_in = NULL; + edns->opt_list_out = NULL; edns->opt_list_modules_out = NULL; edns->padding_block_size = 0; @@ -1094,7 +1095,8 @@ parse_edns_from_pkt(sldns_buffer* pkt, struct edns_data* edns, edns->ext_rcode = sldns_buffer_read_u8(pkt); /* ttl used for bits */ edns->edns_version = sldns_buffer_read_u8(pkt); edns->bits = sldns_buffer_read_u16(pkt); - edns->opt_list = NULL; + edns->opt_list_in = NULL; + edns->opt_list_out = NULL; edns->opt_list_modules_out = NULL; edns->padding_block_size = 0; diff --git a/util/data/msgparse.h b/util/data/msgparse.h index 434a5b0b8..4bb82cc3c 100644 --- a/util/data/msgparse.h +++ b/util/data/msgparse.h @@ -225,8 +225,12 @@ struct edns_data { uint16_t bits; /** UDP reassembly size. */ uint16_t udp_size; - /** rdata element list, or NULL if none */ - struct edns_option* opt_list; + /** rdata element list of options of an incoming packet created at + * parse time, or NULL if none */ + struct edns_option* opt_list_in; + /** rdata element list of options to encode for outgoing packets, + * or NULL if none */ + struct edns_option* opt_list_out; /** rdata element list of outgoing edns options from modules * or NULL if none */ struct edns_option* opt_list_modules_out; diff --git a/util/data/msgreply.c b/util/data/msgreply.c index 67a47a7b3..1d5a1f214 100644 --- a/util/data/msgreply.c +++ b/util/data/msgreply.c @@ -989,34 +989,6 @@ parse_reply_in_temp_region(sldns_buffer* pkt, struct regional* region, 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_list_append(struct edns_option** list, uint16_t code, size_t len, uint8_t* data, struct regional* region) { diff --git a/util/data/msgreply.h b/util/data/msgreply.h index 5a30a1d77..81c763fc7 100644 --- a/util/data/msgreply.h +++ b/util/data/msgreply.h @@ -518,18 +518,6 @@ void log_reply_info(enum verbosity_value v, struct query_info *qinf, void log_query_info(enum verbosity_value v, const char* str, struct query_info* qinf); -/** - * Append edns option to edns data structure - * @param edns: the edns data structure to append the edns option to. - * @param region: region to allocate the new edns option. - * @param code: the edns option's code. - * @param len: the edns option's length. - * @param data: the edns option's data. - * @return false on failure. - */ -int edns_opt_append(struct edns_data* edns, struct regional* region, - uint16_t code, size_t len, uint8_t* data); - /** * Append edns option to edns option list * @param list: the edns option list to append the edns option to. diff --git a/util/edns.c b/util/edns.c index 84308449c..2081cd1e6 100644 --- a/util/edns.c +++ b/util/edns.c @@ -140,12 +140,12 @@ static int edns_keepalive(struct edns_data* edns_out, struct edns_data* edns_in, * sent on that connection will have a TCP Keepalive option. */ if(c->tcp_keepalive || - edns_opt_list_find(edns_in->opt_list, LDNS_EDNS_KEEPALIVE)) { + edns_opt_list_find(edns_in->opt_list_in, LDNS_EDNS_KEEPALIVE)) { int keepalive = c->tcp_timeout_msec / 100; uint8_t data[2]; data[0] = (uint8_t)((keepalive >> 8) & 0xff); data[1] = (uint8_t)(keepalive & 0xff); - if(!edns_opt_list_append(&edns_out->opt_list, LDNS_EDNS_KEEPALIVE, + if(!edns_opt_list_append(&edns_out->opt_list_out, LDNS_EDNS_KEEPALIVE, sizeof(data), data, region)) return 0; c->tcp_keepalive = 1; @@ -160,17 +160,17 @@ int apply_edns_options(struct edns_data* edns_out, struct edns_data* edns_in, !edns_keepalive(edns_out, edns_in, c, region)) return 0; - if (cfg->nsid && edns_opt_list_find(edns_in->opt_list, LDNS_EDNS_NSID) - && !edns_opt_list_append(&edns_out->opt_list, + if (cfg->nsid && edns_opt_list_find(edns_in->opt_list_in, LDNS_EDNS_NSID) + && !edns_opt_list_append(&edns_out->opt_list_out, LDNS_EDNS_NSID, cfg->nsid_len, cfg->nsid, region)) return 0; if(!cfg->pad_responses || c->type != comm_tcp || !c->ssl - || !edns_opt_list_find(edns_in->opt_list, LDNS_EDNS_PADDING)) { + || !edns_opt_list_find(edns_in->opt_list_in, LDNS_EDNS_PADDING)) { ; /* pass */ } - else if(!edns_opt_list_append(&edns_out->opt_list, LDNS_EDNS_PADDING + else if(!edns_opt_list_append(&edns_out->opt_list_out, LDNS_EDNS_PADDING , 0, NULL, region)) return 0; else diff --git a/validator/autotrust.c b/validator/autotrust.c index 080385e93..f26bfdb44 100644 --- a/validator/autotrust.c +++ b/validator/autotrust.c @@ -2377,7 +2377,8 @@ probe_anchor(struct module_env* env, struct trust_anchor* tp) edns.ext_rcode = 0; edns.edns_version = 0; edns.bits = EDNS_DO; - edns.opt_list = NULL; + edns.opt_list_in = NULL; + edns.opt_list_out = NULL; edns.opt_list_modules_out = NULL; edns.padding_block_size = 0; if(sldns_buffer_capacity(buf) < 65535)