]> git.ipfire.org Git - thirdparty/unbound.git/commitdiff
Move option handling to parse-time
authorTom Carpay <tom@nlnetlabs.nl>
Mon, 1 Nov 2021 13:48:31 +0000 (13:48 +0000)
committerTom Carpay <tom@nlnetlabs.nl>
Mon, 1 Nov 2021 13:48:31 +0000 (13:48 +0000)
daemon/worker.c
services/mesh.c
util/data/msgparse.c
util/data/msgparse.h
util/edns.c
util/edns.h

index abfb84fbeaf3f4d744e6207efe1241c85e5b280b..67b2e3166cc25cf27468a62508c29a01fae8d2d2 100644 (file)
@@ -1242,7 +1242,8 @@ worker_handle_request(struct comm_point* c, void* arg, int error,
                }
                goto send_reply;
        }
-       if((ret=parse_edns_from_pkt(c->buffer, &edns, worker->scratchpad)) != 0) {
+       if((ret=parse_edns_from_pkt(c->buffer, &edns, worker->env.cfg, c,
+                                       worker->scratchpad)) != 0) {
                struct edns_data reply_edns;
                verbose(VERB_ALGO, "worker parse edns: formerror.");
                log_addr(VERB_CLIENT,"from",&repinfo->addr, repinfo->addrlen);
index 0bfa152ee7c655a3fbf887861e232d230c961897..e91c28485b22bd03f653722bff1f6a0af346f22c 100644 (file)
@@ -1503,20 +1503,15 @@ 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_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_modules_out)
-                       return 0;
-       }
+       if(edns->opt_list_in && !(r->edns.opt_list_in =
+                       edns_opt_copy_region(edns->opt_list_in, s->s.region)))
+               return 0;
+       if(edns->opt_list_out && !(r->edns.opt_list_out =
+                       edns_opt_copy_region(edns->opt_list_out, s->s.region)))
+               return 0;
+       if(edns->opt_list_modules_out && !(r->edns.opt_list_modules_out =
+                       edns_opt_copy_region(edns->opt_list_modules_out, s->s.region)))
+               return 0;
        r->qid = qid;
        r->qflags = qflags;
        r->next = s->cb_list;
@@ -1535,20 +1530,15 @@ 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_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_modules_out)
-                       return 0;
-       }
+       if(edns->opt_list_in && !(r->edns.opt_list_in =
+                       edns_opt_copy_region(edns->opt_list_in, s->s.region)))
+               return 0;
+       if(edns->opt_list_out && !(r->edns.opt_list_out =
+                       edns_opt_copy_region(edns->opt_list_out, s->s.region)))
+               return 0;
+       if(edns->opt_list_modules_out && !(r->edns.opt_list_modules_out =
+                       edns_opt_copy_region(edns->opt_list_modules_out, s->s.region)))
+               return 0;
        r->qid = qid;
        r->qflags = qflags;
        r->start_time = *s->s.env->now_tv;
index b3ff353411ae4440980624433b8e4be29cbc5423..1fc7f2d55fc96be3d87188bd0ae76d45cac745eb 100644 (file)
  * Routines for message parsing a packet buffer to a descriptive structure.
  */
 #include "config.h"
+#include "util/config_file.h"
 #include "util/data/msgparse.h"
 #include "util/data/msgreply.h"
 #include "util/data/dname.h"
 #include "util/data/packed_rrset.h"
+#include "util/netevent.h"
 #include "util/storage/lookup3.h"
 #include "util/regional.h"
 #include "sldns/rrdef.h"
