resolved: simplify dns zone logic: take a single key when looking up entries
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.
This commit is contained in:
parent
744c769375
commit
5032b16dfe
|
@ -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) {
|
void dns_scope_process_query(DnsScope *s, DnsStream *stream, DnsPacket *p) {
|
||||||
_cleanup_(dns_packet_unrefp) DnsPacket *reply = NULL;
|
_cleanup_(dns_packet_unrefp) DnsPacket *reply = NULL;
|
||||||
_cleanup_(dns_answer_unrefp) DnsAnswer *answer = NULL, *soa = NULL;
|
_cleanup_(dns_answer_unrefp) DnsAnswer *answer = NULL, *soa = NULL;
|
||||||
|
DnsResourceKey *key = NULL;
|
||||||
bool tentative = false;
|
bool tentative = false;
|
||||||
int r, fd;
|
int r, fd;
|
||||||
|
|
||||||
|
@ -576,7 +577,10 @@ void dns_scope_process_query(DnsScope *s, DnsStream *stream, DnsPacket *p) {
|
||||||
return;
|
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) {
|
if (r < 0) {
|
||||||
log_debug_errno(r, "Failed to lookup key: %m");
|
log_debug_errno(r, "Failed to lookup key: %m");
|
||||||
return;
|
return;
|
||||||
|
|
|
@ -283,97 +283,76 @@ int dns_zone_put(DnsZone *z, DnsScope *s, DnsResourceRecord *rr, bool probe) {
|
||||||
return 0;
|
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;
|
_cleanup_(dns_answer_unrefp) DnsAnswer *answer = NULL, *soa = NULL;
|
||||||
unsigned i, n_answer = 0, n_soa = 0;
|
unsigned n_answer = 0;
|
||||||
bool tentative = true;
|
DnsZoneItem *j, *first;
|
||||||
|
bool tentative = true, need_soa = false;
|
||||||
int r;
|
int r;
|
||||||
|
|
||||||
assert(z);
|
assert(z);
|
||||||
assert(q);
|
assert(key);
|
||||||
assert(ret_answer);
|
assert(ret_answer);
|
||||||
assert(ret_soa);
|
|
||||||
|
|
||||||
if (q->n_keys <= 0) {
|
|
||||||
*ret_answer = NULL;
|
|
||||||
*ret_soa = NULL;
|
|
||||||
|
|
||||||
if (ret_tentative)
|
|
||||||
*ret_tentative = false;
|
|
||||||
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* First iteration, count what we have */
|
/* First iteration, count what we have */
|
||||||
for (i = 0; i < q->n_keys; i++) {
|
|
||||||
DnsZoneItem *j, *first;
|
|
||||||
|
|
||||||
if (q->keys[i]->type == DNS_TYPE_ANY ||
|
if (key->type == DNS_TYPE_ANY || key->class == DNS_CLASS_ANY) {
|
||||||
q->keys[i]->class == DNS_CLASS_ANY) {
|
bool found = false, added = false;
|
||||||
bool found = false, added = false;
|
int k;
|
||||||
int k;
|
|
||||||
|
|
||||||
/* If this is a generic match, then we have to
|
/* If this is a generic match, then we have to
|
||||||
* go through the list by the name and look
|
* go through the list by the name and look
|
||||||
* for everything manually */
|
* for everything manually */
|
||||||
|
|
||||||
first = hashmap_get(z->by_name, DNS_RESOURCE_KEY_NAME(q->keys[i]));
|
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;
|
||||||
|
|
||||||
|
k = dns_resource_key_match_rr(key, 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 this is a specific match, then look for
|
||||||
|
* the right key immediately */
|
||||||
|
|
||||||
|
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;
|
||||||
|
|
||||||
|
found = true;
|
||||||
|
n_answer++;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!found) {
|
||||||
|
first = hashmap_get(z->by_name, DNS_RESOURCE_KEY_NAME(key));
|
||||||
LIST_FOREACH(by_name, j, first) {
|
LIST_FOREACH(by_name, j, first) {
|
||||||
if (!IN_SET(j->state, DNS_ZONE_ITEM_PROBING, DNS_ZONE_ITEM_ESTABLISHED, DNS_ZONE_ITEM_VERIFYING))
|
if (!IN_SET(j->state, DNS_ZONE_ITEM_PROBING, DNS_ZONE_ITEM_ESTABLISHED, DNS_ZONE_ITEM_VERIFYING))
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
found = true;
|
need_soa = true;
|
||||||
|
break;
|
||||||
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)
|
|
||||||
n_soa++;
|
|
||||||
|
|
||||||
} else {
|
|
||||||
bool found = false;
|
|
||||||
|
|
||||||
/* If this is a specific match, then look for
|
|
||||||
* the right key immediately */
|
|
||||||
|
|
||||||
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;
|
|
||||||
|
|
||||||
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;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (n_answer <= 0 && n_soa <= 0) {
|
if (n_answer <= 0 && !need_soa)
|
||||||
*ret_answer = NULL;
|
goto return_empty;
|
||||||
*ret_soa = NULL;
|
|
||||||
|
|
||||||
if (ret_tentative)
|
|
||||||
*ret_tentative = false;
|
|
||||||
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (n_answer > 0) {
|
if (n_answer > 0) {
|
||||||
answer = dns_answer_new(n_answer);
|
answer = dns_answer_new(n_answer);
|
||||||
|
@ -381,99 +360,113 @@ int dns_zone_lookup(DnsZone *z, DnsQuestion *q, DnsAnswer **ret_answer, DnsAnswe
|
||||||
return -ENOMEM;
|
return -ENOMEM;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (n_soa > 0) {
|
if (need_soa) {
|
||||||
soa = dns_answer_new(n_soa);
|
soa = dns_answer_new(1);
|
||||||
if (!soa)
|
if (!soa)
|
||||||
return -ENOMEM;
|
return -ENOMEM;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Second iteration, actually add the RRs to the answers */
|
/* Second iteration, actually add the RRs to the answers */
|
||||||
for (i = 0; i < q->n_keys; i++) {
|
if (key->type == DNS_TYPE_ANY || key->class == DNS_CLASS_ANY) {
|
||||||
DnsZoneItem *j, *first;
|
bool found = false, added = false;
|
||||||
|
int k;
|
||||||
|
|
||||||
if (q->keys[i]->type == DNS_TYPE_ANY ||
|
first = hashmap_get(z->by_name, DNS_RESOURCE_KEY_NAME(key));
|
||||||
q->keys[i]->class == DNS_CLASS_ANY) {
|
LIST_FOREACH(by_name, j, first) {
|
||||||
bool found = false, added = false;
|
if (!IN_SET(j->state, DNS_ZONE_ITEM_PROBING, DNS_ZONE_ITEM_ESTABLISHED, DNS_ZONE_ITEM_VERIFYING))
|
||||||
int k;
|
continue;
|
||||||
|
|
||||||
first = hashmap_get(z->by_name, DNS_RESOURCE_KEY_NAME(q->keys[i]));
|
found = true;
|
||||||
|
|
||||||
|
if (j->state != DNS_ZONE_ITEM_PROBING)
|
||||||
|
tentative = false;
|
||||||
|
|
||||||
|
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;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
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;
|
||||||
|
|
||||||
|
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;
|
||||||
|
|
||||||
|
found = true;
|
||||||
|
|
||||||
|
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;
|
||||||
|
|
||||||
|
first = hashmap_get(z->by_name, DNS_RESOURCE_KEY_NAME(key));
|
||||||
LIST_FOREACH(by_name, j, first) {
|
LIST_FOREACH(by_name, j, first) {
|
||||||
if (!IN_SET(j->state, DNS_ZONE_ITEM_PROBING, DNS_ZONE_ITEM_ESTABLISHED, DNS_ZONE_ITEM_VERIFYING))
|
if (!IN_SET(j->state, DNS_ZONE_ITEM_PROBING, DNS_ZONE_ITEM_ESTABLISHED, DNS_ZONE_ITEM_VERIFYING))
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
found = true;
|
|
||||||
|
|
||||||
if (j->state != DNS_ZONE_ITEM_PROBING)
|
if (j->state != DNS_ZONE_ITEM_PROBING)
|
||||||
tentative = false;
|
tentative = false;
|
||||||
|
|
||||||
k = dns_resource_key_match_rr(q->keys[i], j->rr);
|
add_soa = true;
|
||||||
if (k < 0)
|
|
||||||
return k;
|
|
||||||
if (k > 0) {
|
|
||||||
r = dns_answer_add(answer, j->rr, 0);
|
|
||||||
if (r < 0)
|
|
||||||
return r;
|
|
||||||
|
|
||||||
added = true;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (found && !added) {
|
if (add_soa) {
|
||||||
r = dns_answer_add_soa(soa, DNS_RESOURCE_KEY_NAME(q->keys[i]), LLMNR_DEFAULT_TTL);
|
r = dns_answer_add_soa(soa, DNS_RESOURCE_KEY_NAME(key), LLMNR_DEFAULT_TTL);
|
||||||
if (r < 0)
|
if (r < 0)
|
||||||
return r;
|
return r;
|
||||||
}
|
}
|
||||||
} 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;
|
|
||||||
|
|
||||||
found = true;
|
|
||||||
|
|
||||||
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;
|
|
||||||
|
|
||||||
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;
|
|
||||||
|
|
||||||
if (j->state != DNS_ZONE_ITEM_PROBING)
|
|
||||||
tentative = false;
|
|
||||||
|
|
||||||
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 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;
|
*ret_answer = answer;
|
||||||
answer = NULL;
|
answer = NULL;
|
||||||
|
|
||||||
*ret_soa = soa;
|
if (ret_soa) {
|
||||||
soa = NULL;
|
*ret_soa = soa;
|
||||||
|
soa = NULL;
|
||||||
|
}
|
||||||
|
|
||||||
if (ret_tentative)
|
if (ret_tentative)
|
||||||
*ret_tentative = tentative;
|
*ret_tentative = tentative;
|
||||||
|
|
||||||
return 1;
|
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) {
|
void dns_zone_item_conflict(DnsZoneItem *i) {
|
||||||
|
|
|
@ -67,7 +67,7 @@ void dns_zone_flush(DnsZone *z);
|
||||||
int dns_zone_put(DnsZone *z, DnsScope *s, DnsResourceRecord *rr, bool probe);
|
int dns_zone_put(DnsZone *z, DnsScope *s, DnsResourceRecord *rr, bool probe);
|
||||||
void dns_zone_remove_rr(DnsZone *z, DnsResourceRecord *rr);
|
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_conflict(DnsZoneItem *i);
|
||||||
void dns_zone_item_ready(DnsZoneItem *i);
|
void dns_zone_item_ready(DnsZoneItem *i);
|
||||||
|
|
Loading…
Reference in a new issue