]> git.ipfire.org Git - thirdparty/unbound.git/commitdiff
split edns_data.opt_list in opt_list_in and opt_list_out
authorTom Carpay <tom@nlnetlabs.nl>
Mon, 1 Nov 2021 12:48:40 +0000 (12:48 +0000)
committerTom Carpay <tom@nlnetlabs.nl>
Mon, 1 Nov 2021 12:48:40 +0000 (12:48 +0000)
opt_list_in for parsed (incoming) edns options, and
opt_list_out for outgoing (to be encoded) edns options

14 files changed:
daemon/worker.c
iterator/iterator.c
libunbound/libworker.c
services/authzone.c
services/mesh.c
services/outside_network.c
testcode/fake_event.c
util/data/msgencode.c
util/data/msgparse.c
util/data/msgparse.h
util/data/msgreply.c
util/data/msgreply.h
util/edns.c
validator/autotrust.c

index 7965a188126fec3d7e216e4475bfb1a30eb781d2..abfb84fbeaf3f4d744e6207efe1241c85e5b280b 100644 (file)
@@ -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));
index 45e9f7bf424c3b59c063aecf4e8cff0ae06dc3a3..64a0602d5181a4f3ed4cf95eaac48fb6fe1676fe 100644 (file)
@@ -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");
index c4ed660f3d546be2b802ea0ac1dbc918a52d73a3..b43bd960472f9e61dbae25971007066b2b8beb0d 100644 (file)
@@ -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)
index 58056a13bd09b7eb5ef055a9f1577ef2bda71b4f..d59573881b08147c0b3fab79ad38822d32dd48a5 100644 (file)
@@ -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);
index df99f891c1385d2fa3c4b2916497215543871fca..0bfa152ee7c655a3fbf887861e232d230c961897 100644 (file)
@@ -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;
index 666e46f989c68bf24602f1f054ee5643991298ce..d5443ad44c24d5f55c1292a7a2451d03a933009e 100644 (file)
@@ -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);
index 5f81b9eb808cf8706752b601f559fe163ac62220..6b0fed2f41cd4ba58f503cd6494d2f1141aad931 100644 (file)
@@ -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);
index 5f297b551bfb179b9dd61a4113b3fa93cfec0d09..05c0d1a99b245b5cbf0308d04c075c0fcb8ff784 100644 (file)
@@ -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);
 }
index fb50c916555c30b8c1d3e095b8b5aa80ab4a6991..b3ff353411ae4440980624433b8e4be29cbc5423 100644 (file)
@@ -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;
 
index 434a5b0b8f6d63b0b17410058778077474db8fd8..4bb82cc3cc56ef44a9370ebd4f95b2edc1a85c25 100644 (file)
@@ -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;
index 67a47a7b373b09de41f48f1900d1fc97f43e5c88..1d5a1f214f9d951cf000db1fd5675e7eb5afec8a 100644 (file)
@@ -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)
 {
index 5a30a1d77d8b86f64d708e1cf424cafe4873dee2..81c763fc7c3a247f04a5519594581e09ec175c4f 100644 (file)
@@ -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.
index 84308449c7f3efa68dd346823460875a60f11af9..2081cd1e63f1eb063711abed8270645f91939785 100644 (file)
@@ -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
index 080385e937f8362ef15358d7b46baafdcbf86f2e..f26bfdb44ee3ce73c19e3f75fab79266104eebbc 100644 (file)
@@ -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)