]> git.ipfire.org Git - thirdparty/unbound.git/commitdiff
Nicer encoding. fixes.
authorWouter Wijngaards <wouter@nlnetlabs.nl>
Mon, 11 Jun 2007 10:12:43 +0000 (10:12 +0000)
committerWouter Wijngaards <wouter@nlnetlabs.nl>
Mon, 11 Jun 2007 10:12:43 +0000 (10:12 +0000)
git-svn-id: file:///svn/unbound/trunk@379 be551aaa-1e26-0410-a405-d3ace91eadb9

daemon/worker.c
doc/Changelog
iterator/iterator.c
services/outside_network.c
testcode/unitmsgparse.c
util/data/msgencode.c
util/data/msgencode.h
util/data/msgparse.c
util/data/msgreply.c
util/netevent.c

index d75190f5c0ec50cb2503d0d9f57b2926745b1795..b414db09cc350083f7e986ae96d98691e4432759 100644 (file)
@@ -503,7 +503,7 @@ answer_from_cache(struct worker* worker, struct lruhash_entry* e, uint16_t id,
        /* locked and ids and ttls are OK. */
        if(!reply_info_answer_encode(&mrentry->key, rep, id, flags, 
                repinfo->c->buffer, timenow, 1, worker->scratchpad,
-               udpsize, edns)) {
+               udpsize, edns, (int)(edns->bits & EDNS_DO) )) {
                replyerror_fillbuf(LDNS_RCODE_SERVFAIL, repinfo, id,
                        flags, &mrentry->key);
        }
