+
+int dns_query_follow_cname(DnsQuery *q, const char *name) {
+ DnsResourceKey *keys;
+ unsigned i;
+
+ assert(q);
+
+ if (q->n_cname > CNAME_MAX)
+ return -ELOOP;
+
+ keys = new(DnsResourceKey, q->n_keys);
+ if (!keys)
+ return -ENOMEM;
+
+ for (i = 0; i < q->n_keys; i++) {
+ keys[i].class = q->keys[i].class;
+ keys[i].type = q->keys[i].type;
+ keys[i].name = strdup(name);
+ if (!keys[i].name) {
+
+ for (; i > 0; i--)
+ free(keys[i-1].name);
+ free(keys);
+ return -ENOMEM;
+ }
+ }
+
+ for (i = 0; i < q->n_keys; i++)
+ free(q->keys[i].name);
+ free(q->keys);
+
+ q->keys = keys;
+
+ q->n_cname++;
+
+ dns_query_set_state(q, DNS_QUERY_NULL);
+ return 0;
+}
+
+int dns_query_matches_rr(DnsQuery *q, DnsResourceRecord *rr) {
+ unsigned i;
+ int r;
+
+ assert(q);
+ assert(rr);
+
+ for (i = 0; i < q->n_keys; i++) {
+
+ if (rr->key.class != q->keys[i].class)
+ continue;
+
+ if (rr->key.type != q->keys[i].type &&
+ q->keys[i].type != DNS_TYPE_ANY)
+ continue;
+
+ r = dns_name_equal(rr->key.name, q->keys[i].name);
+ if (r != 0)
+ return r;
+ }
+
+ return 0;
+}
+
+int dns_query_matches_cname(DnsQuery *q, DnsResourceRecord *rr) {
+ unsigned i;
+ int r;
+
+ assert(q);
+ assert(rr);
+
+ for (i = 0; i < q->n_keys; i++) {
+
+ if (rr->key.class != q->keys[i].class)
+ continue;
+
+ if (rr->key.type != DNS_TYPE_CNAME)
+ continue;
+
+ r = dns_name_equal(rr->key.name, q->keys[i].name);
+ if (r != 0)
+ return r;
+ }
+
+ return 0;
+}