]> git.ipfire.org Git - thirdparty/knot-resolver.git/commitdiff
Fixed an error that caused the integration tests to fail.
authorKarel Slany <karel.slany@nic.cz>
Wed, 10 Aug 2016 14:36:49 +0000 (16:36 +0200)
committerOndřej Surý <ondrej@sury.org>
Thu, 11 Aug 2016 12:06:45 +0000 (14:06 +0200)
EDNS data from the packet must be erased before attempting to send the
query again.

lib/resolve.c

index ea907556d3ef2fd1881d82d6f6049807ac763da4..56ee37b586893b9b7ac77b346a2dc76818d53e9c 100644 (file)
@@ -270,6 +270,34 @@ static int edns_put(knot_pkt_t *pkt)
        return knot_pkt_put(pkt, KNOT_COMPR_HINT_NONE, pkt->opt_rr, KNOT_PF_FREE);
 }
 
+/** Removes last EDNS OPT RR written to the packet. */
+static int edns_erase_and_reserve(knot_pkt_t *pkt)
+{
+       /* Nothing to be done. */
+       if (!pkt || !pkt->opt_rr) {
+               return 0;
+       }
+
+       /* Fail if the data are located elsewhere than at the end of packet. */
+       if (pkt->current != KNOT_ADDITIONAL ||
+           pkt->opt_rr != &pkt->rr[pkt->rrset_count - 1]) {
+               return -1;
+       }
+
+       size_t len = knot_rrset_size(pkt->opt_rr);
+       int16_t rr_removed = pkt->opt_rr->rrs.rr_count;
+       /* Decrease rrset counters. */
+       pkt->rrset_count -= 1;
+       pkt->sections[pkt->current].count -= 1;
+       pkt->size -= len;
+       knot_wire_add_arcount(pkt->wire, -rr_removed); /* ADDITIONAL */
+
+       pkt->opt_rr = NULL;
+
+       /* Reserve the freed space. */
+       return knot_pkt_reserve(pkt, len);
+}
+
 static int edns_create(knot_pkt_t *pkt, knot_pkt_t *template, struct kr_request *req)
 {
        pkt->opt_rr = knot_rrset_copy(req->ctx->opt_rr, &pkt->mm);
@@ -358,7 +386,11 @@ static int query_finalize(struct kr_request *request, struct kr_query *qry, knot
        int ret = 0;
        knot_pkt_begin(pkt, KNOT_ADDITIONAL);
        if (!(qry->flags & QUERY_SAFEMODE)) {
-               ret = edns_create(pkt, request->answer, request);
+               /* Remove any EDNS records from any previous iteration. */
+               ret = edns_erase_and_reserve(pkt);
+               if (ret == 0) {
+                       ret = edns_create(pkt, request->answer, request);
+               }
                if (ret == 0) {
                        /* Stub resolution (ask for +rd and +do) */
                        if (qry->flags & QUERY_STUB) {