@@ -529,12 +529,12 @@ worker_handle_request(struct comm_point* c, void* arg, int error,
        struct work_query* w;
        struct edns_data edns;
 
-       verbose(VERB_DETAIL, "worker handle request");
        if(error != NETEVENT_NOERROR) {
-               log_err("called with err=%d", error);
+               log_err("handle request called with err=%d", error);
                return 0;
        }
        if((ret=worker_check_request(c->buffer)) != 0) {
+               verbose(VERB_ALGO, "worker check request: bad query.");
                if(ret != -1) {
                        LDNS_QR_SET(ldns_buffer_begin(c->buffer));
                        LDNS_RCODE_SET(ldns_buffer_begin(c->buffer), ret);
@@ -546,6 +546,7 @@ worker_handle_request(struct comm_point* c, void* arg, int error,
        worker->stats.num_queries++;
        /* see if query is in the cache */
        if(!query_info_parse(&qinfo, c->buffer)) {
+               verbose(VERB_ALGO, "worker parse request: formerror.");
                LDNS_QR_SET(ldns_buffer_begin(c->buffer));
                LDNS_RCODE_SET(ldns_buffer_begin(c->buffer), 
                        LDNS_RCODE_FORMERR);
@@ -553,6 +554,7 @@ worker_handle_request(struct comm_point* c, void* arg, int error,
        }
        h = query_info_hash(&qinfo);
        if((ret=parse_edns_from_pkt(c->buffer, &edns)) != 0) {
+               verbose(VERB_ALGO, "worker parse edns: formerror.");
                LDNS_QR_SET(ldns_buffer_begin(c->buffer));
                LDNS_RCODE_SET(ldns_buffer_begin(c->buffer), ret);
                return 1;
@@ -562,6 +564,7 @@ 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;
+               verbose(VERB_ALGO, "query with bad edns version.");
                replyerror_fillbuf(EDNS_RCODE_BADVERS&0xf, repinfo, 
                        *(uint16_t*)ldns_buffer_begin(c->buffer),
                        ldns_buffer_read_u16_at(c->buffer, 2), &qinfo);
@@ -572,7 +575,6 @@ worker_handle_request(struct comm_point* c, void* arg, int error,
                edns.udp_size = 65535; /* max size for TCP replies */
        if((e=slabhash_lookup(worker->env.msg_cache, h, &qinfo, 0))) {
                /* answer from cache - we have acquired a readlock on it */
-               verbose(VERB_DETAIL, "answer from the cache");
                if(answer_from_cache(worker, e, 
                        *(uint16_t*)ldns_buffer_begin(c->buffer), 
                        ldns_buffer_read_u16_at(c->buffer, 2), repinfo, 
index f9a78af931fbaec5cf5226c31f4f5116b4b9b96a..f0d1faa1f1374c71c066543cc7a27b2cb89dac4f 100644 (file)
@@ -1,3 +1,13 @@
+11 June 2007: Wouter
+       - replies on TCP queries have the address field set in replyinfo,
+         for serviced queries, because the initiator does not know that
+         a TCP fallback has occured.
+       - omit DNSSEC types from nonDO replies, except if qtype is ANY or
+         if qtype directly queries for the type (and then only show that
+         'unknown type' in the answer section).
+       - fixed message parsing where rrsigs on their own would be put
+         in the signature list over the rrsig type.
+
 7 June 2007: Wouter
        - fixup error in double linked list insertion for subqueries and
          for outbound list of serviced queries for iterator module.
index bb520721e9ed094750a383fe5b547fa12326a675..8e22fb0971d6cc213a00d7123324f45a1ff21055 100644 (file)
@@ -163,7 +163,8 @@ iter_handlereply(struct module_qstate* qstate, int id,
        qstate->edns.bits &= EDNS_DO;
        if(!reply_info_answer_encode(&reply_qinfo, reply_msg, 0, 
                qstate->query_flags, qstate->buf, 0, 0, 
-               qstate->scratch, us, &qstate->edns))
+               qstate->scratch, us, &qstate->edns, 
+               (int)(qstate->edns.bits&EDNS_DO)))
                return 0;
        dns_cache_store_msg(qstate->env, &reply_qinfo, qstate->query_hash, 
                reply_msg);
@@ -344,7 +345,7 @@ iter_encode_respmsg(struct module_qstate* qstate, struct iter_qstate* iq,
        edns.bits = qstate->edns.bits & EDNS_DO;
        if(!reply_info_answer_encode(&qinf, msg->rep, 0, iq->orig_qflags, 
                qstate->buf, 0, 1, qstate->scratch, qstate->edns.udp_size, 
-               &edns)) {
+               &edns, (int)(qstate->edns.bits & EDNS_DO))) {
                /* encode servfail */
                error_response(qstate, id, LDNS_RCODE_SERVFAIL);
                return;
index 67c2d294995cedc560c8066a93501f6aa96ef939..b1a2c5a88d8ad78a7f9cdf840f503eeb8018529e 100644 (file)
@@ -1017,7 +1017,9 @@ serviced_tcp_callback(struct comm_point* c, void* arg, int error,
                serviced_tcp_initiate(sq->outnet, sq, c->buffer);
                return 0;
        }
-
+       /* insert address into reply info */
+       memcpy(&rep->addr, &sq->addr, sq->addrlen);
+       rep->addrlen = sq->addrlen;
        (void)rbtree_delete(sq->outnet->serviced, sq);
        serviced_callbacks(sq, error, c, rep);
        serviced_delete(sq);
index 4060c1ea6e118261ad4a729328aac82c63ea5f6c..c26391cdec0da8ae1b50089dcd1f1c58bcfecabe 100644 (file)
@@ -270,7 +270,7 @@ testpkt(ldns_buffer* pkt, struct alloc_cache* alloc, ldns_buffer* out,
        } else {
                const size_t lim = 512;
                ret = reply_info_encode(&qi, rep, id, flags, out, timenow,
-                       region, 65535);
+                       region, 65535, (int)(edns.bits & EDNS_DO) );
                unit_assert(ret != 0); /* udp packets should fit */
                attach_edns_record(out, &edns);
                if(vbmp) printf("inlen %u outlen %u\n", 
@@ -281,7 +281,8 @@ testpkt(ldns_buffer* pkt, struct alloc_cache* alloc, ldns_buffer* out,
                if(ldns_buffer_limit(out) > lim) {
                        ret = reply_info_encode(&qi, rep, id, flags, out, 
                                timenow, region, 
-                               lim - calc_edns_field_size(&edns));
+                               lim - calc_edns_field_size(&edns),
+                               (int)(edns.bits & EDNS_DO));
                        unit_assert(ret != 0); /* should fit, but with TC */
                        attach_edns_record(out, &edns);
                        if( LDNS_QDCOUNT(ldns_buffer_begin(out)) !=
index ce1802ffba06152eec7808d7a1da746750485892..fb6a68f783de09fc4268632999500a1ceb5f42a5 100644 (file)
@@ -413,17 +413,49 @@ compress_rdata(ldns_buffer* pkt, uint8_t* rdata, size_t todolen,
        return RETVAL_OK;
 }
 
+/** Returns true if RR type should be included */
+static int
+rrset_belongs_in_reply(ldns_pkt_section s, uint16_t rrtype, uint16_t qtype, 
+       int dnssec)
+{
+       if(dnssec)
+               return 1;
+       /* skip non DNSSEC types, except if directly queried for */
+       if(s == LDNS_SECTION_ANSWER) {
+               if(qtype == LDNS_RR_TYPE_ANY || qtype == rrtype)
+                       return 1;
+       }
+       /* check DNSSEC-ness */
+       switch(rrtype) {
+               case LDNS_RR_TYPE_SIG:
+               case LDNS_RR_TYPE_KEY:
+               case LDNS_RR_TYPE_NXT:
+               case LDNS_RR_TYPE_DS:
+               case LDNS_RR_TYPE_RRSIG:
+               case LDNS_RR_TYPE_NSEC:
+               case LDNS_RR_TYPE_DNSKEY:
+               /* FIXME: include NSEC3 here. */
+                       return 0;
+       }
+       return 1;
+}
+
 /** store rrset in buffer in wireformat, return RETVAL_* */
 static int
 packed_rrset_encode(struct ub_packed_rrset_key* key, ldns_buffer* pkt, 
        uint16_t* num_rrs, uint32_t timenow, region_type* region,
-       int do_data, int do_sig, struct compress_tree_node** tree)
+       int do_data, int do_sig, struct compress_tree_node** tree,
+       ldns_pkt_section s, uint16_t qtype, int dnssec)
 {
        size_t i, owner_pos;
        int r, owner_labs;
        uint16_t owner_ptr = 0;
        struct packed_rrset_data* data = (struct packed_rrset_data*)
                key->entry.data;
+       
+       /* does this RR type belong in the answer? */
+       if(!rrset_belongs_in_reply(s, ntohs(key->rk.type), qtype, dnssec))
+               return RETVAL_OK;
 
        owner_labs = dname_count_labels(key->rk.dname);
        owner_pos = ldns_buffer_position(pkt);
@@ -452,7 +484,7 @@ packed_rrset_encode(struct ub_packed_rrset_key* key, ldns_buffer* pkt,
                }
        }
        /* insert rrsigs */
-       if(do_sig) {
+       if(do_sig && dnssec) {
                size_t total = data->count+data->rrsig_count;
                for(i=data->count; i<total; i++) {
                        if(owner_ptr && owner_labs != 1) {
@@ -481,7 +513,7 @@ packed_rrset_encode(struct ub_packed_rrset_key* key, ldns_buffer* pkt,
        /* change rrnum only after we are sure it fits */
        if(do_data)
                *num_rrs += data->count;
-       if(do_sig)
+       if(do_sig && dnssec)
                *num_rrs += data->rrsig_count;
 
        return RETVAL_OK;
@@ -491,16 +523,18 @@ packed_rrset_encode(struct ub_packed_rrset_key* key, ldns_buffer* pkt,
 static int
 insert_section(struct reply_info* rep, size_t num_rrsets, uint16_t* num_rrs,
        ldns_buffer* pkt, size_t rrsets_before, uint32_t timenow, 
-       region_type* region, int addit, struct compress_tree_node** tree)
+       region_type* region, struct compress_tree_node** tree,
+       ldns_pkt_section s, uint16_t qtype, int dnssec)
 {
        int r;
        size_t i, setstart;
        *num_rrs = 0;
-       if(!addit) {
+       if(s != LDNS_SECTION_ADDITIONAL) {
                for(i=0; i<num_rrsets; i++) {
                        setstart = ldns_buffer_position(pkt);
                        if((r=packed_rrset_encode(rep->rrsets[rrsets_before+i], 
-                               pkt, num_rrs, timenow, region, 1, 1, tree))
+                               pkt, num_rrs, timenow, region, 1, 1, tree,
+                               s, qtype, dnssec))
                                != RETVAL_OK) {
                                /* Bad, but if due to size must set TC bit */
                                /* trim off the rrset neatly. */
@@ -512,28 +546,31 @@ insert_section(struct reply_info* rep, size_t num_rrsets, uint16_t* num_rrs,
                for(i=0; i<num_rrsets; i++) {
                        setstart = ldns_buffer_position(pkt);
                        if((r=packed_rrset_encode(rep->rrsets[rrsets_before+i], 
-                               pkt, num_rrs, timenow, region, 1, 0, tree))
+                               pkt, num_rrs, timenow, region, 1, 0, tree,
+                               s, qtype, dnssec))
                                != RETVAL_OK) {
                                ldns_buffer_set_position(pkt, setstart);
                                return r;
                        }
                }
-               for(i=0; i<num_rrsets; i++) {
+               if(dnssec)
+                 for(i=0; i<num_rrsets; i++) {
                        setstart = ldns_buffer_position(pkt);
                        if((r=packed_rrset_encode(rep->rrsets[rrsets_before+i], 
-                               pkt, num_rrs, timenow, region, 0, 1, tree))
+                               pkt, num_rrs, timenow, region, 0, 1, tree,
+                               s, qtype, dnssec))
                                != RETVAL_OK) {
                                ldns_buffer_set_position(pkt, setstart);
                                return r;
                        }
-               }
+                 }
        }
        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)
+       region_type* region, uint16_t udpsize, int dnssec)
 {
        uint16_t ancount=0, nscount=0, arcount=0;
        struct compress_tree_node* tree = 0;
@@ -567,7 +604,8 @@ int reply_info_encode(struct query_info* qinfo, struct reply_info* rep,
 
        /* insert answer section */
        if((r=insert_section(rep, rep->an_numrrsets, &ancount, buffer, 
-               0, timenow, region, 0, &tree)) != RETVAL_OK) {
+               0, timenow, region, &tree, LDNS_SECTION_ANSWER, qinfo->qtype, 
+               dnssec)) != RETVAL_OK) {
                if(r == RETVAL_TRUNC) {
                        /* create truncated message */
                        ldns_buffer_write_u16_at(buffer, 6, ancount);
@@ -581,7 +619,8 @@ int reply_info_encode(struct query_info* qinfo, struct reply_info* rep,
 
        /* insert auth section */
        if((r=insert_section(rep, rep->ns_numrrsets, &nscount, buffer, 
-               rep->an_numrrsets, timenow, region, 0, &tree)) != RETVAL_OK) {
+               rep->an_numrrsets, timenow, region, &tree,
+               LDNS_SECTION_AUTHORITY, qinfo->qtype, dnssec)) != RETVAL_OK) {
                if(r == RETVAL_TRUNC) {
                        /* create truncated message */
                        ldns_buffer_write_u16_at(buffer, 8, nscount);
@@ -596,7 +635,8 @@ int reply_info_encode(struct query_info* qinfo, struct reply_info* rep,
        /* insert add section */
        if((r=insert_section(rep, rep->ar_numrrsets, &arcount, buffer, 
                rep->an_numrrsets + rep->ns_numrrsets, timenow, region, 
-               1, &tree)) != RETVAL_OK) {
+               &tree, LDNS_SECTION_ADDITIONAL, qinfo->qtype, 
+               dnssec)) != RETVAL_OK) {
                if(r == RETVAL_TRUNC) {
                        /* no need to set TC bit, this is the additional */
                        ldns_buffer_write_u16_at(buffer, 10, arcount);
@@ -646,7 +686,7 @@ int
 reply_info_answer_encode(struct query_info* qinf, struct reply_info* rep, 
        uint16_t id, uint16_t qflags, ldns_buffer* pkt, uint32_t timenow,
        int cached, struct region* region, uint16_t udpsize, 
-       struct edns_data* edns)
+       struct edns_data* edns, int dnssec)
 {
        uint16_t flags;
 
@@ -662,7 +702,7 @@ reply_info_answer_encode(struct query_info* qinf, struct reply_info* rep,
                return 0; /* packet too small to contain edns... */
        udpsize -= calc_edns_field_size(edns);
        if(!reply_info_encode(qinf, rep, id, flags, pkt, timenow, region,
-               udpsize)) {
+               udpsize, dnssec)) {
                log_err("reply encode: out of memory");
                return 0;
        }
index de49404f52997310a49360ea08e217b839665da4..203929dc832c56d1ab2339f51141969aa4bde9ef 100644 (file)
@@ -61,12 +61,13 @@ struct edns_data;
  * @param udpsize: size of the answer, 512, from EDNS, or 64k for TCP.
  * @param edns: EDNS data included in the answer, NULL for none.
  *     or if edns_present = 0, it is not included.
+ * @param dnssec: if 0 DNSSEC records are omitted from the answer.
  * @return: 0 on error (server failure).
  */
 int reply_info_answer_encode(struct query_info* qinf, struct reply_info* rep, 
        uint16_t id, uint16_t qflags, ldns_buffer* dest, uint32_t timenow,
        int cached, struct region* region, uint16_t udpsize, 
-       struct edns_data* edns);
+       struct edns_data* edns, int dnssec);
 
 /**
  * Regenerate the wireformat from the stored msg reply.
@@ -81,12 +82,13 @@ int reply_info_answer_encode(struct query_info* qinf, struct reply_info* rep,
  * @param timenow: time now, to adjust ttl values.
  * @param region: to store temporary data in.
  * @param udpsize: size of the answer, 512, from EDNS, or 64k for TCP.
+ * @param dnssec: if 0 DNSSEC records are omitted from the answer.
  * @return: nonzero is success, or 
  *     0 on error: malloc failure (no log_err has been done).
  */
 int reply_info_encode(struct query_info* qinfo, struct reply_info* rep, 
        uint16_t id, uint16_t flags, ldns_buffer* buffer, uint32_t timenow, 
-       struct region* region, uint16_t udpsize);
+       struct region* region, uint16_t udpsize, int dnssec);
 
 /**
  * Encode query packet. Assumes the buffer is large enough.
index ac01bddcc09e4dfca5d71cc7a7375c70f0bd6503..61c320740f7a7a987e0c308fa1767189e1ed42e1 100644 (file)
@@ -720,7 +720,7 @@ add_rr_to_rrset(struct rrset_parse* rrset, ldns_buffer* pkt,
                return LDNS_RCODE_SERVFAIL;
        rr->ttl_data = ldns_buffer_current(pkt);
        rr->next = 0;
-       if(type == LDNS_RR_TYPE_RRSIG) {
+       if(type == LDNS_RR_TYPE_RRSIG && rrset->type != LDNS_RR_TYPE_RRSIG) {
                if(rrset->rrsig_last) 
                        rrset->rrsig_last->next = rr;
                else    rrset->rrsig_first = rr;
index fc9b7661bdc016dc4fb0c9693b197782315f8bfa..859788363fe404681b83aaa8be322b835bb45991 100644 (file)
@@ -659,7 +659,7 @@ log_dns_msg(const char* str, struct query_info* qinfo, struct reply_info* rep)
        ldns_buffer* buf = ldns_buffer_new(65535);
        struct region* region = region_create(malloc, free);
        if(!reply_info_encode(qinfo, rep, 0, rep->flags, buf, 0, 
-               region, 65535)) {
+               region, 65535, 1)) {
                log_info("%s: log_dns_msg: out of memory", str);
        } else {
                ldns_status s;
index ff09ffda76d92a917ae2ac8059679309639867e1..b07913056bbc0a541e9655cb7f6c6cbbb8b88ce3 100644 (file)
@@ -231,7 +231,6 @@ comm_point_udp_callback(int fd, short event, void* arg)
        rep.c = (struct comm_point*)arg;
        log_assert(rep.c->type == comm_udp);
 
-       verbose(VERB_ALGO, "callback udp");
        if(!(event&EV_READ))
                return;
        log_assert(rep.c && rep.c->buffer && rep.c->fd == fd);