X-Git-Url: http://www.chiark.greenend.org.uk/ucgi/~ianmdlvl/git?a=blobdiff_plain;f=src%2Fresolve%2Fresolved-dns-answer.c;h=7c4ab18b5835f97ce8210976340d4365e9441268;hb=0e3434aeb1eed951fdbeddacc6126e10d82a1c8b;hp=d90766452747adfb0d8dcfaa886be5d1fee8f578;hpb=934e9b10b4f4bfb48e21883670c7f45b6911fa9b;p=elogind.git diff --git a/src/resolve/resolved-dns-answer.c b/src/resolve/resolved-dns-answer.c index d90766452..7c4ab18b5 100644 --- a/src/resolve/resolved-dns-answer.c +++ b/src/resolve/resolved-dns-answer.c @@ -97,6 +97,32 @@ int dns_answer_add(DnsAnswer *a, DnsResourceRecord *rr) { return 1; } +int dns_answer_add_soa(DnsAnswer *a, const char *name, uint32_t ttl) { + _cleanup_(dns_resource_record_unrefp) DnsResourceRecord *soa = NULL; + + soa = dns_resource_record_new_full(DNS_CLASS_IN, DNS_TYPE_SOA, name); + if (!soa) + return -ENOMEM; + + soa->ttl = ttl; + + soa->soa.mname = strdup(name); + if (!soa->soa.mname) + return -ENOMEM; + + soa->soa.rname = strappend("root.", name); + if (!soa->soa.rname) + return -ENOMEM; + + soa->soa.serial = 1; + soa->soa.refresh = 1; + soa->soa.retry = 1; + soa->soa.expire = 1; + soa->soa.minimum = ttl; + + return dns_answer_add(a, soa); +} + int dns_answer_contains(DnsAnswer *a, DnsResourceKey *key) { unsigned i; int r; @@ -122,6 +148,10 @@ int dns_answer_find_soa(DnsAnswer *a, DnsResourceKey *key, DnsResourceRecord **r assert(key); assert(ret); + /* For a SOA record we can never find a matching SOA record */ + if (key->type == DNS_TYPE_SOA) + return 0; + for (i = 0; i < a->n_rrs; i++) { if (a->rrs[i]->key->class != DNS_CLASS_IN) @@ -175,3 +205,34 @@ DnsAnswer *dns_answer_merge(DnsAnswer *a, DnsAnswer *b) { return k; } + +void dns_answer_order_by_scope(DnsAnswer *a, bool prefer_link_local) { + DnsResourceRecord **rrs; + unsigned i, start, end; + assert(a); + + if (a->n_rrs <= 1) + return; + + start = 0; + end = a->n_rrs-1; + + /* RFC 4795, Section 2.6 suggests we should order entries + * depending on whether the sender is a link-local address. */ + + rrs = newa(DnsResourceRecord*, a->n_rrs); + for (i = 0; i < a->n_rrs; i++) { + + if (a->rrs[i]->key->class == DNS_CLASS_IN && + ((a->rrs[i]->key->type == DNS_TYPE_A && in_addr_is_link_local(AF_INET, (union in_addr_union*) &a->rrs[i]->a.in_addr) != prefer_link_local) || + (a->rrs[i]->key->type == DNS_TYPE_AAAA && in_addr_is_link_local(AF_INET6, (union in_addr_union*) &a->rrs[i]->aaaa.in6_addr) != prefer_link_local))) + /* Order address records that are are not preferred to the end of the array */ + rrs[end--] = a->rrs[i]; + else + /* Order all other records to the beginning of the array */ + rrs[start++] = a->rrs[i]; + } + + assert(start == end+1); + memcpy(a->rrs, rrs, sizeof(DnsResourceRecord*) * a->n_rrs); +}