resolved-dns-question.c revision 0f7091e624fdba6c0bf281f2a9a23cd3e9ca93fb
b44cd8821087f2afebf85fec5b588f5720a9415cTom Gundersen/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
b44cd8821087f2afebf85fec5b588f5720a9415cTom Gundersen
b44cd8821087f2afebf85fec5b588f5720a9415cTom Gundersen/***
b44cd8821087f2afebf85fec5b588f5720a9415cTom Gundersen This file is part of systemd.
b44cd8821087f2afebf85fec5b588f5720a9415cTom Gundersen
b44cd8821087f2afebf85fec5b588f5720a9415cTom Gundersen Copyright 2014 Lennart Poettering
b44cd8821087f2afebf85fec5b588f5720a9415cTom Gundersen
b44cd8821087f2afebf85fec5b588f5720a9415cTom Gundersen systemd is free software; you can redistribute it and/or modify it
b44cd8821087f2afebf85fec5b588f5720a9415cTom Gundersen under the terms of the GNU Lesser General Public License as published by
b44cd8821087f2afebf85fec5b588f5720a9415cTom Gundersen the Free Software Foundation; either version 2.1 of the License, or
b44cd8821087f2afebf85fec5b588f5720a9415cTom Gundersen (at your option) any later version.
b44cd8821087f2afebf85fec5b588f5720a9415cTom Gundersen
b44cd8821087f2afebf85fec5b588f5720a9415cTom Gundersen systemd is distributed in the hope that it will be useful, but
b44cd8821087f2afebf85fec5b588f5720a9415cTom Gundersen WITHOUT ANY WARRANTY; without even the implied warranty of
b44cd8821087f2afebf85fec5b588f5720a9415cTom Gundersen MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
b44cd8821087f2afebf85fec5b588f5720a9415cTom Gundersen Lesser General Public License for more details.
b44cd8821087f2afebf85fec5b588f5720a9415cTom Gundersen
b44cd8821087f2afebf85fec5b588f5720a9415cTom Gundersen You should have received a copy of the GNU Lesser General Public License
b44cd8821087f2afebf85fec5b588f5720a9415cTom Gundersen along with systemd; If not, see <http://www.gnu.org/licenses/>.
b44cd8821087f2afebf85fec5b588f5720a9415cTom Gundersen***/
b44cd8821087f2afebf85fec5b588f5720a9415cTom Gundersen
b44cd8821087f2afebf85fec5b588f5720a9415cTom Gundersen#include "alloc-util.h"
ff734080aa02cd70b13bc0fdeec4a5886166163aTom Gundersen#include "dns-domain.h"
ff734080aa02cd70b13bc0fdeec4a5886166163aTom Gundersen#include "dns-type.h"
99634696183dfabae20104e58157c69029a11594Tom Gundersen#include "resolved-dns-question.h"
87322b3aee0dc649ff1ae7a403dcc9d7305baba2Tom Gundersen
87322b3aee0dc649ff1ae7a403dcc9d7305baba2Tom GundersenDnsQuestion *dns_question_new(unsigned n) {
b44cd8821087f2afebf85fec5b588f5720a9415cTom Gundersen DnsQuestion *q;
b44cd8821087f2afebf85fec5b588f5720a9415cTom Gundersen
ff734080aa02cd70b13bc0fdeec4a5886166163aTom Gundersen assert(n > 0);
b44cd8821087f2afebf85fec5b588f5720a9415cTom Gundersen
586ac6f711e2eccceb12421df22fca4f117226c4Lennart Poettering q = malloc0(offsetof(DnsQuestion, keys) + sizeof(DnsResourceKey*) * n);
586ac6f711e2eccceb12421df22fca4f117226c4Lennart Poettering if (!q)
4dc355680460fdc8e0d590d8572dff1b6a257d88Tom Gundersen return NULL;
99634696183dfabae20104e58157c69029a11594Tom Gundersen
99634696183dfabae20104e58157c69029a11594Tom Gundersen q->n_ref = 1;
99634696183dfabae20104e58157c69029a11594Tom Gundersen q->n_allocated = n;
99634696183dfabae20104e58157c69029a11594Tom Gundersen
99634696183dfabae20104e58157c69029a11594Tom Gundersen return q;
99634696183dfabae20104e58157c69029a11594Tom Gundersen}
99634696183dfabae20104e58157c69029a11594Tom Gundersen
99634696183dfabae20104e58157c69029a11594Tom GundersenDnsQuestion *dns_question_ref(DnsQuestion *q) {
99634696183dfabae20104e58157c69029a11594Tom Gundersen if (!q)
2dead8129f7b6fe644e17e1dc1739bebacfe1364Tom Gundersen return NULL;
2dead8129f7b6fe644e17e1dc1739bebacfe1364Tom Gundersen
99634696183dfabae20104e58157c69029a11594Tom Gundersen assert(q->n_ref > 0);
99634696183dfabae20104e58157c69029a11594Tom Gundersen q->n_ref++;
99634696183dfabae20104e58157c69029a11594Tom Gundersen return q;
99634696183dfabae20104e58157c69029a11594Tom Gundersen}
99634696183dfabae20104e58157c69029a11594Tom Gundersen
99634696183dfabae20104e58157c69029a11594Tom GundersenDnsQuestion *dns_question_unref(DnsQuestion *q) {
99634696183dfabae20104e58157c69029a11594Tom Gundersen if (!q)
99634696183dfabae20104e58157c69029a11594Tom Gundersen return NULL;
99634696183dfabae20104e58157c69029a11594Tom Gundersen
99634696183dfabae20104e58157c69029a11594Tom Gundersen assert(q->n_ref > 0);
99634696183dfabae20104e58157c69029a11594Tom Gundersen
99634696183dfabae20104e58157c69029a11594Tom Gundersen if (q->n_ref == 1) {
99634696183dfabae20104e58157c69029a11594Tom Gundersen unsigned i;
99634696183dfabae20104e58157c69029a11594Tom Gundersen
99634696183dfabae20104e58157c69029a11594Tom Gundersen for (i = 0; i < q->n_keys; i++)
99634696183dfabae20104e58157c69029a11594Tom Gundersen dns_resource_key_unref(q->keys[i]);
99634696183dfabae20104e58157c69029a11594Tom Gundersen free(q);
99634696183dfabae20104e58157c69029a11594Tom Gundersen } else
99634696183dfabae20104e58157c69029a11594Tom Gundersen q->n_ref--;
99634696183dfabae20104e58157c69029a11594Tom Gundersen
99634696183dfabae20104e58157c69029a11594Tom Gundersen return NULL;
99634696183dfabae20104e58157c69029a11594Tom Gundersen}
99634696183dfabae20104e58157c69029a11594Tom Gundersen
99634696183dfabae20104e58157c69029a11594Tom Gundersenint dns_question_add(DnsQuestion *q, DnsResourceKey *key) {
99634696183dfabae20104e58157c69029a11594Tom Gundersen unsigned i;
99634696183dfabae20104e58157c69029a11594Tom Gundersen int r;
99634696183dfabae20104e58157c69029a11594Tom Gundersen
99634696183dfabae20104e58157c69029a11594Tom Gundersen assert(key);
99634696183dfabae20104e58157c69029a11594Tom Gundersen
99634696183dfabae20104e58157c69029a11594Tom Gundersen if (!q)
99634696183dfabae20104e58157c69029a11594Tom Gundersen return -ENOSPC;
99634696183dfabae20104e58157c69029a11594Tom Gundersen
87322b3aee0dc649ff1ae7a403dcc9d7305baba2Tom Gundersen for (i = 0; i < q->n_keys; i++) {
87322b3aee0dc649ff1ae7a403dcc9d7305baba2Tom Gundersen r = dns_resource_key_equal(q->keys[i], key);
87322b3aee0dc649ff1ae7a403dcc9d7305baba2Tom Gundersen if (r < 0)
87322b3aee0dc649ff1ae7a403dcc9d7305baba2Tom Gundersen return r;
2dead8129f7b6fe644e17e1dc1739bebacfe1364Tom Gundersen if (r > 0)
99634696183dfabae20104e58157c69029a11594Tom Gundersen return 0;
2dead8129f7b6fe644e17e1dc1739bebacfe1364Tom Gundersen }
2dead8129f7b6fe644e17e1dc1739bebacfe1364Tom Gundersen
20af7091de0cdf92bf299addfc3f96c3ef805bd8Tom Gundersen if (q->n_keys >= q->n_allocated)
99634696183dfabae20104e58157c69029a11594Tom Gundersen return -ENOSPC;
99634696183dfabae20104e58157c69029a11594Tom Gundersen
99634696183dfabae20104e58157c69029a11594Tom Gundersen q->keys[q->n_keys++] = dns_resource_key_ref(key);
99634696183dfabae20104e58157c69029a11594Tom Gundersen return 0;
99634696183dfabae20104e58157c69029a11594Tom Gundersen}
20af7091de0cdf92bf299addfc3f96c3ef805bd8Tom Gundersen
20af7091de0cdf92bf299addfc3f96c3ef805bd8Tom Gundersenint dns_question_matches_rr(DnsQuestion *q, DnsResourceRecord *rr, const char *search_domain) {
20af7091de0cdf92bf299addfc3f96c3ef805bd8Tom Gundersen unsigned i;
20af7091de0cdf92bf299addfc3f96c3ef805bd8Tom Gundersen int r;
7c16313f11e3953f3fe4dbf544f2d36f58d14138Tom Gundersen
756775814cf69471f74ce853745bba69f2ba94efThomas Hindoe Paaboel Andersen assert(rr);
7c16313f11e3953f3fe4dbf544f2d36f58d14138Tom Gundersen
7c16313f11e3953f3fe4dbf544f2d36f58d14138Tom Gundersen if (!q)
7c16313f11e3953f3fe4dbf544f2d36f58d14138Tom Gundersen return 0;
7c16313f11e3953f3fe4dbf544f2d36f58d14138Tom Gundersen
b44cd8821087f2afebf85fec5b588f5720a9415cTom Gundersen for (i = 0; i < q->n_keys; i++) {
3733eec3e292e4ddb4cba5eb8d3bd8cbee7102d8Lennart Poettering r = dns_resource_key_match_rr(q->keys[i], rr, search_domain);
3733eec3e292e4ddb4cba5eb8d3bd8cbee7102d8Lennart Poettering if (r != 0)
3733eec3e292e4ddb4cba5eb8d3bd8cbee7102d8Lennart Poettering return r;
3733eec3e292e4ddb4cba5eb8d3bd8cbee7102d8Lennart Poettering }
3733eec3e292e4ddb4cba5eb8d3bd8cbee7102d8Lennart Poettering
3733eec3e292e4ddb4cba5eb8d3bd8cbee7102d8Lennart Poettering return 0;
b44cd8821087f2afebf85fec5b588f5720a9415cTom Gundersen}
b44cd8821087f2afebf85fec5b588f5720a9415cTom Gundersen
b44cd8821087f2afebf85fec5b588f5720a9415cTom Gundersenint dns_question_matches_cname(DnsQuestion *q, DnsResourceRecord *rr, const char *search_domain) {
b44cd8821087f2afebf85fec5b588f5720a9415cTom Gundersen unsigned i;
b826ab586c9e0a9c0d438a75c28cf3a8ab485929Tom Gundersen int r;
87322b3aee0dc649ff1ae7a403dcc9d7305baba2Tom Gundersen
87322b3aee0dc649ff1ae7a403dcc9d7305baba2Tom Gundersen assert(rr);
87322b3aee0dc649ff1ae7a403dcc9d7305baba2Tom Gundersen
87322b3aee0dc649ff1ae7a403dcc9d7305baba2Tom Gundersen if (!q)
87322b3aee0dc649ff1ae7a403dcc9d7305baba2Tom Gundersen return 0;
87322b3aee0dc649ff1ae7a403dcc9d7305baba2Tom Gundersen
b826ab586c9e0a9c0d438a75c28cf3a8ab485929Tom Gundersen for (i = 0; i < q->n_keys; i++) {
87322b3aee0dc649ff1ae7a403dcc9d7305baba2Tom Gundersen r = dns_resource_key_match_cname_or_dname(q->keys[i], rr->key, search_domain);
87322b3aee0dc649ff1ae7a403dcc9d7305baba2Tom Gundersen if (r != 0)
87322b3aee0dc649ff1ae7a403dcc9d7305baba2Tom Gundersen return r;
87322b3aee0dc649ff1ae7a403dcc9d7305baba2Tom Gundersen }
87322b3aee0dc649ff1ae7a403dcc9d7305baba2Tom Gundersen
87322b3aee0dc649ff1ae7a403dcc9d7305baba2Tom Gundersen return 0;
87322b3aee0dc649ff1ae7a403dcc9d7305baba2Tom Gundersen}
87322b3aee0dc649ff1ae7a403dcc9d7305baba2Tom Gundersen
87322b3aee0dc649ff1ae7a403dcc9d7305baba2Tom Gundersenint dns_question_is_valid_for_query(DnsQuestion *q) {
87322b3aee0dc649ff1ae7a403dcc9d7305baba2Tom Gundersen const char *name;
87322b3aee0dc649ff1ae7a403dcc9d7305baba2Tom Gundersen unsigned i;
87322b3aee0dc649ff1ae7a403dcc9d7305baba2Tom Gundersen int r;
87322b3aee0dc649ff1ae7a403dcc9d7305baba2Tom Gundersen
87322b3aee0dc649ff1ae7a403dcc9d7305baba2Tom Gundersen if (!q)
87322b3aee0dc649ff1ae7a403dcc9d7305baba2Tom Gundersen return 0;
87322b3aee0dc649ff1ae7a403dcc9d7305baba2Tom Gundersen
87322b3aee0dc649ff1ae7a403dcc9d7305baba2Tom Gundersen if (q->n_keys <= 0)
d5099efc47d4e6ac60816b5381a5f607ab03f06eMichal Schmidt return 0;
d5099efc47d4e6ac60816b5381a5f607ab03f06eMichal Schmidt
d5099efc47d4e6ac60816b5381a5f607ab03f06eMichal Schmidt if (q->n_keys > 65535)
d5099efc47d4e6ac60816b5381a5f607ab03f06eMichal Schmidt return 0;
d5099efc47d4e6ac60816b5381a5f607ab03f06eMichal Schmidt
87322b3aee0dc649ff1ae7a403dcc9d7305baba2Tom Gundersen name = DNS_RESOURCE_KEY_NAME(q->keys[0]);
87322b3aee0dc649ff1ae7a403dcc9d7305baba2Tom Gundersen if (!name)
87322b3aee0dc649ff1ae7a403dcc9d7305baba2Tom Gundersen return 0;
87322b3aee0dc649ff1ae7a403dcc9d7305baba2Tom Gundersen
87322b3aee0dc649ff1ae7a403dcc9d7305baba2Tom Gundersen /* Check that all keys in this question bear the same name */
87322b3aee0dc649ff1ae7a403dcc9d7305baba2Tom Gundersen for (i = 0; i < q->n_keys; i++) {
87322b3aee0dc649ff1ae7a403dcc9d7305baba2Tom Gundersen assert(q->keys[i]);
87322b3aee0dc649ff1ae7a403dcc9d7305baba2Tom Gundersen
b44cd8821087f2afebf85fec5b588f5720a9415cTom Gundersen if (i > 0) {
3bdace9bf779ce051f00c14914b35c3a26164aa9Lennart Poettering r = dns_name_equal(DNS_RESOURCE_KEY_NAME(q->keys[i]), name);
87322b3aee0dc649ff1ae7a403dcc9d7305baba2Tom Gundersen if (r <= 0)
3bdace9bf779ce051f00c14914b35c3a26164aa9Lennart Poettering return r;
3bdace9bf779ce051f00c14914b35c3a26164aa9Lennart Poettering }
b44cd8821087f2afebf85fec5b588f5720a9415cTom Gundersen
3733eec3e292e4ddb4cba5eb8d3bd8cbee7102d8Lennart Poettering if (!dns_type_is_valid_query(q->keys[i]->type))
3733eec3e292e4ddb4cba5eb8d3bd8cbee7102d8Lennart Poettering return 0;
3733eec3e292e4ddb4cba5eb8d3bd8cbee7102d8Lennart Poettering }
3733eec3e292e4ddb4cba5eb8d3bd8cbee7102d8Lennart Poettering
3bdace9bf779ce051f00c14914b35c3a26164aa9Lennart Poettering return 1;
ff734080aa02cd70b13bc0fdeec4a5886166163aTom Gundersen}
3bdace9bf779ce051f00c14914b35c3a26164aa9Lennart Poettering
87322b3aee0dc649ff1ae7a403dcc9d7305baba2Tom Gundersenint dns_question_contains(DnsQuestion *a, const DnsResourceKey *k) {
3bdace9bf779ce051f00c14914b35c3a26164aa9Lennart Poettering unsigned j;
87322b3aee0dc649ff1ae7a403dcc9d7305baba2Tom Gundersen int r;
3bdace9bf779ce051f00c14914b35c3a26164aa9Lennart Poettering
3bdace9bf779ce051f00c14914b35c3a26164aa9Lennart Poettering assert(k);
8eb9058dc1f99a5eb9b8726a978fcc0720837a10Lennart Poettering
1a04db0fc9d08fffe80d6d7b5b60459295922b11Lennart Poettering if (!a)
1a04db0fc9d08fffe80d6d7b5b60459295922b11Lennart Poettering return 0;
8eb9058dc1f99a5eb9b8726a978fcc0720837a10Lennart Poettering
3bdace9bf779ce051f00c14914b35c3a26164aa9Lennart Poettering for (j = 0; j < a->n_keys; j++) {
3bdace9bf779ce051f00c14914b35c3a26164aa9Lennart Poettering r = dns_resource_key_equal(a->keys[j], k);
3bdace9bf779ce051f00c14914b35c3a26164aa9Lennart Poettering if (r != 0)
3bdace9bf779ce051f00c14914b35c3a26164aa9Lennart Poettering return r;
3bdace9bf779ce051f00c14914b35c3a26164aa9Lennart Poettering }
3bdace9bf779ce051f00c14914b35c3a26164aa9Lennart Poettering
b44cd8821087f2afebf85fec5b588f5720a9415cTom Gundersen return 0;
b44cd8821087f2afebf85fec5b588f5720a9415cTom Gundersen}
b44cd8821087f2afebf85fec5b588f5720a9415cTom Gundersen
b44cd8821087f2afebf85fec5b588f5720a9415cTom Gundersenint dns_question_is_equal(DnsQuestion *a, DnsQuestion *b) {
3a864fe4a894745ac61f1ecabd7cadf04139a284Tom Gundersen unsigned j;
b44cd8821087f2afebf85fec5b588f5720a9415cTom Gundersen int r;
b44cd8821087f2afebf85fec5b588f5720a9415cTom Gundersen
b44cd8821087f2afebf85fec5b588f5720a9415cTom Gundersen if (!a)
3a864fe4a894745ac61f1ecabd7cadf04139a284Tom Gundersen return !b || b->n_keys == 0;
b44cd8821087f2afebf85fec5b588f5720a9415cTom Gundersen if (!b)
b44cd8821087f2afebf85fec5b588f5720a9415cTom Gundersen return a->n_keys == 0;
b44cd8821087f2afebf85fec5b588f5720a9415cTom Gundersen
b44cd8821087f2afebf85fec5b588f5720a9415cTom Gundersen /* Checks if all keys in a are also contained b, and vice versa */
b44cd8821087f2afebf85fec5b588f5720a9415cTom Gundersen
3733eec3e292e4ddb4cba5eb8d3bd8cbee7102d8Lennart Poettering for (j = 0; j < a->n_keys; j++) {
8de4a226c71ef43e652274b33b5d19211a44ac7bTom Gundersen r = dns_question_contains(b, a->keys[j]);
ff734080aa02cd70b13bc0fdeec4a5886166163aTom Gundersen if (r <= 0)
20af7091de0cdf92bf299addfc3f96c3ef805bd8Tom Gundersen return r;
59b8f6b628145586e87b8a4f6e29c755ad7d61edTom Gundersen }
b3ec603ce8053ba3f95da1d36f15ea762c83d1e1Lennart Poettering
d5099efc47d4e6ac60816b5381a5f607ab03f06eMichal Schmidt for (j = 0; j < b->n_keys; j++) {
586ac6f711e2eccceb12421df22fca4f117226c4Lennart Poettering r = dns_question_contains(a, b->keys[j]);
586ac6f711e2eccceb12421df22fca4f117226c4Lennart Poettering if (r <= 0)
b44cd8821087f2afebf85fec5b588f5720a9415cTom Gundersen return r;
b44cd8821087f2afebf85fec5b588f5720a9415cTom Gundersen }
b44cd8821087f2afebf85fec5b588f5720a9415cTom Gundersen
b44cd8821087f2afebf85fec5b588f5720a9415cTom Gundersen return 1;
b44cd8821087f2afebf85fec5b588f5720a9415cTom Gundersen}
b44cd8821087f2afebf85fec5b588f5720a9415cTom Gundersen
b44cd8821087f2afebf85fec5b588f5720a9415cTom Gundersenint dns_question_cname_redirect(DnsQuestion *q, const DnsResourceRecord *cname, DnsQuestion **ret) {
a6f1e036de8f212f33ead7f5387c297afd8be26eTom Gundersen _cleanup_(dns_question_unrefp) DnsQuestion *n = NULL;
a6f1e036de8f212f33ead7f5387c297afd8be26eTom Gundersen bool same = true;
b44cd8821087f2afebf85fec5b588f5720a9415cTom Gundersen unsigned i;
b44cd8821087f2afebf85fec5b588f5720a9415cTom Gundersen int r;
b44cd8821087f2afebf85fec5b588f5720a9415cTom Gundersen
b44cd8821087f2afebf85fec5b588f5720a9415cTom Gundersen assert(cname);
b44cd8821087f2afebf85fec5b588f5720a9415cTom Gundersen assert(ret);
b44cd8821087f2afebf85fec5b588f5720a9415cTom Gundersen assert(IN_SET(cname->key->type, DNS_TYPE_CNAME, DNS_TYPE_DNAME));
b44cd8821087f2afebf85fec5b588f5720a9415cTom Gundersen
b44cd8821087f2afebf85fec5b588f5720a9415cTom Gundersen if (!q) {
b44cd8821087f2afebf85fec5b588f5720a9415cTom Gundersen n = dns_question_new(0);
b44cd8821087f2afebf85fec5b588f5720a9415cTom Gundersen if (!n)
b44cd8821087f2afebf85fec5b588f5720a9415cTom Gundersen return -ENOMEM;
b44cd8821087f2afebf85fec5b588f5720a9415cTom Gundersen
b44cd8821087f2afebf85fec5b588f5720a9415cTom Gundersen *ret = n;
b44cd8821087f2afebf85fec5b588f5720a9415cTom Gundersen n = 0;
b44cd8821087f2afebf85fec5b588f5720a9415cTom Gundersen return 0;
b44cd8821087f2afebf85fec5b588f5720a9415cTom Gundersen }
b44cd8821087f2afebf85fec5b588f5720a9415cTom Gundersen
b44cd8821087f2afebf85fec5b588f5720a9415cTom Gundersen for (i = 0; i < q->n_keys; i++) {
b44cd8821087f2afebf85fec5b588f5720a9415cTom Gundersen _cleanup_free_ char *destination = NULL;
b44cd8821087f2afebf85fec5b588f5720a9415cTom Gundersen const char *d;
b44cd8821087f2afebf85fec5b588f5720a9415cTom Gundersen
b44cd8821087f2afebf85fec5b588f5720a9415cTom Gundersen if (cname->key->type == DNS_TYPE_CNAME)
b44cd8821087f2afebf85fec5b588f5720a9415cTom Gundersen d = cname->cname.name;
b44cd8821087f2afebf85fec5b588f5720a9415cTom Gundersen else {
b44cd8821087f2afebf85fec5b588f5720a9415cTom Gundersen r = dns_name_change_suffix(DNS_RESOURCE_KEY_NAME(q->keys[i]), DNS_RESOURCE_KEY_NAME(cname->key), cname->dname.name, &destination);
b44cd8821087f2afebf85fec5b588f5720a9415cTom Gundersen if (r < 0)
b44cd8821087f2afebf85fec5b588f5720a9415cTom Gundersen return r;
b44cd8821087f2afebf85fec5b588f5720a9415cTom Gundersen if (r == 0)
b44cd8821087f2afebf85fec5b588f5720a9415cTom Gundersen continue;
b44cd8821087f2afebf85fec5b588f5720a9415cTom Gundersen
b44cd8821087f2afebf85fec5b588f5720a9415cTom Gundersen d = destination;
ff734080aa02cd70b13bc0fdeec4a5886166163aTom Gundersen }
ff734080aa02cd70b13bc0fdeec4a5886166163aTom Gundersen
ff734080aa02cd70b13bc0fdeec4a5886166163aTom Gundersen r = dns_name_equal(DNS_RESOURCE_KEY_NAME(q->keys[i]), d);
ff734080aa02cd70b13bc0fdeec4a5886166163aTom Gundersen if (r < 0)
ff734080aa02cd70b13bc0fdeec4a5886166163aTom Gundersen return r;
ff734080aa02cd70b13bc0fdeec4a5886166163aTom Gundersen
ff734080aa02cd70b13bc0fdeec4a5886166163aTom Gundersen if (r == 0) {
8de4a226c71ef43e652274b33b5d19211a44ac7bTom Gundersen same = false;
ff734080aa02cd70b13bc0fdeec4a5886166163aTom Gundersen break;
ff734080aa02cd70b13bc0fdeec4a5886166163aTom Gundersen }
ff734080aa02cd70b13bc0fdeec4a5886166163aTom Gundersen }
ff734080aa02cd70b13bc0fdeec4a5886166163aTom Gundersen
ff734080aa02cd70b13bc0fdeec4a5886166163aTom Gundersen if (same) {
ff734080aa02cd70b13bc0fdeec4a5886166163aTom Gundersen /* Shortcut, the names are already right */
ff734080aa02cd70b13bc0fdeec4a5886166163aTom Gundersen *ret = dns_question_ref(q);
a6f1e036de8f212f33ead7f5387c297afd8be26eTom Gundersen return 0;
a6f1e036de8f212f33ead7f5387c297afd8be26eTom Gundersen }
969b009d9416806911b9b52e7e7bc619c0c1a931Tom Gundersen
969b009d9416806911b9b52e7e7bc619c0c1a931Tom Gundersen n = dns_question_new(q->n_keys);
969b009d9416806911b9b52e7e7bc619c0c1a931Tom Gundersen if (!n)
b3ec603ce8053ba3f95da1d36f15ea762c83d1e1Lennart Poettering return -ENOMEM;
969b009d9416806911b9b52e7e7bc619c0c1a931Tom Gundersen
969b009d9416806911b9b52e7e7bc619c0c1a931Tom Gundersen /* Create a new question, and patch in the new name */
969b009d9416806911b9b52e7e7bc619c0c1a931Tom Gundersen for (i = 0; i < q->n_keys; i++) {
969b009d9416806911b9b52e7e7bc619c0c1a931Tom Gundersen _cleanup_(dns_resource_key_unrefp) DnsResourceKey *k = NULL;
b3ec603ce8053ba3f95da1d36f15ea762c83d1e1Lennart Poettering
969b009d9416806911b9b52e7e7bc619c0c1a931Tom Gundersen k = dns_resource_key_new_redirect(q->keys[i], cname);
969b009d9416806911b9b52e7e7bc619c0c1a931Tom Gundersen if (!k)
969b009d9416806911b9b52e7e7bc619c0c1a931Tom Gundersen return -ENOMEM;
969b009d9416806911b9b52e7e7bc619c0c1a931Tom Gundersen
969b009d9416806911b9b52e7e7bc619c0c1a931Tom Gundersen r = dns_question_add(n, k);
969b009d9416806911b9b52e7e7bc619c0c1a931Tom Gundersen if (r < 0)
969b009d9416806911b9b52e7e7bc619c0c1a931Tom Gundersen return r;
a6f1e036de8f212f33ead7f5387c297afd8be26eTom Gundersen }
a6f1e036de8f212f33ead7f5387c297afd8be26eTom Gundersen
969b009d9416806911b9b52e7e7bc619c0c1a931Tom Gundersen *ret = n;
b3ec603ce8053ba3f95da1d36f15ea762c83d1e1Lennart Poettering n = NULL;
969b009d9416806911b9b52e7e7bc619c0c1a931Tom Gundersen
969b009d9416806911b9b52e7e7bc619c0c1a931Tom Gundersen return 1;
969b009d9416806911b9b52e7e7bc619c0c1a931Tom Gundersen}
969b009d9416806911b9b52e7e7bc619c0c1a931Tom Gundersen
969b009d9416806911b9b52e7e7bc619c0c1a931Tom Gundersenconst char *dns_question_first_name(DnsQuestion *q) {
969b009d9416806911b9b52e7e7bc619c0c1a931Tom Gundersen
969b009d9416806911b9b52e7e7bc619c0c1a931Tom Gundersen if (!q)
969b009d9416806911b9b52e7e7bc619c0c1a931Tom Gundersen return NULL;
969b009d9416806911b9b52e7e7bc619c0c1a931Tom Gundersen
969b009d9416806911b9b52e7e7bc619c0c1a931Tom Gundersen if (q->n_keys < 1)
969b009d9416806911b9b52e7e7bc619c0c1a931Tom Gundersen return NULL;
969b009d9416806911b9b52e7e7bc619c0c1a931Tom Gundersen
969b009d9416806911b9b52e7e7bc619c0c1a931Tom Gundersen return DNS_RESOURCE_KEY_NAME(q->keys[0]);
969b009d9416806911b9b52e7e7bc619c0c1a931Tom Gundersen}
969b009d9416806911b9b52e7e7bc619c0c1a931Tom Gundersen
969b009d9416806911b9b52e7e7bc619c0c1a931Tom Gundersenint dns_question_new_address(DnsQuestion **ret, int family, const char *name) {
969b009d9416806911b9b52e7e7bc619c0c1a931Tom Gundersen _cleanup_(dns_question_unrefp) DnsQuestion *q = NULL;
969b009d9416806911b9b52e7e7bc619c0c1a931Tom Gundersen int r;
969b009d9416806911b9b52e7e7bc619c0c1a931Tom Gundersen
969b009d9416806911b9b52e7e7bc619c0c1a931Tom Gundersen assert(ret);
969b009d9416806911b9b52e7e7bc619c0c1a931Tom Gundersen assert(name);
969b009d9416806911b9b52e7e7bc619c0c1a931Tom Gundersen
969b009d9416806911b9b52e7e7bc619c0c1a931Tom Gundersen if (!IN_SET(family, AF_INET, AF_INET6, AF_UNSPEC))
969b009d9416806911b9b52e7e7bc619c0c1a931Tom Gundersen return -EAFNOSUPPORT;
969b009d9416806911b9b52e7e7bc619c0c1a931Tom Gundersen
969b009d9416806911b9b52e7e7bc619c0c1a931Tom Gundersen q = dns_question_new(family == AF_UNSPEC ? 2 : 1);
969b009d9416806911b9b52e7e7bc619c0c1a931Tom Gundersen if (!q)
969b009d9416806911b9b52e7e7bc619c0c1a931Tom Gundersen return -ENOMEM;
969b009d9416806911b9b52e7e7bc619c0c1a931Tom Gundersen
969b009d9416806911b9b52e7e7bc619c0c1a931Tom Gundersen if (family != AF_INET6) {
969b009d9416806911b9b52e7e7bc619c0c1a931Tom Gundersen _cleanup_(dns_resource_key_unrefp) DnsResourceKey *key = NULL;
969b009d9416806911b9b52e7e7bc619c0c1a931Tom Gundersen
969b009d9416806911b9b52e7e7bc619c0c1a931Tom Gundersen key = dns_resource_key_new(DNS_CLASS_IN, DNS_TYPE_A, name);
969b009d9416806911b9b52e7e7bc619c0c1a931Tom Gundersen if (!key)
969b009d9416806911b9b52e7e7bc619c0c1a931Tom Gundersen return -ENOMEM;
969b009d9416806911b9b52e7e7bc619c0c1a931Tom Gundersen
969b009d9416806911b9b52e7e7bc619c0c1a931Tom Gundersen r = dns_question_add(q, key);
969b009d9416806911b9b52e7e7bc619c0c1a931Tom Gundersen if (r < 0)
969b009d9416806911b9b52e7e7bc619c0c1a931Tom Gundersen return r;
969b009d9416806911b9b52e7e7bc619c0c1a931Tom Gundersen }
969b009d9416806911b9b52e7e7bc619c0c1a931Tom Gundersen
969b009d9416806911b9b52e7e7bc619c0c1a931Tom Gundersen if (family != AF_INET) {
969b009d9416806911b9b52e7e7bc619c0c1a931Tom Gundersen _cleanup_(dns_resource_key_unrefp) DnsResourceKey *key = NULL;
969b009d9416806911b9b52e7e7bc619c0c1a931Tom Gundersen
969b009d9416806911b9b52e7e7bc619c0c1a931Tom Gundersen key = dns_resource_key_new(DNS_CLASS_IN, DNS_TYPE_AAAA, name);
b3ec603ce8053ba3f95da1d36f15ea762c83d1e1Lennart Poettering if (!key)
969b009d9416806911b9b52e7e7bc619c0c1a931Tom Gundersen return -ENOMEM;
969b009d9416806911b9b52e7e7bc619c0c1a931Tom Gundersen
969b009d9416806911b9b52e7e7bc619c0c1a931Tom Gundersen r = dns_question_add(q, key);
969b009d9416806911b9b52e7e7bc619c0c1a931Tom Gundersen if (r < 0)
969b009d9416806911b9b52e7e7bc619c0c1a931Tom Gundersen return r;
969b009d9416806911b9b52e7e7bc619c0c1a931Tom Gundersen }
969b009d9416806911b9b52e7e7bc619c0c1a931Tom Gundersen
969b009d9416806911b9b52e7e7bc619c0c1a931Tom Gundersen *ret = q;
969b009d9416806911b9b52e7e7bc619c0c1a931Tom Gundersen q = NULL;
969b009d9416806911b9b52e7e7bc619c0c1a931Tom Gundersen
969b009d9416806911b9b52e7e7bc619c0c1a931Tom Gundersen return 0;
969b009d9416806911b9b52e7e7bc619c0c1a931Tom Gundersen}
969b009d9416806911b9b52e7e7bc619c0c1a931Tom Gundersen
969b009d9416806911b9b52e7e7bc619c0c1a931Tom Gundersenint dns_question_new_reverse(DnsQuestion **ret, int family, const union in_addr_union *a) {
969b009d9416806911b9b52e7e7bc619c0c1a931Tom Gundersen _cleanup_(dns_resource_key_unrefp) DnsResourceKey *key = NULL;
969b009d9416806911b9b52e7e7bc619c0c1a931Tom Gundersen _cleanup_(dns_question_unrefp) DnsQuestion *q = NULL;
969b009d9416806911b9b52e7e7bc619c0c1a931Tom Gundersen _cleanup_free_ char *reverse = NULL;
969b009d9416806911b9b52e7e7bc619c0c1a931Tom Gundersen int r;
969b009d9416806911b9b52e7e7bc619c0c1a931Tom Gundersen
969b009d9416806911b9b52e7e7bc619c0c1a931Tom Gundersen assert(ret);
969b009d9416806911b9b52e7e7bc619c0c1a931Tom Gundersen assert(a);
969b009d9416806911b9b52e7e7bc619c0c1a931Tom Gundersen
969b009d9416806911b9b52e7e7bc619c0c1a931Tom Gundersen if (!IN_SET(family, AF_INET, AF_INET6, AF_UNSPEC))
969b009d9416806911b9b52e7e7bc619c0c1a931Tom Gundersen return -EAFNOSUPPORT;
969b009d9416806911b9b52e7e7bc619c0c1a931Tom Gundersen
969b009d9416806911b9b52e7e7bc619c0c1a931Tom Gundersen r = dns_name_reverse(family, a, &reverse);
969b009d9416806911b9b52e7e7bc619c0c1a931Tom Gundersen if (r < 0)
969b009d9416806911b9b52e7e7bc619c0c1a931Tom Gundersen return r;
969b009d9416806911b9b52e7e7bc619c0c1a931Tom Gundersen
969b009d9416806911b9b52e7e7bc619c0c1a931Tom Gundersen q = dns_question_new(1);
969b009d9416806911b9b52e7e7bc619c0c1a931Tom Gundersen if (!q)
969b009d9416806911b9b52e7e7bc619c0c1a931Tom Gundersen return -ENOMEM;
969b009d9416806911b9b52e7e7bc619c0c1a931Tom Gundersen
969b009d9416806911b9b52e7e7bc619c0c1a931Tom Gundersen key = dns_resource_key_new_consume(DNS_CLASS_IN, DNS_TYPE_PTR, reverse);
969b009d9416806911b9b52e7e7bc619c0c1a931Tom Gundersen if (!key)
969b009d9416806911b9b52e7e7bc619c0c1a931Tom Gundersen return -ENOMEM;
969b009d9416806911b9b52e7e7bc619c0c1a931Tom Gundersen
969b009d9416806911b9b52e7e7bc619c0c1a931Tom Gundersen reverse = NULL;
969b009d9416806911b9b52e7e7bc619c0c1a931Tom Gundersen
969b009d9416806911b9b52e7e7bc619c0c1a931Tom Gundersen r = dns_question_add(q, key);
969b009d9416806911b9b52e7e7bc619c0c1a931Tom Gundersen if (r < 0)
969b009d9416806911b9b52e7e7bc619c0c1a931Tom Gundersen return r;
969b009d9416806911b9b52e7e7bc619c0c1a931Tom Gundersen
969b009d9416806911b9b52e7e7bc619c0c1a931Tom Gundersen *ret = q;
969b009d9416806911b9b52e7e7bc619c0c1a931Tom Gundersen q = NULL;
969b009d9416806911b9b52e7e7bc619c0c1a931Tom Gundersen
969b009d9416806911b9b52e7e7bc619c0c1a931Tom Gundersen return 0;
969b009d9416806911b9b52e7e7bc619c0c1a931Tom Gundersen}
969b009d9416806911b9b52e7e7bc619c0c1a931Tom Gundersen
969b009d9416806911b9b52e7e7bc619c0c1a931Tom Gundersenint dns_question_new_service(DnsQuestion **ret, const char *name, bool with_txt) {
969b009d9416806911b9b52e7e7bc619c0c1a931Tom Gundersen _cleanup_(dns_resource_key_unrefp) DnsResourceKey *key = NULL;
969b009d9416806911b9b52e7e7bc619c0c1a931Tom Gundersen _cleanup_(dns_question_unrefp) DnsQuestion *q = NULL;
969b009d9416806911b9b52e7e7bc619c0c1a931Tom Gundersen int r;
969b009d9416806911b9b52e7e7bc619c0c1a931Tom Gundersen
969b009d9416806911b9b52e7e7bc619c0c1a931Tom Gundersen assert(ret);
969b009d9416806911b9b52e7e7bc619c0c1a931Tom Gundersen assert(name);
969b009d9416806911b9b52e7e7bc619c0c1a931Tom Gundersen
969b009d9416806911b9b52e7e7bc619c0c1a931Tom Gundersen q = dns_question_new(1 + with_txt);
969b009d9416806911b9b52e7e7bc619c0c1a931Tom Gundersen if (!q)
969b009d9416806911b9b52e7e7bc619c0c1a931Tom Gundersen return -ENOMEM;
969b009d9416806911b9b52e7e7bc619c0c1a931Tom Gundersen
969b009d9416806911b9b52e7e7bc619c0c1a931Tom Gundersen key = dns_resource_key_new(DNS_CLASS_IN, DNS_TYPE_SRV, name);
969b009d9416806911b9b52e7e7bc619c0c1a931Tom Gundersen if (!key)
969b009d9416806911b9b52e7e7bc619c0c1a931Tom Gundersen return -ENOMEM;
969b009d9416806911b9b52e7e7bc619c0c1a931Tom Gundersen
969b009d9416806911b9b52e7e7bc619c0c1a931Tom Gundersen r = dns_question_add(q, key);
969b009d9416806911b9b52e7e7bc619c0c1a931Tom Gundersen if (r < 0)
969b009d9416806911b9b52e7e7bc619c0c1a931Tom Gundersen return r;
d6bd972d061af306ede2affd2c9340a1660f7996Tom Gundersen
969b009d9416806911b9b52e7e7bc619c0c1a931Tom Gundersen if (with_txt) {
969b009d9416806911b9b52e7e7bc619c0c1a931Tom Gundersen dns_resource_key_unref(key);
d6bd972d061af306ede2affd2c9340a1660f7996Tom Gundersen key = dns_resource_key_new(DNS_CLASS_IN, DNS_TYPE_TXT, name);
a6f1e036de8f212f33ead7f5387c297afd8be26eTom Gundersen if (!key)
a6f1e036de8f212f33ead7f5387c297afd8be26eTom Gundersen return -ENOMEM;
d6bd972d061af306ede2affd2c9340a1660f7996Tom Gundersen
969b009d9416806911b9b52e7e7bc619c0c1a931Tom Gundersen r = dns_question_add(q, key);
a6f1e036de8f212f33ead7f5387c297afd8be26eTom Gundersen if (r < 0)
a6f1e036de8f212f33ead7f5387c297afd8be26eTom Gundersen return r;
a6f1e036de8f212f33ead7f5387c297afd8be26eTom Gundersen }
969b009d9416806911b9b52e7e7bc619c0c1a931Tom Gundersen
969b009d9416806911b9b52e7e7bc619c0c1a931Tom Gundersen *ret = q;
969b009d9416806911b9b52e7e7bc619c0c1a931Tom Gundersen q = NULL;
969b009d9416806911b9b52e7e7bc619c0c1a931Tom Gundersen
4dc355680460fdc8e0d590d8572dff1b6a257d88Tom Gundersen return 0;
a6f1e036de8f212f33ead7f5387c297afd8be26eTom Gundersen}
a6f1e036de8f212f33ead7f5387c297afd8be26eTom Gundersen