faa133f3aa7a18f26563dc5d6b95898cb315c37aLennart Poettering/***
faa133f3aa7a18f26563dc5d6b95898cb315c37aLennart Poettering This file is part of systemd.
faa133f3aa7a18f26563dc5d6b95898cb315c37aLennart Poettering
faa133f3aa7a18f26563dc5d6b95898cb315c37aLennart Poettering Copyright 2014 Lennart Poettering
faa133f3aa7a18f26563dc5d6b95898cb315c37aLennart Poettering
faa133f3aa7a18f26563dc5d6b95898cb315c37aLennart Poettering systemd is free software; you can redistribute it and/or modify it
faa133f3aa7a18f26563dc5d6b95898cb315c37aLennart Poettering under the terms of the GNU Lesser General Public License as published by
faa133f3aa7a18f26563dc5d6b95898cb315c37aLennart Poettering the Free Software Foundation; either version 2.1 of the License, or
faa133f3aa7a18f26563dc5d6b95898cb315c37aLennart Poettering (at your option) any later version.
faa133f3aa7a18f26563dc5d6b95898cb315c37aLennart Poettering
faa133f3aa7a18f26563dc5d6b95898cb315c37aLennart Poettering systemd is distributed in the hope that it will be useful, but
faa133f3aa7a18f26563dc5d6b95898cb315c37aLennart Poettering WITHOUT ANY WARRANTY; without even the implied warranty of
faa133f3aa7a18f26563dc5d6b95898cb315c37aLennart Poettering MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
faa133f3aa7a18f26563dc5d6b95898cb315c37aLennart Poettering Lesser General Public License for more details.
faa133f3aa7a18f26563dc5d6b95898cb315c37aLennart Poettering
faa133f3aa7a18f26563dc5d6b95898cb315c37aLennart Poettering You should have received a copy of the GNU Lesser General Public License
faa133f3aa7a18f26563dc5d6b95898cb315c37aLennart Poettering along with systemd; If not, see <http://www.gnu.org/licenses/>.
faa133f3aa7a18f26563dc5d6b95898cb315c37aLennart Poettering***/
faa133f3aa7a18f26563dc5d6b95898cb315c37aLennart Poettering
b5efdb8af40ea759a1ea584c1bc44ecc81dd00ceLennart Poettering#include "alloc-util.h"
4ad7f2761da661853dcc29d542efb4727abb1101Nick Owens#include "dns-domain.h"
0f7091e624fdba6c0bf281f2a9a23cd3e9ca93fbLennart Poettering#include "dns-type.h"
b5efdb8af40ea759a1ea584c1bc44ecc81dd00ceLennart Poettering#include "resolved-dns-question.h"
faa133f3aa7a18f26563dc5d6b95898cb315c37aLennart Poettering
faa133f3aa7a18f26563dc5d6b95898cb315c37aLennart PoetteringDnsQuestion *dns_question_new(unsigned n) {
faa133f3aa7a18f26563dc5d6b95898cb315c37aLennart Poettering DnsQuestion *q;
faa133f3aa7a18f26563dc5d6b95898cb315c37aLennart Poettering
faa133f3aa7a18f26563dc5d6b95898cb315c37aLennart Poettering assert(n > 0);
faa133f3aa7a18f26563dc5d6b95898cb315c37aLennart Poettering
faa133f3aa7a18f26563dc5d6b95898cb315c37aLennart Poettering q = malloc0(offsetof(DnsQuestion, keys) + sizeof(DnsResourceKey*) * n);
faa133f3aa7a18f26563dc5d6b95898cb315c37aLennart Poettering if (!q)
faa133f3aa7a18f26563dc5d6b95898cb315c37aLennart Poettering return NULL;
faa133f3aa7a18f26563dc5d6b95898cb315c37aLennart Poettering
faa133f3aa7a18f26563dc5d6b95898cb315c37aLennart Poettering q->n_ref = 1;
faa133f3aa7a18f26563dc5d6b95898cb315c37aLennart Poettering q->n_allocated = n;
faa133f3aa7a18f26563dc5d6b95898cb315c37aLennart Poettering
faa133f3aa7a18f26563dc5d6b95898cb315c37aLennart Poettering return q;
faa133f3aa7a18f26563dc5d6b95898cb315c37aLennart Poettering}
faa133f3aa7a18f26563dc5d6b95898cb315c37aLennart Poettering
faa133f3aa7a18f26563dc5d6b95898cb315c37aLennart PoetteringDnsQuestion *dns_question_ref(DnsQuestion *q) {
faa133f3aa7a18f26563dc5d6b95898cb315c37aLennart Poettering if (!q)
faa133f3aa7a18f26563dc5d6b95898cb315c37aLennart Poettering return NULL;
faa133f3aa7a18f26563dc5d6b95898cb315c37aLennart Poettering
faa133f3aa7a18f26563dc5d6b95898cb315c37aLennart Poettering assert(q->n_ref > 0);
faa133f3aa7a18f26563dc5d6b95898cb315c37aLennart Poettering q->n_ref++;
faa133f3aa7a18f26563dc5d6b95898cb315c37aLennart Poettering return q;
faa133f3aa7a18f26563dc5d6b95898cb315c37aLennart Poettering}
faa133f3aa7a18f26563dc5d6b95898cb315c37aLennart Poettering
faa133f3aa7a18f26563dc5d6b95898cb315c37aLennart PoetteringDnsQuestion *dns_question_unref(DnsQuestion *q) {
faa133f3aa7a18f26563dc5d6b95898cb315c37aLennart Poettering if (!q)
faa133f3aa7a18f26563dc5d6b95898cb315c37aLennart Poettering return NULL;
faa133f3aa7a18f26563dc5d6b95898cb315c37aLennart Poettering
faa133f3aa7a18f26563dc5d6b95898cb315c37aLennart Poettering assert(q->n_ref > 0);
faa133f3aa7a18f26563dc5d6b95898cb315c37aLennart Poettering
faa133f3aa7a18f26563dc5d6b95898cb315c37aLennart Poettering if (q->n_ref == 1) {
faa133f3aa7a18f26563dc5d6b95898cb315c37aLennart Poettering unsigned i;
faa133f3aa7a18f26563dc5d6b95898cb315c37aLennart Poettering
faa133f3aa7a18f26563dc5d6b95898cb315c37aLennart Poettering for (i = 0; i < q->n_keys; i++)
faa133f3aa7a18f26563dc5d6b95898cb315c37aLennart Poettering dns_resource_key_unref(q->keys[i]);
faa133f3aa7a18f26563dc5d6b95898cb315c37aLennart Poettering free(q);
faa133f3aa7a18f26563dc5d6b95898cb315c37aLennart Poettering } else
faa133f3aa7a18f26563dc5d6b95898cb315c37aLennart Poettering q->n_ref--;
faa133f3aa7a18f26563dc5d6b95898cb315c37aLennart Poettering
faa133f3aa7a18f26563dc5d6b95898cb315c37aLennart Poettering return NULL;
faa133f3aa7a18f26563dc5d6b95898cb315c37aLennart Poettering}
faa133f3aa7a18f26563dc5d6b95898cb315c37aLennart Poettering
faa133f3aa7a18f26563dc5d6b95898cb315c37aLennart Poetteringint dns_question_add(DnsQuestion *q, DnsResourceKey *key) {
7e8e0422aeb16f2a09a40546c61df753d10029b6Lennart Poettering unsigned i;
7e8e0422aeb16f2a09a40546c61df753d10029b6Lennart Poettering int r;
7e8e0422aeb16f2a09a40546c61df753d10029b6Lennart Poettering
faa133f3aa7a18f26563dc5d6b95898cb315c37aLennart Poettering assert(key);
faa133f3aa7a18f26563dc5d6b95898cb315c37aLennart Poettering
8013e860b6344cb109e68208a3a91b0fc3cb9ed1Lennart Poettering if (!q)
8013e860b6344cb109e68208a3a91b0fc3cb9ed1Lennart Poettering return -ENOSPC;
8013e860b6344cb109e68208a3a91b0fc3cb9ed1Lennart Poettering
7e8e0422aeb16f2a09a40546c61df753d10029b6Lennart Poettering for (i = 0; i < q->n_keys; i++) {
7e8e0422aeb16f2a09a40546c61df753d10029b6Lennart Poettering r = dns_resource_key_equal(q->keys[i], key);
7e8e0422aeb16f2a09a40546c61df753d10029b6Lennart Poettering if (r < 0)
7e8e0422aeb16f2a09a40546c61df753d10029b6Lennart Poettering return r;
7e8e0422aeb16f2a09a40546c61df753d10029b6Lennart Poettering if (r > 0)
7e8e0422aeb16f2a09a40546c61df753d10029b6Lennart Poettering return 0;
7e8e0422aeb16f2a09a40546c61df753d10029b6Lennart Poettering }
7e8e0422aeb16f2a09a40546c61df753d10029b6Lennart Poettering
faa133f3aa7a18f26563dc5d6b95898cb315c37aLennart Poettering if (q->n_keys >= q->n_allocated)
faa133f3aa7a18f26563dc5d6b95898cb315c37aLennart Poettering return -ENOSPC;
faa133f3aa7a18f26563dc5d6b95898cb315c37aLennart Poettering
faa133f3aa7a18f26563dc5d6b95898cb315c37aLennart Poettering q->keys[q->n_keys++] = dns_resource_key_ref(key);
faa133f3aa7a18f26563dc5d6b95898cb315c37aLennart Poettering return 0;
faa133f3aa7a18f26563dc5d6b95898cb315c37aLennart Poettering}
faa133f3aa7a18f26563dc5d6b95898cb315c37aLennart Poettering
801ad6a6a9cd8fbd58b9f9c27f20dbb3c87d47ddLennart Poetteringint dns_question_matches_rr(DnsQuestion *q, DnsResourceRecord *rr, const char *search_domain) {
faa133f3aa7a18f26563dc5d6b95898cb315c37aLennart Poettering unsigned i;
faa133f3aa7a18f26563dc5d6b95898cb315c37aLennart Poettering int r;
faa133f3aa7a18f26563dc5d6b95898cb315c37aLennart Poettering
faa133f3aa7a18f26563dc5d6b95898cb315c37aLennart Poettering assert(rr);
faa133f3aa7a18f26563dc5d6b95898cb315c37aLennart Poettering
8013e860b6344cb109e68208a3a91b0fc3cb9ed1Lennart Poettering if (!q)
8013e860b6344cb109e68208a3a91b0fc3cb9ed1Lennart Poettering return 0;
8013e860b6344cb109e68208a3a91b0fc3cb9ed1Lennart Poettering
faa133f3aa7a18f26563dc5d6b95898cb315c37aLennart Poettering for (i = 0; i < q->n_keys; i++) {
801ad6a6a9cd8fbd58b9f9c27f20dbb3c87d47ddLennart Poettering r = dns_resource_key_match_rr(q->keys[i], rr, search_domain);
faa133f3aa7a18f26563dc5d6b95898cb315c37aLennart Poettering if (r != 0)
faa133f3aa7a18f26563dc5d6b95898cb315c37aLennart Poettering return r;
faa133f3aa7a18f26563dc5d6b95898cb315c37aLennart Poettering }
faa133f3aa7a18f26563dc5d6b95898cb315c37aLennart Poettering
faa133f3aa7a18f26563dc5d6b95898cb315c37aLennart Poettering return 0;
faa133f3aa7a18f26563dc5d6b95898cb315c37aLennart Poettering}
faa133f3aa7a18f26563dc5d6b95898cb315c37aLennart Poettering
542e0c84d1518a1515e03194dd25299b2652778cLennart Poetteringint dns_question_matches_cname_or_dname(DnsQuestion *q, DnsResourceRecord *rr, const char *search_domain) {
faa133f3aa7a18f26563dc5d6b95898cb315c37aLennart Poettering unsigned i;
faa133f3aa7a18f26563dc5d6b95898cb315c37aLennart Poettering int r;
faa133f3aa7a18f26563dc5d6b95898cb315c37aLennart Poettering
faa133f3aa7a18f26563dc5d6b95898cb315c37aLennart Poettering assert(rr);
faa133f3aa7a18f26563dc5d6b95898cb315c37aLennart Poettering
8013e860b6344cb109e68208a3a91b0fc3cb9ed1Lennart Poettering if (!q)
8013e860b6344cb109e68208a3a91b0fc3cb9ed1Lennart Poettering return 0;
8013e860b6344cb109e68208a3a91b0fc3cb9ed1Lennart Poettering
542e0c84d1518a1515e03194dd25299b2652778cLennart Poettering if (!IN_SET(rr->key->type, DNS_TYPE_CNAME, DNS_TYPE_DNAME))
542e0c84d1518a1515e03194dd25299b2652778cLennart Poettering return 0;
542e0c84d1518a1515e03194dd25299b2652778cLennart Poettering
faa133f3aa7a18f26563dc5d6b95898cb315c37aLennart Poettering for (i = 0; i < q->n_keys; i++) {
542e0c84d1518a1515e03194dd25299b2652778cLennart Poettering /* For a {C,D}NAME record we can never find a matching {C,D}NAME record */
542e0c84d1518a1515e03194dd25299b2652778cLennart Poettering if (!dns_type_may_redirect(q->keys[i]->type))
542e0c84d1518a1515e03194dd25299b2652778cLennart Poettering return 0;
542e0c84d1518a1515e03194dd25299b2652778cLennart Poettering
5d27351f8546530cf779847b0b04b0172c09f9d0Tom Gundersen r = dns_resource_key_match_cname_or_dname(q->keys[i], rr->key, search_domain);
faa133f3aa7a18f26563dc5d6b95898cb315c37aLennart Poettering if (r != 0)
faa133f3aa7a18f26563dc5d6b95898cb315c37aLennart Poettering return r;
faa133f3aa7a18f26563dc5d6b95898cb315c37aLennart Poettering }
faa133f3aa7a18f26563dc5d6b95898cb315c37aLennart Poettering
34b9656f0b2890743eee6a746ef08d817abfd5e9Lennart Poettering return 0;
faa133f3aa7a18f26563dc5d6b95898cb315c37aLennart Poettering}
faa133f3aa7a18f26563dc5d6b95898cb315c37aLennart Poettering
703e4f5e39c019da8c002ba10bd450ce378c0e91Lennart Poetteringint dns_question_is_valid_for_query(DnsQuestion *q) {
faa133f3aa7a18f26563dc5d6b95898cb315c37aLennart Poettering const char *name;
faa133f3aa7a18f26563dc5d6b95898cb315c37aLennart Poettering unsigned i;
faa133f3aa7a18f26563dc5d6b95898cb315c37aLennart Poettering int r;
faa133f3aa7a18f26563dc5d6b95898cb315c37aLennart Poettering
8013e860b6344cb109e68208a3a91b0fc3cb9ed1Lennart Poettering if (!q)
8013e860b6344cb109e68208a3a91b0fc3cb9ed1Lennart Poettering return 0;
faa133f3aa7a18f26563dc5d6b95898cb315c37aLennart Poettering
faa133f3aa7a18f26563dc5d6b95898cb315c37aLennart Poettering if (q->n_keys <= 0)
faa133f3aa7a18f26563dc5d6b95898cb315c37aLennart Poettering return 0;
faa133f3aa7a18f26563dc5d6b95898cb315c37aLennart Poettering
faa133f3aa7a18f26563dc5d6b95898cb315c37aLennart Poettering if (q->n_keys > 65535)
faa133f3aa7a18f26563dc5d6b95898cb315c37aLennart Poettering return 0;
faa133f3aa7a18f26563dc5d6b95898cb315c37aLennart Poettering
faa133f3aa7a18f26563dc5d6b95898cb315c37aLennart Poettering name = DNS_RESOURCE_KEY_NAME(q->keys[0]);
faa133f3aa7a18f26563dc5d6b95898cb315c37aLennart Poettering if (!name)
faa133f3aa7a18f26563dc5d6b95898cb315c37aLennart Poettering return 0;
faa133f3aa7a18f26563dc5d6b95898cb315c37aLennart Poettering
faa133f3aa7a18f26563dc5d6b95898cb315c37aLennart Poettering /* Check that all keys in this question bear the same name */
0f7091e624fdba6c0bf281f2a9a23cd3e9ca93fbLennart Poettering for (i = 0; i < q->n_keys; i++) {
34b9656f0b2890743eee6a746ef08d817abfd5e9Lennart Poettering assert(q->keys[i]);
34b9656f0b2890743eee6a746ef08d817abfd5e9Lennart Poettering
0f7091e624fdba6c0bf281f2a9a23cd3e9ca93fbLennart Poettering if (i > 0) {
0f7091e624fdba6c0bf281f2a9a23cd3e9ca93fbLennart Poettering r = dns_name_equal(DNS_RESOURCE_KEY_NAME(q->keys[i]), name);
0f7091e624fdba6c0bf281f2a9a23cd3e9ca93fbLennart Poettering if (r <= 0)
0f7091e624fdba6c0bf281f2a9a23cd3e9ca93fbLennart Poettering return r;
0f7091e624fdba6c0bf281f2a9a23cd3e9ca93fbLennart Poettering }
0f7091e624fdba6c0bf281f2a9a23cd3e9ca93fbLennart Poettering
0f7091e624fdba6c0bf281f2a9a23cd3e9ca93fbLennart Poettering if (!dns_type_is_valid_query(q->keys[i]->type))
0f7091e624fdba6c0bf281f2a9a23cd3e9ca93fbLennart Poettering return 0;
faa133f3aa7a18f26563dc5d6b95898cb315c37aLennart Poettering }
faa133f3aa7a18f26563dc5d6b95898cb315c37aLennart Poettering
faa133f3aa7a18f26563dc5d6b95898cb315c37aLennart Poettering return 1;
faa133f3aa7a18f26563dc5d6b95898cb315c37aLennart Poettering}
faa133f3aa7a18f26563dc5d6b95898cb315c37aLennart Poettering
6a21960c0be378799db51a2735ff68474e5e21f8Lennart Poetteringint dns_question_contains(DnsQuestion *a, const DnsResourceKey *k) {
1086182d83d4c02a75f96f0184d5e8e5d3af6528Lennart Poettering unsigned j;
1086182d83d4c02a75f96f0184d5e8e5d3af6528Lennart Poettering int r;
1086182d83d4c02a75f96f0184d5e8e5d3af6528Lennart Poettering
1086182d83d4c02a75f96f0184d5e8e5d3af6528Lennart Poettering assert(k);
1086182d83d4c02a75f96f0184d5e8e5d3af6528Lennart Poettering
8013e860b6344cb109e68208a3a91b0fc3cb9ed1Lennart Poettering if (!a)
8013e860b6344cb109e68208a3a91b0fc3cb9ed1Lennart Poettering return 0;
8013e860b6344cb109e68208a3a91b0fc3cb9ed1Lennart Poettering
1086182d83d4c02a75f96f0184d5e8e5d3af6528Lennart Poettering for (j = 0; j < a->n_keys; j++) {
1086182d83d4c02a75f96f0184d5e8e5d3af6528Lennart Poettering r = dns_resource_key_equal(a->keys[j], k);
1086182d83d4c02a75f96f0184d5e8e5d3af6528Lennart Poettering if (r != 0)
1086182d83d4c02a75f96f0184d5e8e5d3af6528Lennart Poettering return r;
1086182d83d4c02a75f96f0184d5e8e5d3af6528Lennart Poettering }
1086182d83d4c02a75f96f0184d5e8e5d3af6528Lennart Poettering
1086182d83d4c02a75f96f0184d5e8e5d3af6528Lennart Poettering return 0;
1086182d83d4c02a75f96f0184d5e8e5d3af6528Lennart Poettering}
1086182d83d4c02a75f96f0184d5e8e5d3af6528Lennart Poettering
1086182d83d4c02a75f96f0184d5e8e5d3af6528Lennart Poetteringint dns_question_is_equal(DnsQuestion *a, DnsQuestion *b) {
1086182d83d4c02a75f96f0184d5e8e5d3af6528Lennart Poettering unsigned j;
1086182d83d4c02a75f96f0184d5e8e5d3af6528Lennart Poettering int r;
1086182d83d4c02a75f96f0184d5e8e5d3af6528Lennart Poettering
b6800689e03456efd0430d171ebf962f64b94eb0Lennart Poettering if (a == b)
b6800689e03456efd0430d171ebf962f64b94eb0Lennart Poettering return 1;
b6800689e03456efd0430d171ebf962f64b94eb0Lennart Poettering
8013e860b6344cb109e68208a3a91b0fc3cb9ed1Lennart Poettering if (!a)
8013e860b6344cb109e68208a3a91b0fc3cb9ed1Lennart Poettering return !b || b->n_keys == 0;
8013e860b6344cb109e68208a3a91b0fc3cb9ed1Lennart Poettering if (!b)
8013e860b6344cb109e68208a3a91b0fc3cb9ed1Lennart Poettering return a->n_keys == 0;
1086182d83d4c02a75f96f0184d5e8e5d3af6528Lennart Poettering
1086182d83d4c02a75f96f0184d5e8e5d3af6528Lennart Poettering /* Checks if all keys in a are also contained b, and vice versa */
1086182d83d4c02a75f96f0184d5e8e5d3af6528Lennart Poettering
1086182d83d4c02a75f96f0184d5e8e5d3af6528Lennart Poettering for (j = 0; j < a->n_keys; j++) {
1086182d83d4c02a75f96f0184d5e8e5d3af6528Lennart Poettering r = dns_question_contains(b, a->keys[j]);
1086182d83d4c02a75f96f0184d5e8e5d3af6528Lennart Poettering if (r <= 0)
1086182d83d4c02a75f96f0184d5e8e5d3af6528Lennart Poettering return r;
1086182d83d4c02a75f96f0184d5e8e5d3af6528Lennart Poettering }
1086182d83d4c02a75f96f0184d5e8e5d3af6528Lennart Poettering
1086182d83d4c02a75f96f0184d5e8e5d3af6528Lennart Poettering for (j = 0; j < b->n_keys; j++) {
1086182d83d4c02a75f96f0184d5e8e5d3af6528Lennart Poettering r = dns_question_contains(a, b->keys[j]);
1086182d83d4c02a75f96f0184d5e8e5d3af6528Lennart Poettering if (r <= 0)
1086182d83d4c02a75f96f0184d5e8e5d3af6528Lennart Poettering return r;
1086182d83d4c02a75f96f0184d5e8e5d3af6528Lennart Poettering }
1086182d83d4c02a75f96f0184d5e8e5d3af6528Lennart Poettering
1086182d83d4c02a75f96f0184d5e8e5d3af6528Lennart Poettering return 1;
1086182d83d4c02a75f96f0184d5e8e5d3af6528Lennart Poettering}
1086182d83d4c02a75f96f0184d5e8e5d3af6528Lennart Poettering
36d9205d669bcdcb04fa730d1f3549a9fc9a9001Tom Gundersenint dns_question_cname_redirect(DnsQuestion *q, const DnsResourceRecord *cname, DnsQuestion **ret) {
faa133f3aa7a18f26563dc5d6b95898cb315c37aLennart Poettering _cleanup_(dns_question_unrefp) DnsQuestion *n = NULL;
23b298bce75a0d1f4f15f34458af9678b4a30c3aLennart Poettering DnsResourceKey *key;
faa133f3aa7a18f26563dc5d6b95898cb315c37aLennart Poettering bool same = true;
faa133f3aa7a18f26563dc5d6b95898cb315c37aLennart Poettering int r;
faa133f3aa7a18f26563dc5d6b95898cb315c37aLennart Poettering
36d9205d669bcdcb04fa730d1f3549a9fc9a9001Tom Gundersen assert(cname);
faa133f3aa7a18f26563dc5d6b95898cb315c37aLennart Poettering assert(ret);
58db254ade4fb2ef77de68f28c4f13814819f6a1Lennart Poettering assert(IN_SET(cname->key->type, DNS_TYPE_CNAME, DNS_TYPE_DNAME));
faa133f3aa7a18f26563dc5d6b95898cb315c37aLennart Poettering
23b298bce75a0d1f4f15f34458af9678b4a30c3aLennart Poettering if (dns_question_size(q) <= 0) {
23b298bce75a0d1f4f15f34458af9678b4a30c3aLennart Poettering *ret = NULL;
8013e860b6344cb109e68208a3a91b0fc3cb9ed1Lennart Poettering return 0;
8013e860b6344cb109e68208a3a91b0fc3cb9ed1Lennart Poettering }
8013e860b6344cb109e68208a3a91b0fc3cb9ed1Lennart Poettering
23b298bce75a0d1f4f15f34458af9678b4a30c3aLennart Poettering DNS_QUESTION_FOREACH(key, q) {
58db254ade4fb2ef77de68f28c4f13814819f6a1Lennart Poettering _cleanup_free_ char *destination = NULL;
58db254ade4fb2ef77de68f28c4f13814819f6a1Lennart Poettering const char *d;
58db254ade4fb2ef77de68f28c4f13814819f6a1Lennart Poettering
58db254ade4fb2ef77de68f28c4f13814819f6a1Lennart Poettering if (cname->key->type == DNS_TYPE_CNAME)
58db254ade4fb2ef77de68f28c4f13814819f6a1Lennart Poettering d = cname->cname.name;
58db254ade4fb2ef77de68f28c4f13814819f6a1Lennart Poettering else {
23b298bce75a0d1f4f15f34458af9678b4a30c3aLennart Poettering r = dns_name_change_suffix(DNS_RESOURCE_KEY_NAME(key), DNS_RESOURCE_KEY_NAME(cname->key), cname->dname.name, &destination);
58db254ade4fb2ef77de68f28c4f13814819f6a1Lennart Poettering if (r < 0)
58db254ade4fb2ef77de68f28c4f13814819f6a1Lennart Poettering return r;
58db254ade4fb2ef77de68f28c4f13814819f6a1Lennart Poettering if (r == 0)
58db254ade4fb2ef77de68f28c4f13814819f6a1Lennart Poettering continue;
58db254ade4fb2ef77de68f28c4f13814819f6a1Lennart Poettering
58db254ade4fb2ef77de68f28c4f13814819f6a1Lennart Poettering d = destination;
58db254ade4fb2ef77de68f28c4f13814819f6a1Lennart Poettering }
58db254ade4fb2ef77de68f28c4f13814819f6a1Lennart Poettering
23b298bce75a0d1f4f15f34458af9678b4a30c3aLennart Poettering r = dns_name_equal(DNS_RESOURCE_KEY_NAME(key), d);
faa133f3aa7a18f26563dc5d6b95898cb315c37aLennart Poettering if (r < 0)
faa133f3aa7a18f26563dc5d6b95898cb315c37aLennart Poettering return r;
faa133f3aa7a18f26563dc5d6b95898cb315c37aLennart Poettering
faa133f3aa7a18f26563dc5d6b95898cb315c37aLennart Poettering if (r == 0) {
faa133f3aa7a18f26563dc5d6b95898cb315c37aLennart Poettering same = false;
faa133f3aa7a18f26563dc5d6b95898cb315c37aLennart Poettering break;
faa133f3aa7a18f26563dc5d6b95898cb315c37aLennart Poettering }
faa133f3aa7a18f26563dc5d6b95898cb315c37aLennart Poettering }
faa133f3aa7a18f26563dc5d6b95898cb315c37aLennart Poettering
23b298bce75a0d1f4f15f34458af9678b4a30c3aLennart Poettering /* Fully the same, indicate we didn't do a thing */
faa133f3aa7a18f26563dc5d6b95898cb315c37aLennart Poettering if (same) {
23b298bce75a0d1f4f15f34458af9678b4a30c3aLennart Poettering *ret = NULL;
faa133f3aa7a18f26563dc5d6b95898cb315c37aLennart Poettering return 0;
faa133f3aa7a18f26563dc5d6b95898cb315c37aLennart Poettering }
faa133f3aa7a18f26563dc5d6b95898cb315c37aLennart Poettering
faa133f3aa7a18f26563dc5d6b95898cb315c37aLennart Poettering n = dns_question_new(q->n_keys);
faa133f3aa7a18f26563dc5d6b95898cb315c37aLennart Poettering if (!n)
faa133f3aa7a18f26563dc5d6b95898cb315c37aLennart Poettering return -ENOMEM;
faa133f3aa7a18f26563dc5d6b95898cb315c37aLennart Poettering
faa133f3aa7a18f26563dc5d6b95898cb315c37aLennart Poettering /* Create a new question, and patch in the new name */
23b298bce75a0d1f4f15f34458af9678b4a30c3aLennart Poettering DNS_QUESTION_FOREACH(key, q) {
faa133f3aa7a18f26563dc5d6b95898cb315c37aLennart Poettering _cleanup_(dns_resource_key_unrefp) DnsResourceKey *k = NULL;
faa133f3aa7a18f26563dc5d6b95898cb315c37aLennart Poettering
23b298bce75a0d1f4f15f34458af9678b4a30c3aLennart Poettering k = dns_resource_key_new_redirect(key, cname);
faa133f3aa7a18f26563dc5d6b95898cb315c37aLennart Poettering if (!k)
faa133f3aa7a18f26563dc5d6b95898cb315c37aLennart Poettering return -ENOMEM;
faa133f3aa7a18f26563dc5d6b95898cb315c37aLennart Poettering
faa133f3aa7a18f26563dc5d6b95898cb315c37aLennart Poettering r = dns_question_add(n, k);
faa133f3aa7a18f26563dc5d6b95898cb315c37aLennart Poettering if (r < 0)
faa133f3aa7a18f26563dc5d6b95898cb315c37aLennart Poettering return r;
faa133f3aa7a18f26563dc5d6b95898cb315c37aLennart Poettering }
faa133f3aa7a18f26563dc5d6b95898cb315c37aLennart Poettering
faa133f3aa7a18f26563dc5d6b95898cb315c37aLennart Poettering *ret = n;
faa133f3aa7a18f26563dc5d6b95898cb315c37aLennart Poettering n = NULL;
faa133f3aa7a18f26563dc5d6b95898cb315c37aLennart Poettering
faa133f3aa7a18f26563dc5d6b95898cb315c37aLennart Poettering return 1;
faa133f3aa7a18f26563dc5d6b95898cb315c37aLennart Poettering}
45ec7efb6c2560c80dfa752bc9d3733749dc52cbLennart Poettering
703e4f5e39c019da8c002ba10bd450ce378c0e91Lennart Poetteringconst char *dns_question_first_name(DnsQuestion *q) {
703e4f5e39c019da8c002ba10bd450ce378c0e91Lennart Poettering
703e4f5e39c019da8c002ba10bd450ce378c0e91Lennart Poettering if (!q)
703e4f5e39c019da8c002ba10bd450ce378c0e91Lennart Poettering return NULL;
45ec7efb6c2560c80dfa752bc9d3733749dc52cbLennart Poettering
45ec7efb6c2560c80dfa752bc9d3733749dc52cbLennart Poettering if (q->n_keys < 1)
45ec7efb6c2560c80dfa752bc9d3733749dc52cbLennart Poettering return NULL;
45ec7efb6c2560c80dfa752bc9d3733749dc52cbLennart Poettering
45ec7efb6c2560c80dfa752bc9d3733749dc52cbLennart Poettering return DNS_RESOURCE_KEY_NAME(q->keys[0]);
45ec7efb6c2560c80dfa752bc9d3733749dc52cbLennart Poettering}
45ec7efb6c2560c80dfa752bc9d3733749dc52cbLennart Poettering
23b298bce75a0d1f4f15f34458af9678b4a30c3aLennart Poetteringint dns_question_new_address(DnsQuestion **ret, int family, const char *name, bool convert_idna) {
45ec7efb6c2560c80dfa752bc9d3733749dc52cbLennart Poettering _cleanup_(dns_question_unrefp) DnsQuestion *q = NULL;
23b298bce75a0d1f4f15f34458af9678b4a30c3aLennart Poettering _cleanup_free_ char *buf = NULL;
45ec7efb6c2560c80dfa752bc9d3733749dc52cbLennart Poettering int r;
45ec7efb6c2560c80dfa752bc9d3733749dc52cbLennart Poettering
45ec7efb6c2560c80dfa752bc9d3733749dc52cbLennart Poettering assert(ret);
45ec7efb6c2560c80dfa752bc9d3733749dc52cbLennart Poettering assert(name);
45ec7efb6c2560c80dfa752bc9d3733749dc52cbLennart Poettering
45ec7efb6c2560c80dfa752bc9d3733749dc52cbLennart Poettering if (!IN_SET(family, AF_INET, AF_INET6, AF_UNSPEC))
45ec7efb6c2560c80dfa752bc9d3733749dc52cbLennart Poettering return -EAFNOSUPPORT;
45ec7efb6c2560c80dfa752bc9d3733749dc52cbLennart Poettering
23b298bce75a0d1f4f15f34458af9678b4a30c3aLennart Poettering if (convert_idna) {
23b298bce75a0d1f4f15f34458af9678b4a30c3aLennart Poettering r = dns_name_apply_idna(name, &buf);
23b298bce75a0d1f4f15f34458af9678b4a30c3aLennart Poettering if (r < 0)
23b298bce75a0d1f4f15f34458af9678b4a30c3aLennart Poettering return r;
23b298bce75a0d1f4f15f34458af9678b4a30c3aLennart Poettering
23b298bce75a0d1f4f15f34458af9678b4a30c3aLennart Poettering name = buf;
23b298bce75a0d1f4f15f34458af9678b4a30c3aLennart Poettering }
23b298bce75a0d1f4f15f34458af9678b4a30c3aLennart Poettering
45ec7efb6c2560c80dfa752bc9d3733749dc52cbLennart Poettering q = dns_question_new(family == AF_UNSPEC ? 2 : 1);
45ec7efb6c2560c80dfa752bc9d3733749dc52cbLennart Poettering if (!q)
45ec7efb6c2560c80dfa752bc9d3733749dc52cbLennart Poettering return -ENOMEM;
45ec7efb6c2560c80dfa752bc9d3733749dc52cbLennart Poettering
45ec7efb6c2560c80dfa752bc9d3733749dc52cbLennart Poettering if (family != AF_INET6) {
45ec7efb6c2560c80dfa752bc9d3733749dc52cbLennart Poettering _cleanup_(dns_resource_key_unrefp) DnsResourceKey *key = NULL;
45ec7efb6c2560c80dfa752bc9d3733749dc52cbLennart Poettering
45ec7efb6c2560c80dfa752bc9d3733749dc52cbLennart Poettering key = dns_resource_key_new(DNS_CLASS_IN, DNS_TYPE_A, name);
45ec7efb6c2560c80dfa752bc9d3733749dc52cbLennart Poettering if (!key)
45ec7efb6c2560c80dfa752bc9d3733749dc52cbLennart Poettering return -ENOMEM;
45ec7efb6c2560c80dfa752bc9d3733749dc52cbLennart Poettering
45ec7efb6c2560c80dfa752bc9d3733749dc52cbLennart Poettering r = dns_question_add(q, key);
45ec7efb6c2560c80dfa752bc9d3733749dc52cbLennart Poettering if (r < 0)
45ec7efb6c2560c80dfa752bc9d3733749dc52cbLennart Poettering return r;
45ec7efb6c2560c80dfa752bc9d3733749dc52cbLennart Poettering }
45ec7efb6c2560c80dfa752bc9d3733749dc52cbLennart Poettering
45ec7efb6c2560c80dfa752bc9d3733749dc52cbLennart Poettering if (family != AF_INET) {
45ec7efb6c2560c80dfa752bc9d3733749dc52cbLennart Poettering _cleanup_(dns_resource_key_unrefp) DnsResourceKey *key = NULL;
45ec7efb6c2560c80dfa752bc9d3733749dc52cbLennart Poettering
45ec7efb6c2560c80dfa752bc9d3733749dc52cbLennart Poettering key = dns_resource_key_new(DNS_CLASS_IN, DNS_TYPE_AAAA, name);
45ec7efb6c2560c80dfa752bc9d3733749dc52cbLennart Poettering if (!key)
45ec7efb6c2560c80dfa752bc9d3733749dc52cbLennart Poettering return -ENOMEM;
45ec7efb6c2560c80dfa752bc9d3733749dc52cbLennart Poettering
45ec7efb6c2560c80dfa752bc9d3733749dc52cbLennart Poettering r = dns_question_add(q, key);
45ec7efb6c2560c80dfa752bc9d3733749dc52cbLennart Poettering if (r < 0)
45ec7efb6c2560c80dfa752bc9d3733749dc52cbLennart Poettering return r;
45ec7efb6c2560c80dfa752bc9d3733749dc52cbLennart Poettering }
45ec7efb6c2560c80dfa752bc9d3733749dc52cbLennart Poettering
45ec7efb6c2560c80dfa752bc9d3733749dc52cbLennart Poettering *ret = q;
45ec7efb6c2560c80dfa752bc9d3733749dc52cbLennart Poettering q = NULL;
45ec7efb6c2560c80dfa752bc9d3733749dc52cbLennart Poettering
45ec7efb6c2560c80dfa752bc9d3733749dc52cbLennart Poettering return 0;
45ec7efb6c2560c80dfa752bc9d3733749dc52cbLennart Poettering}
45ec7efb6c2560c80dfa752bc9d3733749dc52cbLennart Poettering
45ec7efb6c2560c80dfa752bc9d3733749dc52cbLennart Poetteringint dns_question_new_reverse(DnsQuestion **ret, int family, const union in_addr_union *a) {
45ec7efb6c2560c80dfa752bc9d3733749dc52cbLennart Poettering _cleanup_(dns_resource_key_unrefp) DnsResourceKey *key = NULL;
45ec7efb6c2560c80dfa752bc9d3733749dc52cbLennart Poettering _cleanup_(dns_question_unrefp) DnsQuestion *q = NULL;
45ec7efb6c2560c80dfa752bc9d3733749dc52cbLennart Poettering _cleanup_free_ char *reverse = NULL;
45ec7efb6c2560c80dfa752bc9d3733749dc52cbLennart Poettering int r;
45ec7efb6c2560c80dfa752bc9d3733749dc52cbLennart Poettering
45ec7efb6c2560c80dfa752bc9d3733749dc52cbLennart Poettering assert(ret);
45ec7efb6c2560c80dfa752bc9d3733749dc52cbLennart Poettering assert(a);
45ec7efb6c2560c80dfa752bc9d3733749dc52cbLennart Poettering
45ec7efb6c2560c80dfa752bc9d3733749dc52cbLennart Poettering if (!IN_SET(family, AF_INET, AF_INET6, AF_UNSPEC))
45ec7efb6c2560c80dfa752bc9d3733749dc52cbLennart Poettering return -EAFNOSUPPORT;
45ec7efb6c2560c80dfa752bc9d3733749dc52cbLennart Poettering
45ec7efb6c2560c80dfa752bc9d3733749dc52cbLennart Poettering r = dns_name_reverse(family, a, &reverse);
45ec7efb6c2560c80dfa752bc9d3733749dc52cbLennart Poettering if (r < 0)
45ec7efb6c2560c80dfa752bc9d3733749dc52cbLennart Poettering return r;
45ec7efb6c2560c80dfa752bc9d3733749dc52cbLennart Poettering
45ec7efb6c2560c80dfa752bc9d3733749dc52cbLennart Poettering q = dns_question_new(1);
45ec7efb6c2560c80dfa752bc9d3733749dc52cbLennart Poettering if (!q)
45ec7efb6c2560c80dfa752bc9d3733749dc52cbLennart Poettering return -ENOMEM;
45ec7efb6c2560c80dfa752bc9d3733749dc52cbLennart Poettering
45ec7efb6c2560c80dfa752bc9d3733749dc52cbLennart Poettering key = dns_resource_key_new_consume(DNS_CLASS_IN, DNS_TYPE_PTR, reverse);
45ec7efb6c2560c80dfa752bc9d3733749dc52cbLennart Poettering if (!key)
45ec7efb6c2560c80dfa752bc9d3733749dc52cbLennart Poettering return -ENOMEM;
45ec7efb6c2560c80dfa752bc9d3733749dc52cbLennart Poettering
45ec7efb6c2560c80dfa752bc9d3733749dc52cbLennart Poettering reverse = NULL;
45ec7efb6c2560c80dfa752bc9d3733749dc52cbLennart Poettering
45ec7efb6c2560c80dfa752bc9d3733749dc52cbLennart Poettering r = dns_question_add(q, key);
45ec7efb6c2560c80dfa752bc9d3733749dc52cbLennart Poettering if (r < 0)
45ec7efb6c2560c80dfa752bc9d3733749dc52cbLennart Poettering return r;
45ec7efb6c2560c80dfa752bc9d3733749dc52cbLennart Poettering
45ec7efb6c2560c80dfa752bc9d3733749dc52cbLennart Poettering *ret = q;
45ec7efb6c2560c80dfa752bc9d3733749dc52cbLennart Poettering q = NULL;
45ec7efb6c2560c80dfa752bc9d3733749dc52cbLennart Poettering
45ec7efb6c2560c80dfa752bc9d3733749dc52cbLennart Poettering return 0;
45ec7efb6c2560c80dfa752bc9d3733749dc52cbLennart Poettering}
45ec7efb6c2560c80dfa752bc9d3733749dc52cbLennart Poettering
23b298bce75a0d1f4f15f34458af9678b4a30c3aLennart Poetteringint dns_question_new_service(
23b298bce75a0d1f4f15f34458af9678b4a30c3aLennart Poettering DnsQuestion **ret,
23b298bce75a0d1f4f15f34458af9678b4a30c3aLennart Poettering const char *service,
23b298bce75a0d1f4f15f34458af9678b4a30c3aLennart Poettering const char *type,
23b298bce75a0d1f4f15f34458af9678b4a30c3aLennart Poettering const char *domain,
23b298bce75a0d1f4f15f34458af9678b4a30c3aLennart Poettering bool with_txt,
23b298bce75a0d1f4f15f34458af9678b4a30c3aLennart Poettering bool convert_idna) {
23b298bce75a0d1f4f15f34458af9678b4a30c3aLennart Poettering
45ec7efb6c2560c80dfa752bc9d3733749dc52cbLennart Poettering _cleanup_(dns_resource_key_unrefp) DnsResourceKey *key = NULL;
45ec7efb6c2560c80dfa752bc9d3733749dc52cbLennart Poettering _cleanup_(dns_question_unrefp) DnsQuestion *q = NULL;
23b298bce75a0d1f4f15f34458af9678b4a30c3aLennart Poettering _cleanup_free_ char *buf = NULL, *joined = NULL;
23b298bce75a0d1f4f15f34458af9678b4a30c3aLennart Poettering const char *name;
45ec7efb6c2560c80dfa752bc9d3733749dc52cbLennart Poettering int r;
45ec7efb6c2560c80dfa752bc9d3733749dc52cbLennart Poettering
45ec7efb6c2560c80dfa752bc9d3733749dc52cbLennart Poettering assert(ret);
23b298bce75a0d1f4f15f34458af9678b4a30c3aLennart Poettering
23b298bce75a0d1f4f15f34458af9678b4a30c3aLennart Poettering /* We support three modes of invocation:
23b298bce75a0d1f4f15f34458af9678b4a30c3aLennart Poettering *
23b298bce75a0d1f4f15f34458af9678b4a30c3aLennart Poettering * 1. Only a domain is specified, in which case we assume a properly encoded SRV RR name, including service
23b298bce75a0d1f4f15f34458af9678b4a30c3aLennart Poettering * type and possibly a service name. If specified in this way we assume it's already IDNA converted if
23b298bce75a0d1f4f15f34458af9678b4a30c3aLennart Poettering * that's necessary.
23b298bce75a0d1f4f15f34458af9678b4a30c3aLennart Poettering *
23b298bce75a0d1f4f15f34458af9678b4a30c3aLennart Poettering * 2. Both service type and a domain specified, in which case a normal SRV RR is assumed, without a DNS-SD
23b298bce75a0d1f4f15f34458af9678b4a30c3aLennart Poettering * style prefix. In this case we'll IDNA convert the domain, if that's requested.
23b298bce75a0d1f4f15f34458af9678b4a30c3aLennart Poettering *
23b298bce75a0d1f4f15f34458af9678b4a30c3aLennart Poettering * 3. All three of service name, type and domain are specified, in which case a DNS-SD service is put
23b298bce75a0d1f4f15f34458af9678b4a30c3aLennart Poettering * together. The service name is never IDNA converted, and the domain is if requested.
23b298bce75a0d1f4f15f34458af9678b4a30c3aLennart Poettering *
23b298bce75a0d1f4f15f34458af9678b4a30c3aLennart Poettering * It's not supported to specify a service name without a type, or no domain name.
23b298bce75a0d1f4f15f34458af9678b4a30c3aLennart Poettering */
23b298bce75a0d1f4f15f34458af9678b4a30c3aLennart Poettering
23b298bce75a0d1f4f15f34458af9678b4a30c3aLennart Poettering if (!domain)
23b298bce75a0d1f4f15f34458af9678b4a30c3aLennart Poettering return -EINVAL;
23b298bce75a0d1f4f15f34458af9678b4a30c3aLennart Poettering
23b298bce75a0d1f4f15f34458af9678b4a30c3aLennart Poettering if (type) {
23b298bce75a0d1f4f15f34458af9678b4a30c3aLennart Poettering if (convert_idna) {
23b298bce75a0d1f4f15f34458af9678b4a30c3aLennart Poettering r = dns_name_apply_idna(domain, &buf);
23b298bce75a0d1f4f15f34458af9678b4a30c3aLennart Poettering if (r < 0)
23b298bce75a0d1f4f15f34458af9678b4a30c3aLennart Poettering return r;
23b298bce75a0d1f4f15f34458af9678b4a30c3aLennart Poettering
23b298bce75a0d1f4f15f34458af9678b4a30c3aLennart Poettering domain = buf;
23b298bce75a0d1f4f15f34458af9678b4a30c3aLennart Poettering }
23b298bce75a0d1f4f15f34458af9678b4a30c3aLennart Poettering
23b298bce75a0d1f4f15f34458af9678b4a30c3aLennart Poettering r = dns_service_join(service, type, domain, &joined);
23b298bce75a0d1f4f15f34458af9678b4a30c3aLennart Poettering if (r < 0)
23b298bce75a0d1f4f15f34458af9678b4a30c3aLennart Poettering return r;
23b298bce75a0d1f4f15f34458af9678b4a30c3aLennart Poettering
23b298bce75a0d1f4f15f34458af9678b4a30c3aLennart Poettering name = joined;
23b298bce75a0d1f4f15f34458af9678b4a30c3aLennart Poettering } else {
23b298bce75a0d1f4f15f34458af9678b4a30c3aLennart Poettering if (service)
23b298bce75a0d1f4f15f34458af9678b4a30c3aLennart Poettering return -EINVAL;
23b298bce75a0d1f4f15f34458af9678b4a30c3aLennart Poettering
23b298bce75a0d1f4f15f34458af9678b4a30c3aLennart Poettering name = domain;
23b298bce75a0d1f4f15f34458af9678b4a30c3aLennart Poettering }
45ec7efb6c2560c80dfa752bc9d3733749dc52cbLennart Poettering
45ec7efb6c2560c80dfa752bc9d3733749dc52cbLennart Poettering q = dns_question_new(1 + with_txt);
45ec7efb6c2560c80dfa752bc9d3733749dc52cbLennart Poettering if (!q)
45ec7efb6c2560c80dfa752bc9d3733749dc52cbLennart Poettering return -ENOMEM;
45ec7efb6c2560c80dfa752bc9d3733749dc52cbLennart Poettering
45ec7efb6c2560c80dfa752bc9d3733749dc52cbLennart Poettering key = dns_resource_key_new(DNS_CLASS_IN, DNS_TYPE_SRV, name);
45ec7efb6c2560c80dfa752bc9d3733749dc52cbLennart Poettering if (!key)
45ec7efb6c2560c80dfa752bc9d3733749dc52cbLennart Poettering return -ENOMEM;
45ec7efb6c2560c80dfa752bc9d3733749dc52cbLennart Poettering
45ec7efb6c2560c80dfa752bc9d3733749dc52cbLennart Poettering r = dns_question_add(q, key);
45ec7efb6c2560c80dfa752bc9d3733749dc52cbLennart Poettering if (r < 0)
45ec7efb6c2560c80dfa752bc9d3733749dc52cbLennart Poettering return r;
45ec7efb6c2560c80dfa752bc9d3733749dc52cbLennart Poettering
45ec7efb6c2560c80dfa752bc9d3733749dc52cbLennart Poettering if (with_txt) {
45ec7efb6c2560c80dfa752bc9d3733749dc52cbLennart Poettering dns_resource_key_unref(key);
45ec7efb6c2560c80dfa752bc9d3733749dc52cbLennart Poettering key = dns_resource_key_new(DNS_CLASS_IN, DNS_TYPE_TXT, name);
45ec7efb6c2560c80dfa752bc9d3733749dc52cbLennart Poettering if (!key)
45ec7efb6c2560c80dfa752bc9d3733749dc52cbLennart Poettering return -ENOMEM;
45ec7efb6c2560c80dfa752bc9d3733749dc52cbLennart Poettering
45ec7efb6c2560c80dfa752bc9d3733749dc52cbLennart Poettering r = dns_question_add(q, key);
45ec7efb6c2560c80dfa752bc9d3733749dc52cbLennart Poettering if (r < 0)
45ec7efb6c2560c80dfa752bc9d3733749dc52cbLennart Poettering return r;
45ec7efb6c2560c80dfa752bc9d3733749dc52cbLennart Poettering }
45ec7efb6c2560c80dfa752bc9d3733749dc52cbLennart Poettering
45ec7efb6c2560c80dfa752bc9d3733749dc52cbLennart Poettering *ret = q;
45ec7efb6c2560c80dfa752bc9d3733749dc52cbLennart Poettering q = NULL;
45ec7efb6c2560c80dfa752bc9d3733749dc52cbLennart Poettering
45ec7efb6c2560c80dfa752bc9d3733749dc52cbLennart Poettering return 0;
45ec7efb6c2560c80dfa752bc9d3733749dc52cbLennart Poettering}