@@ -941,8 +943,12 @@ parse_packet(sldns_buffer* pkt, struct msg_parse* msg, struct regional* region)
 /** parse EDNS options from EDNS wireformat rdata */
 static int
 parse_edns_options(uint8_t* rdata_ptr, size_t rdata_len,
-       struct edns_data* edns, struct regional* region)
+       struct edns_data* edns, struct config_file* cfg, struct comm_point* c,
+       struct regional* region)
 {
+       int keepalive;
+       uint8_t data[2]; /* For keepalive value */
+
        /* while still more options, and have code+len to read */
        /* ignores partial content (i.e. rdata len 3) */
        while(rdata_len >= 4) {
@@ -952,10 +958,61 @@ 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_list_append(&edns->opt_list_in, opt_code, opt_len,
-                                       rdata_ptr, region)) {
-                       log_err("out of memory");
-                       return 0;
+
+               /* handle parse time edns options here */
+               switch(opt_code) {
+               case LDNS_EDNS_NSID:
+                       if (!cfg->nsid)
+                               break;
+                       if(!edns_opt_list_append(&edns->opt_list_out,
+                                               LDNS_EDNS_NSID, cfg->nsid_len,
+                                               cfg->nsid, region)) {
+                               log_err("out of memory");
+                               return 0;
+                       }
+                       break;
+
+               case LDNS_EDNS_KEEPALIVE:
+                       /* To respond with a Keepalive option, the client
+                        * connection must have received one message with a TCP
+                        * Keepalive EDNS option, and that option must have 0
+                        * length data. Subsequent messages sent on that
+                        * connection will have a TCP Keepalive option.
+                        */
+                       if (!cfg->do_tcp_keepalive || c->type != comm_udp ||
+                                       !c->tcp_keepalive)
+                               break;
+                       keepalive = c->tcp_timeout_msec / 100;
+                       data[0] = (uint8_t)((keepalive >> 8) & 0xff);
+                       data[1] = (uint8_t)(keepalive & 0xff);
+                       if(!edns_opt_list_append(&edns->opt_list_out,
+                                               LDNS_EDNS_KEEPALIVE,
+                                               sizeof(data), data, region)) {
+                               log_err("out of memory");
+                               return 0;
+                       }
+                       c->tcp_keepalive = 1;
+                       break;
+
+               case LDNS_EDNS_PADDING:
+                       if(!cfg->pad_responses || c->type != comm_tcp ||!c->ssl)
+                               break;
+                       if(!edns_opt_list_append(&edns->opt_list_out,
+                                               LDNS_EDNS_PADDING,
+                                               0, NULL, region)) {
+                               log_err("out of memory");
+                               return 0;
+                       }
+                       edns->padding_block_size = cfg->pad_responses_block_size;
+                       break;
+
+               default:
+                       if(!edns_opt_list_append(&edns->opt_list_in,
+                                       opt_code, opt_len, rdata_ptr, region)) {
+                               log_err("out of memory");
+                               return 0;
+                       }
+                       break;
                }
                rdata_ptr += opt_len;
                rdata_len -= opt_len;
@@ -1027,7 +1084,7 @@ parse_extract_edns(struct msg_parse* msg, struct edns_data* edns,
        /* take the options */
        rdata_len = found->rr_first->size-2;
        rdata_ptr = found->rr_first->ttl_data+6;
-       if(!parse_edns_options(rdata_ptr, rdata_len, edns, region))
+       if(!parse_edns_options(rdata_ptr, rdata_len, edns, NULL, NULL, region))
                return 0;
 
        /* ignore rrsigs */
@@ -1063,7 +1120,7 @@ skip_pkt_rrs(sldns_buffer* pkt, int num)
 
 int 
 parse_edns_from_pkt(sldns_buffer* pkt, struct edns_data* edns,
-       struct regional* region)
+       struct config_file* cfg, struct comm_point* c, struct regional* region)
 {
        size_t rdata_len;
        uint8_t* rdata_ptr;
@@ -1105,7 +1162,7 @@ parse_edns_from_pkt(sldns_buffer* pkt, struct edns_data* edns,
        if(sldns_buffer_remaining(pkt) < rdata_len)
                return LDNS_RCODE_FORMERR;
        rdata_ptr = sldns_buffer_current(pkt);
-       if(!parse_edns_options(rdata_ptr, rdata_len, edns, region))
+       if(!parse_edns_options(rdata_ptr, rdata_len, edns, cfg, c, region))
                return LDNS_RCODE_SERVFAIL;
 
        /* ignore rrsigs */
index 4bb82cc3cc56ef44a9370ebd4f95b2edc1a85c25..51816176055bb6d136a0005f6aa5d122fe035976 100644 (file)
@@ -70,6 +70,8 @@ struct rrset_parse;
 struct rr_parse;
 struct regional;
 struct edns_option;
+struct config_file;
+struct comm_point;
 
 /** number of buckets in parse rrset hash table. Must be power of 2. */
 #define PARSE_TABLE_SIZE 32
@@ -297,12 +299,14 @@ int parse_extract_edns(struct msg_parse* msg, struct edns_data* edns,
  *     section. At end, right after EDNS data or no movement if failed.
  * @param edns: the edns data allocated by the caller. Does not have to be
  *     initialised.
+ * @param cfg: the configuration (with nsid value etc.)
+ * @param c: commpoint to determine transport (if needed)
  * @param region: region to alloc results in (edns option contents)
  * @return: 0 on success, or an RCODE on error.
  *     RCODE formerr if OPT is badly formatted and so on.
  */
 int parse_edns_from_pkt(struct sldns_buffer* pkt, struct edns_data* edns,
-       struct regional* region);
+       struct config_file* cfg, struct comm_point* c, struct regional* region);
 
 /**
  * Calculate hash value for rrset in packet.
index 2081cd1e63f1eb063711abed8270645f91939785..f55dcb97e755ad56a4a28578dd9d9cdef2e0f0a9 100644 (file)
@@ -128,53 +128,3 @@ edns_string_addr_lookup(rbtree_type* tree, struct sockaddr_storage* addr,
        return (struct edns_string_addr*)addr_tree_lookup(tree, addr, addrlen);
 }
 
-static int edns_keepalive(struct edns_data* edns_out, struct edns_data* edns_in,
-               struct comm_point* c, struct regional* region)
-{
-       if(c->type == comm_udp)
-               return 1;
-
-       /* To respond with a Keepalive option, the client connection
-        * must have received one message with a TCP Keepalive EDNS option,
-        * and that option must have 0 length data. Subsequent messages
-        * sent on that connection will have a TCP Keepalive option.
-        */
-       if(c->tcp_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_out, LDNS_EDNS_KEEPALIVE,
-                       sizeof(data), data, region))
-                       return 0;
-               c->tcp_keepalive = 1;
-       }
-       return 1;
-}
-
-int apply_edns_options(struct edns_data* edns_out, struct edns_data* edns_in,
-       struct config_file* cfg, struct comm_point* c, struct regional* region)
-{
-       if(cfg->do_tcp_keepalive &&
-               !edns_keepalive(edns_out, edns_in, c, region))
-               return 0;
-
-       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_in, LDNS_EDNS_PADDING)) {
-              ; /* pass */
-       }
-
-       else if(!edns_opt_list_append(&edns_out->opt_list_out, LDNS_EDNS_PADDING
-                                                        , 0, NULL, region))
-               return 0;
-       else
-               edns_out->padding_block_size = cfg->pad_responses_block_size;
-
-       return 1;
-}
index 11742eb5b7230c9614198d5faddf13083ea72353..d9ded0b84dc4534c3af51c1f85a887dd82402416 100644 (file)
@@ -106,16 +106,4 @@ struct edns_string_addr*
 edns_string_addr_lookup(rbtree_type* tree, struct sockaddr_storage* addr,
        socklen_t addrlen);
 
-/**
- * Apply common EDNS options.
- *
- * @param edns_out: initialised edns information with outbound edns.
- * @param edns_in: initialised edns information with received edns.
- * @param cfg: configuration.
- * @param c: comm channel.
- * @param region: the region to allocate the edns options in.
- */
-int apply_edns_options(struct edns_data* edns_out, struct edns_data* edns_in,
-       struct config_file* cfg, struct comm_point* c, struct regional* region);
-
 #endif