+ dns_query_complete(q, state);
+}
+
+int dns_query_cname_redirect(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_stop(q);
+ q->state = 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;
+}
+
+int dns_query_get_rrs(DnsQuery *q, DnsResourceRecord ***rrs) {
+ int r;
+
+ assert(q);
+ assert(rrs);
+
+ if (IN_SET(q->state, DNS_QUERY_NULL, DNS_QUERY_PENDING))
+ return -EBUSY;
+
+ if (q->received) {
+ r = dns_packet_extract_rrs(q->received);
+ if (r < 0)
+ return r;
+ if (r == 0) {
+ *rrs = NULL;
+ return r;
+ }
+
+ *rrs = q->received->rrs;
+ return r;
+ }
+
+ if (q->cached_rrs) {
+ *rrs = q->cached_rrs;
+ return q->n_cached_rrs;
+ }
+
+ return -ESRCH;
+}
+
+int dns_query_get_rcode(DnsQuery *q) {
+ assert(q);
+
+ if (IN_SET(q->state, DNS_QUERY_NULL, DNS_QUERY_PENDING))
+ return -EBUSY;
+
+ if (!q->received)
+ return -ESRCH;
+
+ return DNS_PACKET_RCODE(q->received);
+}
+
+int dns_query_get_ifindex(DnsQuery *q) {
+ assert(q);
+
+ if (IN_SET(q->state, DNS_QUERY_NULL, DNS_QUERY_PENDING))
+ return -EBUSY;
+
+ if (!q->received)
+ return -ESRCH;
+
+ return q->received->ifindex;