X-Git-Url: http://www.chiark.greenend.org.uk/ucgi/~ianmdlvl/git?p=elogind.git;a=blobdiff_plain;f=src%2Fresolve%2Fresolved-dns-zone.c;h=b51f503df8c1c39ebd852e389ba80aef89b62f66;hp=2325ddfe7fc51c3f9639540c160a072a3681b515;hb=2d4c5cbc0ed3ccb09dc086a040088b454c22c644;hpb=623a4c97b9175f95c4b1c6fc34e36c56f1e4ddbf diff --git a/src/resolve/resolved-dns-zone.c b/src/resolve/resolved-dns-zone.c index 2325ddfe7..b51f503df 100644 --- a/src/resolve/resolved-dns-zone.c +++ b/src/resolve/resolved-dns-zone.c @@ -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])); + 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])); + if (r < 0) + return r; + } + } } } - *ret = answer; + *ret_answer = answer; answer = NULL; + *ret_soa = soa; + soa = NULL; + return 1; }