]> git.ipfire.org Git - thirdparty/unbound.git/commitdiff
fix of flags in errors and very short bufsizes from edns.
authorWouter Wijngaards <wouter@nlnetlabs.nl>
Tue, 19 Jun 2007 13:50:43 +0000 (13:50 +0000)
committerWouter Wijngaards <wouter@nlnetlabs.nl>
Tue, 19 Jun 2007 13:50:43 +0000 (13:50 +0000)
git-svn-id: file:///svn/unbound/trunk@397 be551aaa-1e26-0410-a405-d3ace91eadb9

daemon/worker.c
doc/Changelog
iterator/iterator.c
util/data/msgencode.c

index 506752bc12bae255e11dd72074c9d904bc7b536f..671af29d16aac82dbbb3757c861ad4e21f0aa435 100644 (file)
@@ -157,7 +157,7 @@ replyerror_fillbuf(int r, struct comm_reply* repinfo, uint16_t id,
        
        ldns_buffer_clear(buf);
        ldns_buffer_write(buf, &id, sizeof(uint16_t));
-       flags = (uint16_t)(BIT_QR | r); /* QR and retcode*/
+       flags = (uint16_t)(BIT_QR | BIT_RA | r); /* QR and retcode*/
        flags |= (qflags & (BIT_RD|BIT_CD)); /* copy RD and CD bit */
        ldns_buffer_write_u16(buf, flags);
        flags = 1;
@@ -571,6 +571,16 @@ worker_handle_request(struct comm_point* c, void* arg, int error,
                attach_edns_record(c->buffer, &edns);
                return 1;
        }
+       if(edns.edns_present && edns.udp_size < LDNS_HEADER_SIZE) {
+               verbose(VERB_ALGO, "worker request: edns is too small.");
+               LDNS_QR_SET(ldns_buffer_begin(c->buffer));
+               LDNS_TC_SET(ldns_buffer_begin(c->buffer));
+               LDNS_RCODE_SET(ldns_buffer_begin(c->buffer), 
+                       LDNS_RCODE_SERVFAIL);
+               ldns_buffer_set_position(c->buffer, LDNS_HEADER_SIZE);
+               ldns_buffer_flip(c->buffer);
+               return 1;
+       }
        if(c->type != comm_udp)
                edns.udp_size = 65535; /* max size for TCP replies */
        if((e=slabhash_lookup(worker->env.msg_cache, h, &qinfo, 0))) {
index 86744a85df5c741d45b7f733b9431105826ceaec..c14419a94b3225b822a1a3185447d9388938fe99 100644 (file)
@@ -6,6 +6,9 @@
        - target-fetch-policy: "3 2 1 0 0" config setting.
        - fixup queries answered without RD bit (for root prime results).
        - refuse AXFR and IXFR requests.
+       - fixup RD flag in error reply from iterator. fixup RA flag from
+         worker error reply.
+       - fixup encoding of very short edns buffer sizes, now sets TC bit.
 
 18 June 2007: Wouter
        - same, move subqueries to slumber list when first has resolved.
index 6f7e0f305de3ce82c8b31a4a5ed7689dd5e89e63..0ebdf660dee726a3dcffd2830ae7ea6f3ca2fdf8 100644 (file)
@@ -255,10 +255,12 @@ error_response(struct module_qstate* qstate, int id, int rcode)
        verbose(VERB_DETAIL, "return error response %s", 
                ldns_lookup_by_id(ldns_rcodes, rcode)?
                ldns_lookup_by_id(ldns_rcodes, rcode)->name:"??");
-       if(iq && iq->orig_qname) {
-               /* encode original query */
-               qstate->qinfo.qname = iq->orig_qname;
-               qstate->qinfo.qname_len = iq->orig_qnamelen;
+       if(iq) {
+               if(iq->orig_qname) {
+                       /* encode original query */
+                       qstate->qinfo.qname = iq->orig_qname;
+                       qstate->qinfo.qname_len = iq->orig_qnamelen;
+               }
                qstate->query_flags = iq->orig_qflags;
        }
        qinfo_query_encode(qstate->buf, &qstate->qinfo);
index fb6a68f783de09fc4268632999500a1ceb5f42a5..0add5fd43cc260a363acaeb040424374afc55394 100644 (file)
@@ -568,7 +568,26 @@ insert_section(struct reply_info* rep, size_t num_rrsets, uint16_t* num_rrs,
        return RETVAL_OK;
 }
 
-int reply_info_encode(struct query_info* qinfo, struct reply_info* rep, 
+/** store query section in wireformat buffer, return RETVAL */
+static int
+insert_query(struct query_info* qinfo, struct compress_tree_node* tree, 
+       ldns_buffer* buffer, struct region* region)
+{
+       if(ldns_buffer_remaining(buffer) < 
+               qinfo->qname_len+sizeof(uint16_t)*2)
+               return RETVAL_TRUNC; /* buffer too small */
+       if(!compress_tree_store(&tree, qinfo->qname, 
+               dname_count_labels(qinfo->qname), 
+               ldns_buffer_position(buffer), region, NULL))
+               return RETVAL_OUTMEM;
+       ldns_buffer_write(buffer, qinfo->qname, qinfo->qname_len);
+       ldns_buffer_write_u16(buffer, qinfo->qtype);
+       ldns_buffer_write_u16(buffer, qinfo->qclass);
+       return RETVAL_OK;
+}
+
+int 
+reply_info_encode(struct query_info* qinfo, struct reply_info* rep, 
        uint16_t id, uint16_t flags, ldns_buffer* buffer, uint32_t timenow, 
        region_type* region, uint16_t udpsize, int dnssec)
 {
@@ -590,16 +609,17 @@ int reply_info_encode(struct query_info* qinfo, struct reply_info* rep,
 
        /* insert query section */
        if(rep->qdcount) {
-               if(ldns_buffer_remaining(buffer) < 
-                       qinfo->qname_len+sizeof(uint16_t)*2)
-                       return 0; /* buffer too small */
-               if(!compress_tree_store(&tree, qinfo->qname, 
-                       dname_count_labels(qinfo->qname), 
-                       ldns_buffer_position(buffer), region, NULL))
+               if((r=insert_query(qinfo, tree, buffer, region)) != 
+                       RETVAL_OK) {
+                       if(r == RETVAL_TRUNC) {
+                               /* create truncated message */
+                               ldns_buffer_write_u16_at(buffer, 4, 0);
+                               LDNS_TC_SET(ldns_buffer_begin(buffer));
+                               ldns_buffer_flip(buffer);
+                               return 1;
+                       }
                        return 0;
-               ldns_buffer_write(buffer, qinfo->qname, qinfo->qname_len);
-               ldns_buffer_write_u16(buffer, qinfo->qtype);
-               ldns_buffer_write_u16(buffer, qinfo->qclass);
+               }
        }
 
        /* insert answer section */
@@ -689,6 +709,7 @@ reply_info_answer_encode(struct query_info* qinf, struct reply_info* rep,
        struct edns_data* edns, int dnssec)
 {
        uint16_t flags;
+       int attach_edns = 1;
 
        if(!cached) {
                /* original flags, copy RD bit from query. */
@@ -698,15 +719,23 @@ reply_info_answer_encode(struct query_info* qinf, struct reply_info* rep,
                flags = (rep->flags & ~BIT_AA) | (qflags & (BIT_RD|BIT_CD)); 
        }
        log_assert(flags & BIT_QR); /* QR bit must be on in our replies */
-       if(udpsize < LDNS_HEADER_SIZE + calc_edns_field_size(edns))
-               return 0; /* packet too small to contain edns... */
-       udpsize -= calc_edns_field_size(edns);
+       if(udpsize < LDNS_HEADER_SIZE)
+               return 0;
+       if(udpsize < LDNS_HEADER_SIZE + calc_edns_field_size(edns)) {
+               /* packet too small to contain edns, omit it. */
+               attach_edns = 0;
+       } else {
+               /* reserve space for edns record */
+               udpsize -= calc_edns_field_size(edns);
+       }
+
        if(!reply_info_encode(qinf, rep, id, flags, pkt, timenow, region,
                udpsize, dnssec)) {
                log_err("reply encode: out of memory");
                return 0;
        }
-       attach_edns_record(pkt, edns);
+       if(attach_edns)
+               attach_edns_record(pkt, edns);
        return 1;
 }