resolved: simplify dns zone logic: take a single key when looking up entries
authorLennart Poettering <lennart@poettering.net>
Wed, 18 Nov 2015 14:30:54 +0000 (15:30 +0100)
committerLennart Poettering <lennart@poettering.net>
Wed, 18 Nov 2015 16:07:11 +0000 (17:07 +0100)
Instead of taking a DnsQuestion object (i.e. an array of keys) only take
a single key. This simplifies things a bit, and as DNS/LLMNR require a
single question per query message was unnecessary anyway.

This mimics a similar change that was done a while ago for the dns cache
logic.

src/resolve/resolved-dns-scope.c
src/resolve/resolved-dns-zone.c
src/resolve/resolved-dns-zone.h

index b15370b..873d76e 100644 (file)
@@ -543,6 +543,7 @@ static void dns_scope_verify_conflicts(DnsScope *s, DnsPacket *p) {
 void dns_scope_process_query(DnsScope *s, DnsStream *stream, DnsPacket *p) {
         _cleanup_(dns_packet_unrefp) DnsPacket *reply = NULL;
         _cleanup_(dns_answer_unrefp) DnsAnswer *answer = NULL, *soa = NULL;
+        DnsResourceKey *key = NULL;
         bool tentative = false;
         int r, fd;
 
@@ -576,7 +577,10 @@ void dns_scope_process_query(DnsScope *s, DnsStream *stream, DnsPacket *p) {
                 return;
         }
 
-        r = dns_zone_lookup(&s->zone, p->question, &answer, &soa, &tentative);
+        assert(p->question->n_keys == 1);
+        key = p->question->keys[0];
+
+        r = dns_zone_lookup(&s->zone, key, &answer, &soa, &tentative);
         if (r < 0) {
                 log_debug_errno(r, "Failed to lookup key: %m");
                 return;
index 48dcf76..a021ecb 100644 (file)
@@ -283,97 +283,76 @@ int dns_zone_put(DnsZone *z, DnsScope *s, DnsResourceRecord *rr, bool probe) {
         return 0;
 }
 
-int dns_zone_lookup(DnsZone *z, DnsQuestion *q, DnsAnswer **ret_answer, DnsAnswer **ret_soa, bool *ret_tentative) {
+int dns_zone_lookup(DnsZone *z, DnsResourceKey *key, DnsAnswer **ret_answer, DnsAnswer **ret_soa, bool *ret_tentative) {
         _cleanup_(dns_answer_unrefp) DnsAnswer *answer = NULL, *soa = NULL;
-        unsigned i, n_answer = 0, n_soa = 0;
-        bool tentative = true;
+        unsigned n_answer = 0;
+        DnsZoneItem *j, *first;
+        bool tentative = true, need_soa = false;
         int r;
 
         assert(z);
-        assert(q);
+        assert(key);
         assert(ret_answer);
-        assert(ret_soa);
 
-        if (q->n_keys <= 0) {
-                *ret_answer = NULL;
-                *ret_soa = NULL;
-
-                if (ret_tentative)
-                        *ret_tentative = false;
+        /* First iteration, count what we have */
 
-                return 0;
-        }
+        if (key->type == DNS_TYPE_ANY || key->class == DNS_CLASS_ANY) {
+                bool found = false, added = false;
+                int k;
 
-        /* First iteration, count what we have */
-        for (i = 0; i < q->n_keys; i++) {
-                DnsZoneItem *j, *first;
+                /* If this is a generic match, then we have to
+                 * go through the list by the name and look
+                 * for everything manually */
 
-                if (q->keys[i]->type == DNS_TYPE_ANY ||
-                    q->keys[i]->class == DNS_CLASS_ANY) {
-                        bool found = false, added = false;
-                        int k;
+                first = hashmap_get(z->by_name, DNS_RESOURCE_KEY_NAME(key));
+                LIST_FOREACH(by_name, j, first) {
+                        if (!IN_SET(j->state, DNS_ZONE_ITEM_PROBING, DNS_ZONE_ITEM_ESTABLISHED, DNS_ZONE_ITEM_VERIFYING))
+                                continue;
 
-                        /* If this is a generic match, then we have to
-                         * go through the list by the name and look
-                         * for everything manually */
+                        found = true;
 
-                        first = hashmap_get(z->by_name, DNS_RESOURCE_KEY_NAME(q->keys[i]));
-                        LIST_FOREACH(by_name, j, first) {
-                                if (!IN_SET(j->state, DNS_ZONE_ITEM_PROBING, DNS_ZONE_ITEM_ESTABLISHED, DNS_ZONE_ITEM_VERIFYING))
-                                        continue;
+                        k = dns_resource_key_match_rr(key, j->rr);
+                        if (k < 0)
+                                return k;
+                        if (k > 0) {
+                                n_answer++;
+                                added = true;
+                        }
 
-                                found = true;
+                }
 
-                                k = dns_resource_key_match_rr(q->keys[i], j->rr);
-                                if (k < 0)
-                                        return k;
-                                if (k > 0) {
-                                        n_answer++;
-                                        added = true;
-                                }
+                if (found && !added)
+                        need_soa = true;
 
-                        }
+        } else {
+                bool found = false;
 
-                        if (found && !added)
-                                n_soa++;
+                /* If this is a specific match, then look for
+                 * the right key immediately */
 
-                } else {
-                        bool found = false;
+                first = hashmap_get(z->by_key, key);
+                LIST_FOREACH(by_key, j, first) {
+                        if (!IN_SET(j->state, DNS_ZONE_ITEM_PROBING, DNS_ZONE_ITEM_ESTABLISHED, DNS_ZONE_ITEM_VERIFYING))
+                                continue;
 
-                        /* If this is a specific match, then look for
-                         * the right key immediately */
+                        found = true;
+                        n_answer++;
+                }
 
-                        first = hashmap_get(z->by_key, q->keys[i]);
-                        LIST_FOREACH(by_key, j, first) {
+                if (!found) {
+                        first = hashmap_get(z->by_name, DNS_RESOURCE_KEY_NAME(key));
+                        LIST_FOREACH(by_name, j, first) {
                                 if (!IN_SET(j->state, DNS_ZONE_ITEM_PROBING, DNS_ZONE_ITEM_ESTABLISHED, DNS_ZONE_ITEM_VERIFYING))
                                         continue;
 
-                                found = true;
-                                n_answer++;
-                        }
-
-                        if (!found) {
-                                first = hashmap_get(z->by_name, DNS_RESOURCE_KEY_NAME(q->keys[i]));
-                                LIST_FOREACH(by_name, j, first) {
-                                        if (!IN_SET(j->state, DNS_ZONE_ITEM_PROBING, DNS_ZONE_ITEM_ESTABLISHED, DNS_ZONE_ITEM_VERIFYING))
-                                                continue;
-
-                                        n_soa++;
-                                        break;
-                                }
+                                need_soa = true;
+                                break;
                         }
                 }
         }
 
-        if (n_answer <= 0 && n_soa <= 0) {
-                *ret_answer = NULL;
-                *ret_soa = NULL;
-
-                if (ret_tentative)
-                        *ret_tentative = false;
-
-                return 0;
-        }
+        if (n_answer <= 0 && !need_soa)
+                goto return_empty;
 
         if (n_answer > 0) {
                 answer = dns_answer_new(n_answer);
@@ -381,99 +360,113 @@ int dns_zone_lookup(DnsZone *z, DnsQuestion *q, DnsAnswer **ret_answer, DnsAnswe
                         return -ENOMEM;
         }
 
-        if (n_soa > 0) {
-                soa = dns_answer_new(n_soa);
+        if (need_soa) {
+                soa = dns_answer_new(1);
                 if (!soa)
                         return -ENOMEM;
         }
 
         /* Second iteration, actually add the RRs to the answers */
-        for (i = 0; i < q->n_keys; i++) {
-                DnsZoneItem *j, *first;
-
-                if (q->keys[i]->type == DNS_TYPE_ANY ||
-                    q->keys[i]->class == DNS_CLASS_ANY) {
-                        bool found = false, added = false;
-                        int k;
+        if (key->type == DNS_TYPE_ANY || key->class == DNS_CLASS_ANY) {
+                bool found = false, added = false;
+                int k;
 
-                        first = hashmap_get(z->by_name, DNS_RESOURCE_KEY_NAME(q->keys[i]));
-                        LIST_FOREACH(by_name, j, first) {
-                                if (!IN_SET(j->state, DNS_ZONE_ITEM_PROBING, DNS_ZONE_ITEM_ESTABLISHED, DNS_ZONE_ITEM_VERIFYING))
-                                        continue;
-
-                                found = true;
+                first = hashmap_get(z->by_name, DNS_RESOURCE_KEY_NAME(key));
+                LIST_FOREACH(by_name, j, first) {
+                        if (!IN_SET(j->state, DNS_ZONE_ITEM_PROBING, DNS_ZONE_ITEM_ESTABLISHED, DNS_ZONE_ITEM_VERIFYING))
+                                continue;
 
-                                if (j->state != DNS_ZONE_ITEM_PROBING)
-                                        tentative = false;
+                        found = true;
 
-                                k = dns_resource_key_match_rr(q->keys[i], j->rr);
-                                if (k < 0)
-                                        return k;
-                                if (k > 0) {
-                                        r = dns_answer_add(answer, j->rr, 0);
-                                        if (r < 0)
-                                                return r;
+                        if (j->state != DNS_ZONE_ITEM_PROBING)
+                                tentative = false;
 
-                                        added = true;
-                                }
-                        }
-
-                        if (found && !added) {
-                                r = dns_answer_add_soa(soa, DNS_RESOURCE_KEY_NAME(q->keys[i]), LLMNR_DEFAULT_TTL);
+                        k = dns_resource_key_match_rr(key, j->rr);
+                        if (k < 0)
+                                return k;
+                        if (k > 0) {
+                                r = dns_answer_add(answer, j->rr, 0);
                                 if (r < 0)
                                         return r;
+
+                                added = true;
                         }
-                } else {
-                        bool found = false;
+                }
 
-                        first = hashmap_get(z->by_key, q->keys[i]);
-                        LIST_FOREACH(by_key, j, first) {
-                                if (!IN_SET(j->state, DNS_ZONE_ITEM_PROBING, DNS_ZONE_ITEM_ESTABLISHED, DNS_ZONE_ITEM_VERIFYING))
-                                        continue;
+                if (found && !added) {
+                        r = dns_answer_add_soa(soa, DNS_RESOURCE_KEY_NAME(key), LLMNR_DEFAULT_TTL);
+                        if (r < 0)
+                                return r;
+                }
+        } else {
+                bool found = false;
 
-                                found = true;
+                first = hashmap_get(z->by_key, key);
+                LIST_FOREACH(by_key, j, first) {
+                        if (!IN_SET(j->state, DNS_ZONE_ITEM_PROBING, DNS_ZONE_ITEM_ESTABLISHED, DNS_ZONE_ITEM_VERIFYING))
+                                continue;
 
-                                if (j->state != DNS_ZONE_ITEM_PROBING)
-                                        tentative = false;
+                        found = true;
 
-                                r = dns_answer_add(answer, j->rr, 0);
-                                if (r < 0)
-                                        return r;
-                        }
+                        if (j->state != DNS_ZONE_ITEM_PROBING)
+                                tentative = false;
+
+                        r = dns_answer_add(answer, j->rr, 0);
+                        if (r < 0)
+                                return r;
+                }
 
-                        if (!found) {
-                                bool add_soa = false;
+                if (!found) {
+                        bool add_soa = false;
 
-                                first = hashmap_get(z->by_name, DNS_RESOURCE_KEY_NAME(q->keys[i]));
-                                LIST_FOREACH(by_name, j, first) {
-                                        if (!IN_SET(j->state, DNS_ZONE_ITEM_PROBING, DNS_ZONE_ITEM_ESTABLISHED, DNS_ZONE_ITEM_VERIFYING))
-                                                continue;
+                        first = hashmap_get(z->by_name, DNS_RESOURCE_KEY_NAME(key));
+                        LIST_FOREACH(by_name, j, first) {
+                                if (!IN_SET(j->state, DNS_ZONE_ITEM_PROBING, DNS_ZONE_ITEM_ESTABLISHED, DNS_ZONE_ITEM_VERIFYING))
+                                        continue;
 
-                                        if (j->state != DNS_ZONE_ITEM_PROBING)
-                                                tentative = false;
+                                if (j->state != DNS_ZONE_ITEM_PROBING)
+                                        tentative = false;
 
-                                        add_soa = true;
-                                }
+                                add_soa = true;
+                        }
 
-                                if (add_soa) {
-                                        r = dns_answer_add_soa(soa, DNS_RESOURCE_KEY_NAME(q->keys[i]), LLMNR_DEFAULT_TTL);
-                                        if (r < 0)
-                                                return r;
-                                }
+                        if (add_soa) {
+                                r = dns_answer_add_soa(soa, DNS_RESOURCE_KEY_NAME(key), LLMNR_DEFAULT_TTL);
+                                if (r < 0)
+                                        return r;
                         }
                 }
         }
 
+        /* If the caller sets ret_tentative to NULL, then use this as
+         * indication to not return tentative entries */
+
+        if (!ret_tentative && tentative)
+                goto return_empty;
+
         *ret_answer = answer;
         answer = NULL;
 
-        *ret_soa = soa;
-        soa = NULL;
+        if (ret_soa) {
+                *ret_soa = soa;
+                soa = NULL;
+        }
 
         if (ret_tentative)
                 *ret_tentative = tentative;
 
         return 1;
+
+return_empty:
+        *ret_answer = NULL;
+
+        if (ret_soa)
+                *ret_soa = NULL;
+
+        if (ret_tentative)
+                *ret_tentative = false;
+
+        return 0;
 }
 
 void dns_zone_item_conflict(DnsZoneItem *i) {
index 495d17c..db92113 100644 (file)
@@ -67,7 +67,7 @@ void dns_zone_flush(DnsZone *z);
 int dns_zone_put(DnsZone *z, DnsScope *s, DnsResourceRecord *rr, bool probe);
 void dns_zone_remove_rr(DnsZone *z, DnsResourceRecord *rr);
 
-int dns_zone_lookup(DnsZone *z, DnsQuestion *q, DnsAnswer **answer, DnsAnswer **soa, bool *tentative);
+int dns_zone_lookup(DnsZone *z, DnsResourceKey *key, DnsAnswer **answer, DnsAnswer **soa, bool *tentative);
 
 void dns_zone_item_conflict(DnsZoneItem *i);
 void dns_zone_item_ready(DnsZoneItem *i);