chiark / gitweb /
Reject invalid quoted strings
[elogind.git] / src / resolve / resolved-dns-zone.c
index 2325ddfe7fc51c3f9639540c160a072a3681b515..99ea420ff4e7a8a13eae0617a53a48298e0e4d5e 100644 (file)
@@ -165,6 +165,11 @@ int dns_zone_put(DnsZone *z, DnsResourceRecord *rr) {
         assert(z);
         assert(rr);
 
+        if (rr->key->class == DNS_CLASS_ANY)
+                return -EINVAL;
+        if (rr->key->type == DNS_TYPE_ANY)
+                return -EINVAL;
+
         existing = dns_zone_get(z, rr);
         if (existing)
                 return 0;
@@ -187,58 +192,119 @@ int dns_zone_put(DnsZone *z, DnsResourceRecord *rr) {
         return 0;
 }
 
-int dns_zone_lookup(DnsZone *z, DnsQuestion *q, DnsAnswer **ret) {
-        _cleanup_(dns_answer_unrefp) DnsAnswer *answer = NULL;
+int dns_zone_lookup(DnsZone *z, DnsQuestion *q, DnsAnswer **ret_answer, DnsAnswer **ret_soa) {
+        _cleanup_(dns_answer_unrefp) DnsAnswer *answer = NULL, *soa = NULL;
+        unsigned i, n_answer = 0, n_soa = 0;
         int r;
-        unsigned i, n = 0;
-        bool has_other_rrs = false;
 
         assert(z);
         assert(q);
-        assert(ret);
+        assert(ret_answer);
+        assert(ret_soa);
 
         if (q->n_keys <= 0) {
-                *ret = NULL;
+                *ret_answer = NULL;
+                *ret_soa = NULL;
                 return 0;
         }
 
+        /* First iteration, count what we have */
         for (i = 0; i < q->n_keys; i++) {
                 DnsZoneItem *j;
 
-                j = hashmap_get(z->by_key, q->keys[i]);
-                if (!j) {
-                        if (hashmap_get(z->by_name, DNS_RESOURCE_KEY_NAME(q->keys[i])))
-                                has_other_rrs = true;
-
-                        continue;
+                if (q->keys[i]->type == DNS_TYPE_ANY ||
+                    q->keys[i]->class == DNS_CLASS_ANY) {
+                        int k;
+
+                        /* If this is a generic match, then we have to
+                         * go through the list by the name and look
+                         * for everything manually */
+
+                        j = hashmap_get(z->by_name, DNS_RESOURCE_KEY_NAME(q->keys[i]));
+                        LIST_FOREACH(by_name, j, j) {
+                                k = dns_resource_key_match_rr(q->keys[i], j->rr);
+                                if (k < 0)
+                                        return k;
+                                if (k == 0)
+                                        n_soa++;
+                                else
+                                        n_answer++;
+                        }
+
+                } else {
+                        j = hashmap_get(z->by_key, q->keys[i]);
+                        if (j) {
+                                LIST_FOREACH(by_key, j, j)
+                                        n_answer++;
+                        } else {
+                                if (hashmap_get(z->by_name, DNS_RESOURCE_KEY_NAME(q->keys[i])))
+                                        n_soa ++;
+                        }
                 }
+        }
 
-                LIST_FOREACH(by_name, j, j)
-                        n++;
+        if (n_answer <= 0 && n_soa <= 0) {
+                *ret_answer = NULL;
+                *ret_soa = NULL;
+                return 0;
         }
 
-        if (n <= 0) {
-                *ret = NULL;
-                return has_other_rrs;
+        if (n_answer > 0) {
+                answer = dns_answer_new(n_answer);
+                if (!answer)
+                        return -ENOMEM;
         }
 
-        answer = dns_answer_new(n);
-        if (!answer)
-                return -ENOMEM;
+        if (n_soa > 0) {
+                soa = dns_answer_new(n_soa);
+                if (!soa)
+                        return -ENOMEM;
+        }
 
+        /* Second iteration, actually add the RRs to the answers */
         for (i = 0; i < q->n_keys; i++) {
                 DnsZoneItem *j;
 
-                j = hashmap_get(z->by_key, q->keys[i]);
-                LIST_FOREACH(by_key, j, j) {
-                        r = dns_answer_add(answer, j->rr);
-                        if (r < 0)
-                                return r;
+                if (q->keys[i]->type == DNS_TYPE_ANY ||
+                    q->keys[i]->class == DNS_CLASS_ANY) {
+                        int k;
+
+                        j = hashmap_get(z->by_name, DNS_RESOURCE_KEY_NAME(q->keys[i]));
+                        LIST_FOREACH(by_name, j, j) {
+                                k = dns_resource_key_match_rr(q->keys[i], j->rr);
+                                if (k < 0)
+                                        return k;
+                                if (k == 0)
+                                        r = dns_answer_add_soa(soa, DNS_RESOURCE_KEY_NAME(q->keys[i]), LLMNR_DEFAULT_TTL);
+                                else
+                                        r = dns_answer_add(answer, j->rr);
+                                if (r < 0)
+                                        return r;
+                        }
+                } else {
+
+                        j = hashmap_get(z->by_key, q->keys[i]);
+                        if (j) {
+                                LIST_FOREACH(by_key, j, j) {
+                                        r = dns_answer_add(answer, j->rr);
+                                        if (r < 0)
+                                                return r;
+                                }
+                        } else {
+                                if (hashmap_get(z->by_name, DNS_RESOURCE_KEY_NAME(q->keys[i]))) {
+                                        r = dns_answer_add_soa(soa, DNS_RESOURCE_KEY_NAME(q->keys[i]), LLMNR_DEFAULT_TTL);
+                                        if (r < 0)
+                                                return r;
+                                }
+                        }
                 }
         }
 
-        *ret = answer;
+        *ret_answer = answer;
         answer = NULL;
 
+        *ret_soa = soa;
+        soa = NULL;
+
         return 1;
 }