resolved-dns-query.c revision d634711b261dc72bb48765e8574ba43d455e82ec
091a364c802e34a58f3260c9cb5db9b75c62215cTom Gundersen/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
091a364c802e34a58f3260c9cb5db9b75c62215cTom Gundersen
091a364c802e34a58f3260c9cb5db9b75c62215cTom Gundersen/***
091a364c802e34a58f3260c9cb5db9b75c62215cTom Gundersen This file is part of systemd.
091a364c802e34a58f3260c9cb5db9b75c62215cTom Gundersen
091a364c802e34a58f3260c9cb5db9b75c62215cTom Gundersen Copyright 2014 Lennart Poettering
091a364c802e34a58f3260c9cb5db9b75c62215cTom Gundersen
091a364c802e34a58f3260c9cb5db9b75c62215cTom Gundersen systemd is free software; you can redistribute it and/or modify it
091a364c802e34a58f3260c9cb5db9b75c62215cTom Gundersen under the terms of the GNU Lesser General Public License as published by
091a364c802e34a58f3260c9cb5db9b75c62215cTom Gundersen the Free Software Foundation; either version 2.1 of the License, or
091a364c802e34a58f3260c9cb5db9b75c62215cTom Gundersen (at your option) any later version.
091a364c802e34a58f3260c9cb5db9b75c62215cTom Gundersen
091a364c802e34a58f3260c9cb5db9b75c62215cTom Gundersen systemd is distributed in the hope that it will be useful, but
091a364c802e34a58f3260c9cb5db9b75c62215cTom Gundersen WITHOUT ANY WARRANTY; without even the implied warranty of
091a364c802e34a58f3260c9cb5db9b75c62215cTom Gundersen MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
091a364c802e34a58f3260c9cb5db9b75c62215cTom Gundersen Lesser General Public License for more details.
091a364c802e34a58f3260c9cb5db9b75c62215cTom Gundersen
091a364c802e34a58f3260c9cb5db9b75c62215cTom Gundersen You should have received a copy of the GNU Lesser General Public License
091a364c802e34a58f3260c9cb5db9b75c62215cTom Gundersen along with systemd; If not, see <http://www.gnu.org/licenses/>.
091a364c802e34a58f3260c9cb5db9b75c62215cTom Gundersen***/
091a364c802e34a58f3260c9cb5db9b75c62215cTom Gundersen
07630cea1f3a845c09309f197ac7c4f11edd3b62Lennart Poettering#include "hostname-util.h"
07630cea1f3a845c09309f197ac7c4f11edd3b62Lennart Poettering#include "dns-domain.h"
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering#include "local-addresses.h"
091a364c802e34a58f3260c9cb5db9b75c62215cTom Gundersen
a2a416f768e2aa7db5b975cd50eb19237cac9cceLennart Poettering#include "resolved-dns-query.h"
b5efdb8af40ea759a1ea584c1bc44ecc81dd00ceLennart Poettering
07630cea1f3a845c09309f197ac7c4f11edd3b62Lennart Poettering/* How long to wait for the query in total */
3ffd4af22052963e7a29431721ee204e634bea75Lennart Poettering#define QUERY_TIMEOUT_USEC (30 * USEC_PER_SEC)
a5a807e63a50314e190e9166d8a453cd8dd258e3Zbigniew Jędrzejewski-Szmek
07630cea1f3a845c09309f197ac7c4f11edd3b62Lennart Poettering#define CNAME_MAX 8
c004493cdefc1f43a3956ca529e8070f8d70be56Lennart Poettering#define QUERIES_MAX 2048
07630cea1f3a845c09309f197ac7c4f11edd3b62Lennart Poettering
07630cea1f3a845c09309f197ac7c4f11edd3b62Lennart Poetteringstatic void dns_query_stop(DnsQuery *q) {
822db23cfa98a9fbc48f41e11caafb6f1017e052Lennart Poettering DnsTransaction *t;
6bedfcbb2970e06a4d3280c8fb62083d252ede73Lennart Poettering
3df3e884ae1237ef0d4d23b0e80f4ffda95ac135Ronny Chevalier assert(q);
39d8db043b599a7382f94bfc904d5e108af438bdLennart Poettering
07630cea1f3a845c09309f197ac7c4f11edd3b62Lennart Poettering q->timeout_event_source = sd_event_source_unref(q->timeout_event_source);
5f402ae84bbc08fe8de5682e371b3f66c387da52Daniel Mack
07630cea1f3a845c09309f197ac7c4f11edd3b62Lennart Poettering while ((t = set_steal_first(q->transactions))) {
f8dc7e343d903f053070d01f3273db819deee951Lennart Poettering set_remove(t->queries, q);
bc7702b098b63031767174206f5df14a8ccb45cfDaniel Mack dns_transaction_gc(t);
07630cea1f3a845c09309f197ac7c4f11edd3b62Lennart Poettering }
8b43440b7ef4b81c69c31de7ff820dc07a780254Lennart Poettering}
07630cea1f3a845c09309f197ac7c4f11edd3b62Lennart Poettering
07630cea1f3a845c09309f197ac7c4f11edd3b62Lennart PoetteringDnsQuery *dns_query_free(DnsQuery *q) {
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering if (!q)
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering return NULL;
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering
1c4baffc1895809bae9ac36b670af90a4cb9cd7dTom Gundersen dns_query_stop(q);
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering set_free(q->transactions);
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering dns_question_unref(q->question);
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering dns_answer_unref(q->answer);
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering sd_bus_message_unref(q->request);
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering sd_bus_track_unref(q->bus_track);
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering if (q->manager) {
1c4baffc1895809bae9ac36b670af90a4cb9cd7dTom Gundersen LIST_REMOVE(queries, q->manager->dns_queries, q);
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering q->manager->n_dns_queries--;
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering }
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering free(q);
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering return NULL;
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering}
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poetteringint dns_query_new(Manager *m, DnsQuery **ret, DnsQuestion *question, int ifindex, uint64_t flags) {
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering _cleanup_(dns_query_freep) DnsQuery *q = NULL;
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering unsigned i;
a2a416f768e2aa7db5b975cd50eb19237cac9cceLennart Poettering int r;
a2a416f768e2aa7db5b975cd50eb19237cac9cceLennart Poettering
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering assert(m);
a2a416f768e2aa7db5b975cd50eb19237cac9cceLennart Poettering assert(question);
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering r = dns_question_is_valid(question);
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering if (r < 0)
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering return r;
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering if (m->n_dns_queries >= QUERIES_MAX)
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering return -EBUSY;
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering q = new0(DnsQuery, 1);
21d73c87b09ec2b8642424bc714ce9af3da4fc40Lennart Poettering if (!q)
21d73c87b09ec2b8642424bc714ce9af3da4fc40Lennart Poettering return -ENOMEM;
21d73c87b09ec2b8642424bc714ce9af3da4fc40Lennart Poettering
21d73c87b09ec2b8642424bc714ce9af3da4fc40Lennart Poettering q->question = dns_question_ref(question);
a2a416f768e2aa7db5b975cd50eb19237cac9cceLennart Poettering q->ifindex = ifindex;
a2a416f768e2aa7db5b975cd50eb19237cac9cceLennart Poettering q->flags = flags;
a2a416f768e2aa7db5b975cd50eb19237cac9cceLennart Poettering
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering for (i = 0; i < question->n_keys; i++) {
a2a416f768e2aa7db5b975cd50eb19237cac9cceLennart Poettering _cleanup_free_ char *p;
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering r = dns_resource_key_to_string(question->keys[i], &p);
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering if (r < 0)
a2a416f768e2aa7db5b975cd50eb19237cac9cceLennart Poettering return r;
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering log_debug("Looking up RR for %s", p);
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering }
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering LIST_PREPEND(queries, m->dns_queries, q);
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering m->n_dns_queries++;
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering q->manager = m;
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering if (ret)
da927ba997d68401563b927f92e6e40e021a8e5cMichal Schmidt *ret = q;
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering q = NULL;
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering return 0;
1c4baffc1895809bae9ac36b670af90a4cb9cd7dTom Gundersen}
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poetteringstatic void dns_query_complete(DnsQuery *q, DnsTransactionState state) {
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering assert(q);
0dd25fb9f005d8ab7ac4bc10a609d00569f8c56aLennart Poettering assert(!IN_SET(state, DNS_TRANSACTION_NULL, DNS_TRANSACTION_PENDING));
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering assert(IN_SET(q->state, DNS_TRANSACTION_NULL, DNS_TRANSACTION_PENDING));
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering /* Note that this call might invalidate the query. Callers
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering * should hence not attempt to access the query or transaction
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering * after calling this function. */
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering q->state = state;
1c4baffc1895809bae9ac36b670af90a4cb9cd7dTom Gundersen
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering dns_query_stop(q);
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering if (q->complete)
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering q->complete(q);
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering}
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poetteringstatic int on_query_timeout(sd_event_source *s, usec_t usec, void *userdata) {
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering DnsQuery *q = userdata;
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering assert(s);
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering assert(q);
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering dns_query_complete(q, DNS_TRANSACTION_TIMEOUT);
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering return 0;
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering}
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poetteringstatic int dns_query_add_transaction(DnsQuery *q, DnsScope *s, DnsResourceKey *key) {
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering DnsTransaction *t;
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering int r;
1c4baffc1895809bae9ac36b670af90a4cb9cd7dTom Gundersen
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering assert(q);
1c4baffc1895809bae9ac36b670af90a4cb9cd7dTom Gundersen assert(s);
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering assert(key);
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering r = set_ensure_allocated(&q->transactions, NULL);
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering if (r < 0)
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering return r;
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering t = dns_scope_find_transaction(s, key, true);
1c4baffc1895809bae9ac36b670af90a4cb9cd7dTom Gundersen if (!t) {
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering r = dns_transaction_new(&t, s, key);
1c4baffc1895809bae9ac36b670af90a4cb9cd7dTom Gundersen if (r < 0)
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering return r;
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering }
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering r = set_ensure_allocated(&t->queries, NULL);
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering if (r < 0)
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering goto gc;
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering r = set_put(t->queries, q);
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering if (r < 0)
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering goto gc;
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering r = set_put(q->transactions, t);
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering if (r < 0) {
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering set_remove(t->queries, q);
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering goto gc;
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering }
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering return 0;
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poetteringgc:
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering dns_transaction_gc(t);
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering return r;
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering}
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poetteringstatic int dns_query_add_transaction_split(DnsQuery *q, DnsScope *s) {
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering unsigned i;
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering int r;
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering assert(q);
3e044c492e3ebe64f4e3175c94f9db8a62557b82Markus Elfring assert(s);
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering /* Create one transaction per question key */
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering for (i = 0; i < q->question->n_keys; i++) {
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering r = dns_query_add_transaction(q, s, q->question->keys[i]);
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering if (r < 0)
da927ba997d68401563b927f92e6e40e021a8e5cMichal Schmidt return r;
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering }
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering return 0;
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering}
4afd3348c7506dd1d36305b7bcb9feb8952b9d6bLennart Poettering
1c4baffc1895809bae9ac36b670af90a4cb9cd7dTom Gundersenstatic int SYNTHESIZE_IFINDEX(int ifindex) {
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering /* When the caller asked for resolving on a specific
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering * interface, we synthesize the answer for that
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering * interface. However, if nothing specific was claimed and we
cc98b3025eeb89addb76a27390cb2baca4eab8b9Torstein Husebø * only return localhost RRs, we synthesize the answer for
1c4baffc1895809bae9ac36b670af90a4cb9cd7dTom Gundersen * localhost. */
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering if (ifindex > 0)
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering return ifindex;
1c4baffc1895809bae9ac36b670af90a4cb9cd7dTom Gundersen
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering return LOOPBACK_IFINDEX;
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering}
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering
1c4baffc1895809bae9ac36b670af90a4cb9cd7dTom Gundersenstatic int SYNTHESIZE_FAMILY(uint64_t flags) {
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering /* Picks an address family depending on set flags. This is
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering * purely for synthesized answers, where the family we return
1c4baffc1895809bae9ac36b670af90a4cb9cd7dTom Gundersen * for the reply should match what was requested in the
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering * question, even though we are synthesizing the answer
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering * here. */
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering
1c4baffc1895809bae9ac36b670af90a4cb9cd7dTom Gundersen if (!(flags & SD_RESOLVED_DNS)) {
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering if (flags & SD_RESOLVED_LLMNR_IPV4)
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering return AF_INET;
091a364c802e34a58f3260c9cb5db9b75c62215cTom Gundersen if (flags & SD_RESOLVED_LLMNR_IPV6)
1c4baffc1895809bae9ac36b670af90a4cb9cd7dTom Gundersen return AF_INET6;
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering }
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering return AF_UNSPEC;
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering}
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poetteringstatic DnsProtocol SYNTHESIZE_PROTOCOL(uint64_t flags) {
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering /* Similar as SYNTHESIZE_FAMILY() but does this for the
1c4baffc1895809bae9ac36b670af90a4cb9cd7dTom Gundersen * protocol. If resolving via DNS was requested, we claim it
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering * was DNS. Similar, if nothing specific was
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering * requested. However, if only resolving via LLMNR was
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering * requested we return that. */
1c4baffc1895809bae9ac36b670af90a4cb9cd7dTom Gundersen
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering if (flags & SD_RESOLVED_DNS)
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering return DNS_PROTOCOL_DNS;
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering if (flags & SD_RESOLVED_LLMNR)
1c4baffc1895809bae9ac36b670af90a4cb9cd7dTom Gundersen return DNS_PROTOCOL_LLMNR;
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering return DNS_PROTOCOL_DNS;
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering}
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poetteringstatic int dns_type_to_af(uint16_t t) {
1c4baffc1895809bae9ac36b670af90a4cb9cd7dTom Gundersen switch (t) {
1c4baffc1895809bae9ac36b670af90a4cb9cd7dTom Gundersen
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering case DNS_TYPE_A:
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering return AF_INET;
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering case DNS_TYPE_AAAA:
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering return AF_INET6;
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering
1c4baffc1895809bae9ac36b670af90a4cb9cd7dTom Gundersen case DNS_TYPE_ANY:
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering return AF_UNSPEC;
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering default:
1c4baffc1895809bae9ac36b670af90a4cb9cd7dTom Gundersen return -EINVAL;
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering }
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering}
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering
1c4baffc1895809bae9ac36b670af90a4cb9cd7dTom Gundersenstatic int synthesize_localhost_rr(DnsQuery *q, DnsResourceKey *key, DnsAnswer **answer) {
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering int r;
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering assert(q);
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering assert(key);
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering assert(answer);
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering r = dns_answer_reserve(answer, 2);
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering if (r < 0)
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering return r;
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering if (IN_SET(key->type, DNS_TYPE_A, DNS_TYPE_ANY)) {
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering _cleanup_(dns_resource_record_unrefp) DnsResourceRecord *rr = NULL;
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering rr = dns_resource_record_new_full(DNS_CLASS_IN, DNS_TYPE_A, DNS_RESOURCE_KEY_NAME(key));
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering if (!rr)
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering return -ENOMEM;
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering rr->a.in_addr.s_addr = htobe32(INADDR_LOOPBACK);
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering r = dns_answer_add(*answer, rr, SYNTHESIZE_IFINDEX(q->ifindex));
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering if (r < 0)
da927ba997d68401563b927f92e6e40e021a8e5cMichal Schmidt return r;
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering }
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering if (IN_SET(key->type, DNS_TYPE_AAAA, DNS_TYPE_ANY)) {
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering _cleanup_(dns_resource_record_unrefp) DnsResourceRecord *rr = NULL;
da927ba997d68401563b927f92e6e40e021a8e5cMichal Schmidt
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering rr = dns_resource_record_new_full(DNS_CLASS_IN, DNS_TYPE_AAAA, DNS_RESOURCE_KEY_NAME(key));
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering if (!rr)
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering return -ENOMEM;
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering rr->aaaa.in6_addr = in6addr_loopback;
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering r = dns_answer_add(*answer, rr, SYNTHESIZE_IFINDEX(q->ifindex));
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering if (r < 0)
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering return r;
0014a4ad505d119c7ac4346d9d774c3f17f663a5Lennart Poettering }
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering return 0;
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering}
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poetteringstatic int answer_add_ptr(DnsAnswer **answer, const char *from, const char *to, int ifindex) {
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering _cleanup_(dns_resource_record_unrefp) DnsResourceRecord *rr = NULL;
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering rr = dns_resource_record_new_full(DNS_CLASS_IN, DNS_TYPE_PTR, from);
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering if (!rr)
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering return -ENOMEM;
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering rr->ptr.name = strdup(to);
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering if (!rr->ptr.name)
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering return -ENOMEM;
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering return dns_answer_add(*answer, rr, ifindex);
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering}
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering
78c6a153c47f8d597c827bdcaf8c4e42ac87f738Lennart Poetteringstatic int synthesize_localhost_ptr(DnsQuery *q, DnsResourceKey *key, DnsAnswer **answer) {
eb60f9cd4e93ff5016dc1b5486fd1b7e1565fd92Lennart Poettering int r;
78c6a153c47f8d597c827bdcaf8c4e42ac87f738Lennart Poettering
78c6a153c47f8d597c827bdcaf8c4e42ac87f738Lennart Poettering assert(q);
78c6a153c47f8d597c827bdcaf8c4e42ac87f738Lennart Poettering assert(key);
eb60f9cd4e93ff5016dc1b5486fd1b7e1565fd92Lennart Poettering assert(answer);
78c6a153c47f8d597c827bdcaf8c4e42ac87f738Lennart Poettering
78c6a153c47f8d597c827bdcaf8c4e42ac87f738Lennart Poettering r = dns_answer_reserve(answer, 1);
78c6a153c47f8d597c827bdcaf8c4e42ac87f738Lennart Poettering if (r < 0)
78c6a153c47f8d597c827bdcaf8c4e42ac87f738Lennart Poettering return r;
78c6a153c47f8d597c827bdcaf8c4e42ac87f738Lennart Poettering
eb60f9cd4e93ff5016dc1b5486fd1b7e1565fd92Lennart Poettering if (IN_SET(key->type, DNS_TYPE_PTR, DNS_TYPE_ANY)) {
eb60f9cd4e93ff5016dc1b5486fd1b7e1565fd92Lennart Poettering r = answer_add_ptr(answer, DNS_RESOURCE_KEY_NAME(key), "localhost", SYNTHESIZE_IFINDEX(q->ifindex));
eb60f9cd4e93ff5016dc1b5486fd1b7e1565fd92Lennart Poettering if (r < 0)
eb60f9cd4e93ff5016dc1b5486fd1b7e1565fd92Lennart Poettering return r;
eb60f9cd4e93ff5016dc1b5486fd1b7e1565fd92Lennart Poettering }
78c6a153c47f8d597c827bdcaf8c4e42ac87f738Lennart Poettering
78c6a153c47f8d597c827bdcaf8c4e42ac87f738Lennart Poettering return 0;
78c6a153c47f8d597c827bdcaf8c4e42ac87f738Lennart Poettering}
78c6a153c47f8d597c827bdcaf8c4e42ac87f738Lennart Poettering
78c6a153c47f8d597c827bdcaf8c4e42ac87f738Lennart Poetteringstatic int answer_add_addresses_rr(
78c6a153c47f8d597c827bdcaf8c4e42ac87f738Lennart Poettering DnsAnswer **answer,
78c6a153c47f8d597c827bdcaf8c4e42ac87f738Lennart Poettering const char *name,
78c6a153c47f8d597c827bdcaf8c4e42ac87f738Lennart Poettering struct local_address *addresses,
78c6a153c47f8d597c827bdcaf8c4e42ac87f738Lennart Poettering unsigned n_addresses) {
78c6a153c47f8d597c827bdcaf8c4e42ac87f738Lennart Poettering
78c6a153c47f8d597c827bdcaf8c4e42ac87f738Lennart Poettering unsigned j;
78c6a153c47f8d597c827bdcaf8c4e42ac87f738Lennart Poettering int r;
78c6a153c47f8d597c827bdcaf8c4e42ac87f738Lennart Poettering
78c6a153c47f8d597c827bdcaf8c4e42ac87f738Lennart Poettering assert(answer);
78c6a153c47f8d597c827bdcaf8c4e42ac87f738Lennart Poettering assert(name);
78c6a153c47f8d597c827bdcaf8c4e42ac87f738Lennart Poettering
eb60f9cd4e93ff5016dc1b5486fd1b7e1565fd92Lennart Poettering r = dns_answer_reserve(answer, n_addresses);
eb60f9cd4e93ff5016dc1b5486fd1b7e1565fd92Lennart Poettering if (r < 0)
eb60f9cd4e93ff5016dc1b5486fd1b7e1565fd92Lennart Poettering return r;
eb60f9cd4e93ff5016dc1b5486fd1b7e1565fd92Lennart Poettering
422baca0f230913158078fddf884e06c8c64a316Lennart Poettering for (j = 0; j < n_addresses; j++) {
78c6a153c47f8d597c827bdcaf8c4e42ac87f738Lennart Poettering _cleanup_(dns_resource_record_unrefp) DnsResourceRecord *rr = NULL;
78c6a153c47f8d597c827bdcaf8c4e42ac87f738Lennart Poettering
78c6a153c47f8d597c827bdcaf8c4e42ac87f738Lennart Poettering r = dns_resource_record_new_address(&rr, addresses[j].family, &addresses[j].address, name);
78c6a153c47f8d597c827bdcaf8c4e42ac87f738Lennart Poettering if (r < 0)
78c6a153c47f8d597c827bdcaf8c4e42ac87f738Lennart Poettering return r;
78c6a153c47f8d597c827bdcaf8c4e42ac87f738Lennart Poettering
eb60f9cd4e93ff5016dc1b5486fd1b7e1565fd92Lennart Poettering r = dns_answer_add(*answer, rr, addresses[j].ifindex);
eb60f9cd4e93ff5016dc1b5486fd1b7e1565fd92Lennart Poettering if (r < 0)
78c6a153c47f8d597c827bdcaf8c4e42ac87f738Lennart Poettering return r;
78c6a153c47f8d597c827bdcaf8c4e42ac87f738Lennart Poettering }
78c6a153c47f8d597c827bdcaf8c4e42ac87f738Lennart Poettering
78c6a153c47f8d597c827bdcaf8c4e42ac87f738Lennart Poettering return 0;
78c6a153c47f8d597c827bdcaf8c4e42ac87f738Lennart Poettering}
eb60f9cd4e93ff5016dc1b5486fd1b7e1565fd92Lennart Poettering
eb60f9cd4e93ff5016dc1b5486fd1b7e1565fd92Lennart Poetteringstatic int answer_add_addresses_ptr(
eb60f9cd4e93ff5016dc1b5486fd1b7e1565fd92Lennart Poettering DnsAnswer **answer,
eb60f9cd4e93ff5016dc1b5486fd1b7e1565fd92Lennart Poettering const char *name,
eb60f9cd4e93ff5016dc1b5486fd1b7e1565fd92Lennart Poettering struct local_address *addresses,
eb60f9cd4e93ff5016dc1b5486fd1b7e1565fd92Lennart Poettering unsigned n_addresses,
78c6a153c47f8d597c827bdcaf8c4e42ac87f738Lennart Poettering int af, const union in_addr_union *match) {
eb60f9cd4e93ff5016dc1b5486fd1b7e1565fd92Lennart Poettering
eb60f9cd4e93ff5016dc1b5486fd1b7e1565fd92Lennart Poettering unsigned j;
eb60f9cd4e93ff5016dc1b5486fd1b7e1565fd92Lennart Poettering int r;
eb60f9cd4e93ff5016dc1b5486fd1b7e1565fd92Lennart Poettering
eb60f9cd4e93ff5016dc1b5486fd1b7e1565fd92Lennart Poettering assert(answer);
78c6a153c47f8d597c827bdcaf8c4e42ac87f738Lennart Poettering assert(name);
eb60f9cd4e93ff5016dc1b5486fd1b7e1565fd92Lennart Poettering
eb60f9cd4e93ff5016dc1b5486fd1b7e1565fd92Lennart Poettering for (j = 0; j < n_addresses; j++) {
eb60f9cd4e93ff5016dc1b5486fd1b7e1565fd92Lennart Poettering _cleanup_(dns_resource_record_unrefp) DnsResourceRecord *rr = NULL;
78c6a153c47f8d597c827bdcaf8c4e42ac87f738Lennart Poettering
eb60f9cd4e93ff5016dc1b5486fd1b7e1565fd92Lennart Poettering if (af != AF_UNSPEC) {
eb60f9cd4e93ff5016dc1b5486fd1b7e1565fd92Lennart Poettering
78c6a153c47f8d597c827bdcaf8c4e42ac87f738Lennart Poettering if (addresses[j].family != af)
78c6a153c47f8d597c827bdcaf8c4e42ac87f738Lennart Poettering continue;
78c6a153c47f8d597c827bdcaf8c4e42ac87f738Lennart Poettering
78c6a153c47f8d597c827bdcaf8c4e42ac87f738Lennart Poettering if (match && !in_addr_equal(af, match, &addresses[j].address))
78c6a153c47f8d597c827bdcaf8c4e42ac87f738Lennart Poettering continue;
78c6a153c47f8d597c827bdcaf8c4e42ac87f738Lennart Poettering }
78c6a153c47f8d597c827bdcaf8c4e42ac87f738Lennart Poettering
78c6a153c47f8d597c827bdcaf8c4e42ac87f738Lennart Poettering r = dns_answer_reserve(answer, 1);
78c6a153c47f8d597c827bdcaf8c4e42ac87f738Lennart Poettering if (r < 0)
eb60f9cd4e93ff5016dc1b5486fd1b7e1565fd92Lennart Poettering return r;
eb60f9cd4e93ff5016dc1b5486fd1b7e1565fd92Lennart Poettering
eb60f9cd4e93ff5016dc1b5486fd1b7e1565fd92Lennart Poettering r = dns_resource_record_new_reverse(&rr, addresses[j].family, &addresses[j].address, name);
eb60f9cd4e93ff5016dc1b5486fd1b7e1565fd92Lennart Poettering if (r < 0)
eb60f9cd4e93ff5016dc1b5486fd1b7e1565fd92Lennart Poettering return r;
eb60f9cd4e93ff5016dc1b5486fd1b7e1565fd92Lennart Poettering
eb60f9cd4e93ff5016dc1b5486fd1b7e1565fd92Lennart Poettering r = dns_answer_add(*answer, rr, addresses[j].ifindex);
eb60f9cd4e93ff5016dc1b5486fd1b7e1565fd92Lennart Poettering if (r < 0)
eb60f9cd4e93ff5016dc1b5486fd1b7e1565fd92Lennart Poettering return r;
eb60f9cd4e93ff5016dc1b5486fd1b7e1565fd92Lennart Poettering }
eb60f9cd4e93ff5016dc1b5486fd1b7e1565fd92Lennart Poettering
eb60f9cd4e93ff5016dc1b5486fd1b7e1565fd92Lennart Poettering return 0;
eb60f9cd4e93ff5016dc1b5486fd1b7e1565fd92Lennart Poettering}
56f64d95763a799ba4475daf44d8e9f72a1bd474Michal Schmidt
eb60f9cd4e93ff5016dc1b5486fd1b7e1565fd92Lennart Poetteringstatic int synthesize_system_hostname_rr(DnsQuery *q, DnsResourceKey *key, DnsAnswer **answer) {
eb60f9cd4e93ff5016dc1b5486fd1b7e1565fd92Lennart Poettering _cleanup_free_ struct local_address *addresses = NULL;
eb60f9cd4e93ff5016dc1b5486fd1b7e1565fd92Lennart Poettering int n = 0, af;
eb60f9cd4e93ff5016dc1b5486fd1b7e1565fd92Lennart Poettering
eb60f9cd4e93ff5016dc1b5486fd1b7e1565fd92Lennart Poettering assert(q);
eb60f9cd4e93ff5016dc1b5486fd1b7e1565fd92Lennart Poettering assert(key);
eb60f9cd4e93ff5016dc1b5486fd1b7e1565fd92Lennart Poettering assert(answer);
eb60f9cd4e93ff5016dc1b5486fd1b7e1565fd92Lennart Poettering
8d3d7072e609ef0e0fb37e1d19a29307d58146c3Michal Schmidt af = dns_type_to_af(key->type);
8d3d7072e609ef0e0fb37e1d19a29307d58146c3Michal Schmidt if (af >= 0) {
eb60f9cd4e93ff5016dc1b5486fd1b7e1565fd92Lennart Poettering n = local_addresses(q->manager->rtnl, q->ifindex, af, &addresses);
eb60f9cd4e93ff5016dc1b5486fd1b7e1565fd92Lennart Poettering if (n < 0)
78c6a153c47f8d597c827bdcaf8c4e42ac87f738Lennart Poettering return n;
eb60f9cd4e93ff5016dc1b5486fd1b7e1565fd92Lennart Poettering
eb60f9cd4e93ff5016dc1b5486fd1b7e1565fd92Lennart Poettering if (n == 0) {
78c6a153c47f8d597c827bdcaf8c4e42ac87f738Lennart Poettering struct local_address buffer[2];
78c6a153c47f8d597c827bdcaf8c4e42ac87f738Lennart Poettering
78c6a153c47f8d597c827bdcaf8c4e42ac87f738Lennart Poettering /* If we have no local addresses then use ::1
78c6a153c47f8d597c827bdcaf8c4e42ac87f738Lennart Poettering * and 127.0.0.2 as local ones. */
78c6a153c47f8d597c827bdcaf8c4e42ac87f738Lennart Poettering
78c6a153c47f8d597c827bdcaf8c4e42ac87f738Lennart Poettering if (af == AF_INET || af == AF_UNSPEC)
eb60f9cd4e93ff5016dc1b5486fd1b7e1565fd92Lennart Poettering buffer[n++] = (struct local_address) {
eb60f9cd4e93ff5016dc1b5486fd1b7e1565fd92Lennart Poettering .family = AF_INET,
78c6a153c47f8d597c827bdcaf8c4e42ac87f738Lennart Poettering .ifindex = SYNTHESIZE_IFINDEX(q->ifindex),
eb60f9cd4e93ff5016dc1b5486fd1b7e1565fd92Lennart Poettering .address.in.s_addr = htobe32(0x7F000002),
eb60f9cd4e93ff5016dc1b5486fd1b7e1565fd92Lennart Poettering };
eb60f9cd4e93ff5016dc1b5486fd1b7e1565fd92Lennart Poettering
eb60f9cd4e93ff5016dc1b5486fd1b7e1565fd92Lennart Poettering if (af == AF_INET6 || af == AF_UNSPEC)
4d506d6bb757af3b99e0876234c465e6898c5ea4Lennart Poettering buffer[n++] = (struct local_address) {
4d506d6bb757af3b99e0876234c465e6898c5ea4Lennart Poettering .family = AF_INET6,
4d506d6bb757af3b99e0876234c465e6898c5ea4Lennart Poettering .ifindex = SYNTHESIZE_IFINDEX(q->ifindex),
4d506d6bb757af3b99e0876234c465e6898c5ea4Lennart Poettering .address.in6 = in6addr_loopback,
4d506d6bb757af3b99e0876234c465e6898c5ea4Lennart Poettering };
4d506d6bb757af3b99e0876234c465e6898c5ea4Lennart Poettering
4d506d6bb757af3b99e0876234c465e6898c5ea4Lennart Poettering return answer_add_addresses_rr(answer, DNS_RESOURCE_KEY_NAME(key), buffer, n);
4d506d6bb757af3b99e0876234c465e6898c5ea4Lennart Poettering }
4d506d6bb757af3b99e0876234c465e6898c5ea4Lennart Poettering }
4d506d6bb757af3b99e0876234c465e6898c5ea4Lennart Poettering
4d506d6bb757af3b99e0876234c465e6898c5ea4Lennart Poettering return answer_add_addresses_rr(answer, DNS_RESOURCE_KEY_NAME(key), addresses, n);
4d506d6bb757af3b99e0876234c465e6898c5ea4Lennart Poettering}
4d506d6bb757af3b99e0876234c465e6898c5ea4Lennart Poettering
4d506d6bb757af3b99e0876234c465e6898c5ea4Lennart Poetteringstatic int synthesize_system_hostname_ptr(DnsQuery *q, int af, const union in_addr_union *address, DnsAnswer **answer) {
4d506d6bb757af3b99e0876234c465e6898c5ea4Lennart Poettering _cleanup_free_ struct local_address *addresses = NULL;
4d506d6bb757af3b99e0876234c465e6898c5ea4Lennart Poettering int n, r;
4d506d6bb757af3b99e0876234c465e6898c5ea4Lennart Poettering
4d506d6bb757af3b99e0876234c465e6898c5ea4Lennart Poettering assert(q);
4d506d6bb757af3b99e0876234c465e6898c5ea4Lennart Poettering assert(address);
4d506d6bb757af3b99e0876234c465e6898c5ea4Lennart Poettering assert(answer);
4d506d6bb757af3b99e0876234c465e6898c5ea4Lennart Poettering
4d506d6bb757af3b99e0876234c465e6898c5ea4Lennart Poettering if (af == AF_INET && address->in.s_addr == htobe32(0x7F000002)) {
4d506d6bb757af3b99e0876234c465e6898c5ea4Lennart Poettering
4d506d6bb757af3b99e0876234c465e6898c5ea4Lennart Poettering /* Always map the IPv4 address 127.0.0.2 to the local
4d506d6bb757af3b99e0876234c465e6898c5ea4Lennart Poettering * hostname, in addition to "localhost": */
091a364c802e34a58f3260c9cb5db9b75c62215cTom Gundersen
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering r = dns_answer_reserve(answer, 3);
091a364c802e34a58f3260c9cb5db9b75c62215cTom Gundersen if (r < 0)
091a364c802e34a58f3260c9cb5db9b75c62215cTom Gundersen return r;
c92e531c82a9815ec349aa1bf31236b86b2d5311Lennart Poettering
c92e531c82a9815ec349aa1bf31236b86b2d5311Lennart Poettering r = answer_add_ptr(answer, "2.0.0.127.in-addr.arpa", q->manager->llmnr_hostname, SYNTHESIZE_IFINDEX(q->ifindex));
091a364c802e34a58f3260c9cb5db9b75c62215cTom Gundersen if (r < 0)
091a364c802e34a58f3260c9cb5db9b75c62215cTom Gundersen return r;
091a364c802e34a58f3260c9cb5db9b75c62215cTom Gundersen
091a364c802e34a58f3260c9cb5db9b75c62215cTom Gundersen r = answer_add_ptr(answer, "2.0.0.127.in-addr.arpa", q->manager->mdns_hostname, SYNTHESIZE_IFINDEX(q->ifindex));
1716f6dcf54d4c181c2e2558e3d5414f54c8d9caLennart Poettering if (r < 0)
623a4c97b9175f95c4b1c6fc34e36c56f1e4ddbfLennart Poettering return r;
bc7702b098b63031767174206f5df14a8ccb45cfDaniel Mack
eb60f9cd4e93ff5016dc1b5486fd1b7e1565fd92Lennart Poettering r = answer_add_ptr(answer, "2.0.0.127.in-addr.arpa", "localhost", SYNTHESIZE_IFINDEX(q->ifindex));
1716f6dcf54d4c181c2e2558e3d5414f54c8d9caLennart Poettering if (r < 0)
4e945a6f7971fd7d1f6b2c62ee3afdaff3c95ce4Lennart Poettering return r;
5cb36f41f01cf4b1f4395abfffd1b33116591e58Lennart Poettering
00fa60ae3b2823036cb3e7734f16bce30cb7441dLennart Poettering return 0;
091a364c802e34a58f3260c9cb5db9b75c62215cTom Gundersen }
0d2cd47617b423f37d7425be7a56ae2fca8ff9f6Lennart Poettering
0d2cd47617b423f37d7425be7a56ae2fca8ff9f6Lennart Poettering n = local_addresses(q->manager->rtnl, q->ifindex, af, &addresses);
0d2cd47617b423f37d7425be7a56ae2fca8ff9f6Lennart Poettering if (n < 0)
0d2cd47617b423f37d7425be7a56ae2fca8ff9f6Lennart Poettering return n;
091a364c802e34a58f3260c9cb5db9b75c62215cTom Gundersen
091a364c802e34a58f3260c9cb5db9b75c62215cTom Gundersen r = answer_add_addresses_ptr(answer, q->manager->llmnr_hostname, addresses, n, af, address);
091a364c802e34a58f3260c9cb5db9b75c62215cTom Gundersen if (r < 0)
091a364c802e34a58f3260c9cb5db9b75c62215cTom Gundersen return r;
091a364c802e34a58f3260c9cb5db9b75c62215cTom Gundersen
091a364c802e34a58f3260c9cb5db9b75c62215cTom Gundersen return answer_add_addresses_ptr(answer, q->manager->mdns_hostname, addresses, n, af, address);
091a364c802e34a58f3260c9cb5db9b75c62215cTom Gundersen}
091a364c802e34a58f3260c9cb5db9b75c62215cTom Gundersen
091a364c802e34a58f3260c9cb5db9b75c62215cTom Gundersenstatic int synthesize_gateway_rr(DnsQuery *q, DnsResourceKey *key, DnsAnswer **answer) {
eb60f9cd4e93ff5016dc1b5486fd1b7e1565fd92Lennart Poettering _cleanup_free_ struct local_address *addresses = NULL;
eb60f9cd4e93ff5016dc1b5486fd1b7e1565fd92Lennart Poettering int n = 0, af;
eb60f9cd4e93ff5016dc1b5486fd1b7e1565fd92Lennart Poettering
eb60f9cd4e93ff5016dc1b5486fd1b7e1565fd92Lennart Poettering assert(q);
1716f6dcf54d4c181c2e2558e3d5414f54c8d9caLennart Poettering assert(key);
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering assert(answer);
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering af = dns_type_to_af(key->type);
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering if (af >= 0) {
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering n = local_gateways(q->manager->rtnl, q->ifindex, af, &addresses);
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering if (n < 0)
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering return n;
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering }
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering return answer_add_addresses_rr(answer, DNS_RESOURCE_KEY_NAME(key), addresses, n);
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering}
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poetteringstatic int synthesize_gateway_ptr(DnsQuery *q, int af, const union in_addr_union *address, DnsAnswer **answer) {
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering _cleanup_free_ struct local_address *addresses = NULL;
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering int n;
4d506d6bb757af3b99e0876234c465e6898c5ea4Lennart Poettering
4d506d6bb757af3b99e0876234c465e6898c5ea4Lennart Poettering assert(q);
091a364c802e34a58f3260c9cb5db9b75c62215cTom Gundersen assert(address);
091a364c802e34a58f3260c9cb5db9b75c62215cTom Gundersen assert(answer);
091a364c802e34a58f3260c9cb5db9b75c62215cTom Gundersen
091a364c802e34a58f3260c9cb5db9b75c62215cTom Gundersen n = local_gateways(q->manager->rtnl, q->ifindex, af, &addresses);
091a364c802e34a58f3260c9cb5db9b75c62215cTom Gundersen if (n < 0)
091a364c802e34a58f3260c9cb5db9b75c62215cTom Gundersen return n;
edc501d4674dadc304d45a7e1c5b69e207eb8cd4Lennart Poettering
edc501d4674dadc304d45a7e1c5b69e207eb8cd4Lennart Poettering return answer_add_addresses_ptr(answer, "gateway", addresses, n, af, address);
edc501d4674dadc304d45a7e1c5b69e207eb8cd4Lennart Poettering}
edc501d4674dadc304d45a7e1c5b69e207eb8cd4Lennart Poettering
edc501d4674dadc304d45a7e1c5b69e207eb8cd4Lennart Poetteringstatic int dns_query_synthesize_reply(DnsQuery *q, DnsTransactionState *state) {
edc501d4674dadc304d45a7e1c5b69e207eb8cd4Lennart Poettering _cleanup_(dns_answer_unrefp) DnsAnswer *answer = NULL;
edc501d4674dadc304d45a7e1c5b69e207eb8cd4Lennart Poettering unsigned i;
edc501d4674dadc304d45a7e1c5b69e207eb8cd4Lennart Poettering int r;
edc501d4674dadc304d45a7e1c5b69e207eb8cd4Lennart Poettering
bc7702b098b63031767174206f5df14a8ccb45cfDaniel Mack assert(q);
bc7702b098b63031767174206f5df14a8ccb45cfDaniel Mack assert(state);
bc7702b098b63031767174206f5df14a8ccb45cfDaniel Mack
bc7702b098b63031767174206f5df14a8ccb45cfDaniel Mack /* Tries to synthesize localhost RR replies where appropriate */
edc501d4674dadc304d45a7e1c5b69e207eb8cd4Lennart Poettering
edc501d4674dadc304d45a7e1c5b69e207eb8cd4Lennart Poettering if (!IN_SET(*state,
edc501d4674dadc304d45a7e1c5b69e207eb8cd4Lennart Poettering DNS_TRANSACTION_FAILURE,
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering DNS_TRANSACTION_NO_SERVERS,
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering DNS_TRANSACTION_TIMEOUT,
091a364c802e34a58f3260c9cb5db9b75c62215cTom Gundersen DNS_TRANSACTION_ATTEMPTS_MAX_REACHED))
091a364c802e34a58f3260c9cb5db9b75c62215cTom Gundersen return 0;
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering for (i = 0; i < q->question->n_keys; i++) {
4b95f1798f22c1bb75295f448188560cb6ec9eceLennart Poettering union in_addr_union address;
4b95f1798f22c1bb75295f448188560cb6ec9eceLennart Poettering const char *name;
a51c10485af349eb15faa4d1a63b9818bcf3e589Lennart Poettering int af;
a51c10485af349eb15faa4d1a63b9818bcf3e589Lennart Poettering
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering if (q->question->keys[i]->class != DNS_CLASS_IN &&
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering q->question->keys[i]->class != DNS_CLASS_ANY)
f0e1546763304aedc90e91d70dab9eeb7c966cf8Lennart Poettering continue;
f0e1546763304aedc90e91d70dab9eeb7c966cf8Lennart Poettering
f0e1546763304aedc90e91d70dab9eeb7c966cf8Lennart Poettering name = DNS_RESOURCE_KEY_NAME(q->question->keys[i]);
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering
cab5b05903096e1c9cf5575ccc73f89d15c8db69Lennart Poettering if (is_localhost(name)) {
cab5b05903096e1c9cf5575ccc73f89d15c8db69Lennart Poettering
f0e1546763304aedc90e91d70dab9eeb7c966cf8Lennart Poettering r = synthesize_localhost_rr(q, q->question->keys[i], &answer);
f0e1546763304aedc90e91d70dab9eeb7c966cf8Lennart Poettering if (r < 0)
f0e1546763304aedc90e91d70dab9eeb7c966cf8Lennart Poettering return log_error_errno(r, "Failed to synthesize localhost RRs: %m");
096b6773886bd7a0c8c97aa684b0b67dfae58355Lennart Poettering
096b6773886bd7a0c8c97aa684b0b67dfae58355Lennart Poettering } else if (manager_is_own_hostname(q->manager, name)) {
091a364c802e34a58f3260c9cb5db9b75c62215cTom Gundersen
a564ca2fd113b2876e677beab60b38d50591e246Lennart Poettering r = synthesize_system_hostname_rr(q, q->question->keys[i], &answer);
a564ca2fd113b2876e677beab60b38d50591e246Lennart Poettering if (r < 0)
a564ca2fd113b2876e677beab60b38d50591e246Lennart Poettering return log_error_errno(r, "Failed to synthesize system hostname RRs: %m");
edc501d4674dadc304d45a7e1c5b69e207eb8cd4Lennart Poettering
bc7702b098b63031767174206f5df14a8ccb45cfDaniel Mack } else if (is_gateway_hostname(name)) {
623a4c97b9175f95c4b1c6fc34e36c56f1e4ddbfLennart Poettering
902bb5d8abb2a7d258741828d212ca549ab16950Lennart Poettering r = synthesize_gateway_rr(q, q->question->keys[i], &answer);
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering if (r < 0)
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering return log_error_errno(r, "Failed to synthesize gateway RRs: %m");
091a364c802e34a58f3260c9cb5db9b75c62215cTom Gundersen
4d506d6bb757af3b99e0876234c465e6898c5ea4Lennart Poettering } else if ((dns_name_endswith(name, "127.in-addr.arpa") > 0 && dns_name_equal(name, "2.0.0.127.in-addr.arpa") == 0) ||
4d506d6bb757af3b99e0876234c465e6898c5ea4Lennart Poettering dns_name_equal(name, "1.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.ip6.arpa") > 0) {
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering
623a4c97b9175f95c4b1c6fc34e36c56f1e4ddbfLennart Poettering r = synthesize_localhost_ptr(q, q->question->keys[i], &answer);
78c6a153c47f8d597c827bdcaf8c4e42ac87f738Lennart Poettering if (r < 0)
78c6a153c47f8d597c827bdcaf8c4e42ac87f738Lennart Poettering return log_error_errno(r, "Failed to synthesize localhost PTR RRs: %m");
eb60f9cd4e93ff5016dc1b5486fd1b7e1565fd92Lennart Poettering
eb60f9cd4e93ff5016dc1b5486fd1b7e1565fd92Lennart Poettering } else if (dns_name_address(name, &af, &address) > 0) {
d9fcf2ba1abe81ed3a7a151d6db09139b4dc7a09Lennart Poettering
78c6a153c47f8d597c827bdcaf8c4e42ac87f738Lennart Poettering r = synthesize_system_hostname_ptr(q, af, &address, &answer);
78c6a153c47f8d597c827bdcaf8c4e42ac87f738Lennart Poettering if (r < 0)
eb60f9cd4e93ff5016dc1b5486fd1b7e1565fd92Lennart Poettering return log_error_errno(r, "Failed to synthesize system hostname PTR RR: %m");
0d2cd47617b423f37d7425be7a56ae2fca8ff9f6Lennart Poettering
0d2cd47617b423f37d7425be7a56ae2fca8ff9f6Lennart Poettering r = synthesize_gateway_ptr(q, af, &address, &answer);
091a364c802e34a58f3260c9cb5db9b75c62215cTom Gundersen if (r < 0)
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering return log_error_errno(r, "Failed to synthesize gateway hostname PTR RR: %m");
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering }
091a364c802e34a58f3260c9cb5db9b75c62215cTom Gundersen }
091a364c802e34a58f3260c9cb5db9b75c62215cTom Gundersen
1716f6dcf54d4c181c2e2558e3d5414f54c8d9caLennart Poettering if (!answer)
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering return 0;
1716f6dcf54d4c181c2e2558e3d5414f54c8d9caLennart Poettering
1716f6dcf54d4c181c2e2558e3d5414f54c8d9caLennart Poettering dns_answer_unref(q->answer);
40a1eebde6be7ac3f1885147fc24e06ad1da260cDavid Herrmann q->answer = answer;
1716f6dcf54d4c181c2e2558e3d5414f54c8d9caLennart Poettering answer = NULL;
623a4c97b9175f95c4b1c6fc34e36c56f1e4ddbfLennart Poettering
1716f6dcf54d4c181c2e2558e3d5414f54c8d9caLennart Poettering q->answer_family = SYNTHESIZE_FAMILY(q->flags);
1716f6dcf54d4c181c2e2558e3d5414f54c8d9caLennart Poettering q->answer_protocol = SYNTHESIZE_PROTOCOL(q->flags);
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering q->answer_rcode = DNS_RCODE_SUCCESS;
1716f6dcf54d4c181c2e2558e3d5414f54c8d9caLennart Poettering
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering *state = DNS_TRANSACTION_SUCCESS;
1716f6dcf54d4c181c2e2558e3d5414f54c8d9caLennart Poettering
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering return 1;
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering}
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering
1716f6dcf54d4c181c2e2558e3d5414f54c8d9caLennart Poetteringint dns_query_go(DnsQuery *q) {
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering DnsScopeMatch found = DNS_SCOPE_NO;
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering DnsScope *s, *first = NULL;
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering DnsTransaction *t;
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering const char *name;
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering Iterator i;
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering int r;
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering assert(q);
1716f6dcf54d4c181c2e2558e3d5414f54c8d9caLennart Poettering
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering if (q->state != DNS_TRANSACTION_NULL)
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering return 0;
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering assert(q->question);
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering assert(q->question->n_keys > 0);
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering
1716f6dcf54d4c181c2e2558e3d5414f54c8d9caLennart Poettering name = DNS_RESOURCE_KEY_NAME(q->question->keys[0]);
1716f6dcf54d4c181c2e2558e3d5414f54c8d9caLennart Poettering
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering LIST_FOREACH(scopes, s, q->manager->dns_scopes) {
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering DnsScopeMatch match;
1716f6dcf54d4c181c2e2558e3d5414f54c8d9caLennart Poettering
1716f6dcf54d4c181c2e2558e3d5414f54c8d9caLennart Poettering match = dns_scope_good_domain(s, q->ifindex, q->flags, name);
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering if (match < 0)
a38d99451f2bf8026ec51aee91662292e823c6a8Lennart Poettering return match;
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering
ad867662936a4c7ab2c7116d804c272338801231Lennart Poettering if (match == DNS_SCOPE_NO)
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering continue;
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering found = match;
091a364c802e34a58f3260c9cb5db9b75c62215cTom Gundersen
091a364c802e34a58f3260c9cb5db9b75c62215cTom Gundersen if (match == DNS_SCOPE_YES) {
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering first = s;
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering break;
091a364c802e34a58f3260c9cb5db9b75c62215cTom Gundersen } else {
1716f6dcf54d4c181c2e2558e3d5414f54c8d9caLennart Poettering assert(match == DNS_SCOPE_MAYBE);
1716f6dcf54d4c181c2e2558e3d5414f54c8d9caLennart Poettering
1716f6dcf54d4c181c2e2558e3d5414f54c8d9caLennart Poettering if (!first)
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering first = s;
091a364c802e34a58f3260c9cb5db9b75c62215cTom Gundersen }
1716f6dcf54d4c181c2e2558e3d5414f54c8d9caLennart Poettering }
623a4c97b9175f95c4b1c6fc34e36c56f1e4ddbfLennart Poettering
623a4c97b9175f95c4b1c6fc34e36c56f1e4ddbfLennart Poettering if (found == DNS_SCOPE_NO) {
1716f6dcf54d4c181c2e2558e3d5414f54c8d9caLennart Poettering DnsTransactionState state = DNS_TRANSACTION_NO_SERVERS;
623a4c97b9175f95c4b1c6fc34e36c56f1e4ddbfLennart Poettering
623a4c97b9175f95c4b1c6fc34e36c56f1e4ddbfLennart Poettering dns_query_synthesize_reply(q, &state);
1716f6dcf54d4c181c2e2558e3d5414f54c8d9caLennart Poettering dns_query_complete(q, state);
623a4c97b9175f95c4b1c6fc34e36c56f1e4ddbfLennart Poettering return 1;
623a4c97b9175f95c4b1c6fc34e36c56f1e4ddbfLennart Poettering }
623a4c97b9175f95c4b1c6fc34e36c56f1e4ddbfLennart Poettering
1716f6dcf54d4c181c2e2558e3d5414f54c8d9caLennart Poettering r = dns_query_add_transaction_split(q, first);
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering if (r < 0)
2a1288ff89322a2f49c79f6d1832c8164c14a05cLennart Poettering goto fail;
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering
1716f6dcf54d4c181c2e2558e3d5414f54c8d9caLennart Poettering LIST_FOREACH(scopes, s, first->scopes_next) {
1716f6dcf54d4c181c2e2558e3d5414f54c8d9caLennart Poettering DnsScopeMatch match;
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering
1716f6dcf54d4c181c2e2558e3d5414f54c8d9caLennart Poettering match = dns_scope_good_domain(s, q->ifindex, q->flags, name);
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering if (match < 0)
1716f6dcf54d4c181c2e2558e3d5414f54c8d9caLennart Poettering goto fail;
1716f6dcf54d4c181c2e2558e3d5414f54c8d9caLennart Poettering
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering if (match != found)
623a4c97b9175f95c4b1c6fc34e36c56f1e4ddbfLennart Poettering continue;
623a4c97b9175f95c4b1c6fc34e36c56f1e4ddbfLennart Poettering
623a4c97b9175f95c4b1c6fc34e36c56f1e4ddbfLennart Poettering r = dns_query_add_transaction_split(q, s);
1716f6dcf54d4c181c2e2558e3d5414f54c8d9caLennart Poettering if (r < 0)
1716f6dcf54d4c181c2e2558e3d5414f54c8d9caLennart Poettering goto fail;
1716f6dcf54d4c181c2e2558e3d5414f54c8d9caLennart Poettering }
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering
1716f6dcf54d4c181c2e2558e3d5414f54c8d9caLennart Poettering q->answer = dns_answer_unref(q->answer);
1716f6dcf54d4c181c2e2558e3d5414f54c8d9caLennart Poettering q->answer_rcode = 0;
1716f6dcf54d4c181c2e2558e3d5414f54c8d9caLennart Poettering q->answer_family = AF_UNSPEC;
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering q->answer_protocol = _DNS_PROTOCOL_INVALID;
1716f6dcf54d4c181c2e2558e3d5414f54c8d9caLennart Poettering
1716f6dcf54d4c181c2e2558e3d5414f54c8d9caLennart Poettering r = sd_event_add_time(
1716f6dcf54d4c181c2e2558e3d5414f54c8d9caLennart Poettering q->manager->event,
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering &q->timeout_event_source,
1716f6dcf54d4c181c2e2558e3d5414f54c8d9caLennart Poettering clock_boottime_or_monotonic(),
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering now(clock_boottime_or_monotonic()) + QUERY_TIMEOUT_USEC, 0,
1716f6dcf54d4c181c2e2558e3d5414f54c8d9caLennart Poettering on_query_timeout, q);
1716f6dcf54d4c181c2e2558e3d5414f54c8d9caLennart Poettering if (r < 0)
091a364c802e34a58f3260c9cb5db9b75c62215cTom Gundersen goto fail;
623a4c97b9175f95c4b1c6fc34e36c56f1e4ddbfLennart Poettering
623a4c97b9175f95c4b1c6fc34e36c56f1e4ddbfLennart Poettering q->state = DNS_TRANSACTION_PENDING;
623a4c97b9175f95c4b1c6fc34e36c56f1e4ddbfLennart Poettering q->block_ready++;
1716f6dcf54d4c181c2e2558e3d5414f54c8d9caLennart Poettering
1716f6dcf54d4c181c2e2558e3d5414f54c8d9caLennart Poettering /* Start the transactions that are not started yet */
1716f6dcf54d4c181c2e2558e3d5414f54c8d9caLennart Poettering SET_FOREACH(t, q->transactions, i) {
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering if (t->state != DNS_TRANSACTION_NULL)
623a4c97b9175f95c4b1c6fc34e36c56f1e4ddbfLennart Poettering continue;
1716f6dcf54d4c181c2e2558e3d5414f54c8d9caLennart Poettering
1716f6dcf54d4c181c2e2558e3d5414f54c8d9caLennart Poettering r = dns_transaction_go(t);
1716f6dcf54d4c181c2e2558e3d5414f54c8d9caLennart Poettering if (r < 0)
1716f6dcf54d4c181c2e2558e3d5414f54c8d9caLennart Poettering goto fail;
1716f6dcf54d4c181c2e2558e3d5414f54c8d9caLennart Poettering }
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering
623a4c97b9175f95c4b1c6fc34e36c56f1e4ddbfLennart Poettering q->block_ready--;
623a4c97b9175f95c4b1c6fc34e36c56f1e4ddbfLennart Poettering dns_query_ready(q);
623a4c97b9175f95c4b1c6fc34e36c56f1e4ddbfLennart Poettering
623a4c97b9175f95c4b1c6fc34e36c56f1e4ddbfLennart Poettering return 1;
a5f035960006556beab51c42e6948985635e261aLennart Poettering
623a4c97b9175f95c4b1c6fc34e36c56f1e4ddbfLennart Poetteringfail:
623a4c97b9175f95c4b1c6fc34e36c56f1e4ddbfLennart Poettering dns_query_stop(q);
86ad4cd709ced8daf2b75ab564dece1ce82ffed9Tom Gundersen return r;
86ad4cd709ced8daf2b75ab564dece1ce82ffed9Tom Gundersen}
86ad4cd709ced8daf2b75ab564dece1ce82ffed9Tom Gundersen
86ad4cd709ced8daf2b75ab564dece1ce82ffed9Tom Gundersenvoid dns_query_ready(DnsQuery *q) {
86ad4cd709ced8daf2b75ab564dece1ce82ffed9Tom Gundersen DnsTransaction *t;
86ad4cd709ced8daf2b75ab564dece1ce82ffed9Tom Gundersen DnsTransactionState state = DNS_TRANSACTION_NO_SERVERS;
623a4c97b9175f95c4b1c6fc34e36c56f1e4ddbfLennart Poettering _cleanup_(dns_answer_unrefp) DnsAnswer *answer = NULL;
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering int rcode = 0;
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering DnsScope *scope = NULL;
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering bool pending = false;
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering Iterator i;
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering assert(q);
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering assert(IN_SET(q->state, DNS_TRANSACTION_NULL, DNS_TRANSACTION_PENDING));
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering /* Note that this call might invalidate the query. Callers
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering * should hence not attempt to access the query or transaction
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering * after calling this function, unless the block_ready
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering * counter was explicitly bumped before doing so. */
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering if (q->block_ready > 0)
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering return;
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering SET_FOREACH(t, q->transactions, i) {
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering /* If we found a successful answer, ignore all answers from other scopes */
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering if (state == DNS_TRANSACTION_SUCCESS && t->scope != scope)
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering continue;
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering /* One of the transactions is still going on, let's maybe wait for it */
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering if (IN_SET(t->state, DNS_TRANSACTION_PENDING, DNS_TRANSACTION_NULL)) {
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering pending = true;
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering continue;
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering }
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering /* One of the transactions is successful, let's use
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering * it, and copy its data out */
72290734be81e83e6ef9520c07692f68095eb5b2Tom Gundersen if (t->state == DNS_TRANSACTION_SUCCESS) {
72290734be81e83e6ef9520c07692f68095eb5b2Tom Gundersen DnsAnswer *a;
72290734be81e83e6ef9520c07692f68095eb5b2Tom Gundersen
72290734be81e83e6ef9520c07692f68095eb5b2Tom Gundersen if (t->received) {
72290734be81e83e6ef9520c07692f68095eb5b2Tom Gundersen rcode = DNS_PACKET_RCODE(t->received);
72290734be81e83e6ef9520c07692f68095eb5b2Tom Gundersen a = t->received->answer;
72290734be81e83e6ef9520c07692f68095eb5b2Tom Gundersen } else {
72290734be81e83e6ef9520c07692f68095eb5b2Tom Gundersen rcode = t->cached_rcode;
72290734be81e83e6ef9520c07692f68095eb5b2Tom Gundersen a = t->cached;
72290734be81e83e6ef9520c07692f68095eb5b2Tom Gundersen }
72290734be81e83e6ef9520c07692f68095eb5b2Tom Gundersen
72290734be81e83e6ef9520c07692f68095eb5b2Tom Gundersen if (state == DNS_TRANSACTION_SUCCESS) {
72290734be81e83e6ef9520c07692f68095eb5b2Tom Gundersen DnsAnswer *merged;
72290734be81e83e6ef9520c07692f68095eb5b2Tom Gundersen
72290734be81e83e6ef9520c07692f68095eb5b2Tom Gundersen merged = dns_answer_merge(answer, a);
72290734be81e83e6ef9520c07692f68095eb5b2Tom Gundersen if (!merged) {
72290734be81e83e6ef9520c07692f68095eb5b2Tom Gundersen dns_query_complete(q, DNS_TRANSACTION_RESOURCES);
72290734be81e83e6ef9520c07692f68095eb5b2Tom Gundersen return;
72290734be81e83e6ef9520c07692f68095eb5b2Tom Gundersen }
72290734be81e83e6ef9520c07692f68095eb5b2Tom Gundersen
72290734be81e83e6ef9520c07692f68095eb5b2Tom Gundersen dns_answer_unref(answer);
72290734be81e83e6ef9520c07692f68095eb5b2Tom Gundersen answer = merged;
72290734be81e83e6ef9520c07692f68095eb5b2Tom Gundersen } else {
72290734be81e83e6ef9520c07692f68095eb5b2Tom Gundersen dns_answer_unref(answer);
72290734be81e83e6ef9520c07692f68095eb5b2Tom Gundersen answer = dns_answer_ref(a);
72290734be81e83e6ef9520c07692f68095eb5b2Tom Gundersen }
72290734be81e83e6ef9520c07692f68095eb5b2Tom Gundersen
deb3f3d335d64601bb2d8a7520d8303f99d8a071Lennart Poettering scope = t->scope;
72290734be81e83e6ef9520c07692f68095eb5b2Tom Gundersen state = DNS_TRANSACTION_SUCCESS;
72290734be81e83e6ef9520c07692f68095eb5b2Tom Gundersen continue;
72290734be81e83e6ef9520c07692f68095eb5b2Tom Gundersen }
72290734be81e83e6ef9520c07692f68095eb5b2Tom Gundersen
72290734be81e83e6ef9520c07692f68095eb5b2Tom Gundersen /* One of the transactions has failed, let's see
72290734be81e83e6ef9520c07692f68095eb5b2Tom Gundersen * whether we find anything better, but if not, return
72290734be81e83e6ef9520c07692f68095eb5b2Tom Gundersen * its response data */
72290734be81e83e6ef9520c07692f68095eb5b2Tom Gundersen if (state != DNS_TRANSACTION_SUCCESS && t->state == DNS_TRANSACTION_FAILURE) {
623a4c97b9175f95c4b1c6fc34e36c56f1e4ddbfLennart Poettering DnsAnswer *a;
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering if (t->received) {
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering rcode = DNS_PACKET_RCODE(t->received);
1716f6dcf54d4c181c2e2558e3d5414f54c8d9caLennart Poettering a = t->received->answer;
1716f6dcf54d4c181c2e2558e3d5414f54c8d9caLennart Poettering } else {
1716f6dcf54d4c181c2e2558e3d5414f54c8d9caLennart Poettering rcode = t->cached_rcode;
1716f6dcf54d4c181c2e2558e3d5414f54c8d9caLennart Poettering a = t->cached;
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering }
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering dns_answer_unref(answer);
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering answer = dns_answer_ref(a);
1716f6dcf54d4c181c2e2558e3d5414f54c8d9caLennart Poettering
1716f6dcf54d4c181c2e2558e3d5414f54c8d9caLennart Poettering scope = t->scope;
1716f6dcf54d4c181c2e2558e3d5414f54c8d9caLennart Poettering state = DNS_TRANSACTION_FAILURE;
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering continue;
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering }
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering if (state == DNS_TRANSACTION_NO_SERVERS && t->state != DNS_TRANSACTION_NO_SERVERS)
091a364c802e34a58f3260c9cb5db9b75c62215cTom Gundersen state = t->state;
1716f6dcf54d4c181c2e2558e3d5414f54c8d9caLennart Poettering }
1716f6dcf54d4c181c2e2558e3d5414f54c8d9caLennart Poettering
091a364c802e34a58f3260c9cb5db9b75c62215cTom Gundersen if (pending) {
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering /* If so far we weren't successful, and there's
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering * something still pending, then wait for it */
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering if (state != DNS_TRANSACTION_SUCCESS)
091a364c802e34a58f3260c9cb5db9b75c62215cTom Gundersen return;
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering /* If we already were successful, then only wait for
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering * other transactions on the same scope to finish. */
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering SET_FOREACH(t, q->transactions, i) {
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering if (t->scope == scope && IN_SET(t->state, DNS_TRANSACTION_PENDING, DNS_TRANSACTION_NULL))
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering return;
1716f6dcf54d4c181c2e2558e3d5414f54c8d9caLennart Poettering }
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering }
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering if (IN_SET(state, DNS_TRANSACTION_SUCCESS, DNS_TRANSACTION_FAILURE)) {
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering q->answer = dns_answer_ref(answer);
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering q->answer_rcode = rcode;
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering q->answer_protocol = scope ? scope->protocol : _DNS_PROTOCOL_INVALID;
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering q->answer_family = scope ? scope->family : AF_UNSPEC;
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering }
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering /* Try to synthesize a reply if we couldn't resolve something. */
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering dns_query_synthesize_reply(q, &state);
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering dns_query_complete(q, state);
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering}
623a4c97b9175f95c4b1c6fc34e36c56f1e4ddbfLennart Poettering
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poetteringint dns_query_cname_redirect(DnsQuery *q, const char *name) {
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering _cleanup_(dns_question_unrefp) DnsQuestion *nq = NULL;
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering int r;
1716f6dcf54d4c181c2e2558e3d5414f54c8d9caLennart Poettering
1716f6dcf54d4c181c2e2558e3d5414f54c8d9caLennart Poettering assert(q);
1716f6dcf54d4c181c2e2558e3d5414f54c8d9caLennart Poettering
1716f6dcf54d4c181c2e2558e3d5414f54c8d9caLennart Poettering if (q->n_cname_redirects > CNAME_MAX)
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering return -ELOOP;
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering r = dns_question_cname_redirect(q->question, name, &nq);
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering if (r < 0)
1716f6dcf54d4c181c2e2558e3d5414f54c8d9caLennart Poettering return r;
1716f6dcf54d4c181c2e2558e3d5414f54c8d9caLennart Poettering
1716f6dcf54d4c181c2e2558e3d5414f54c8d9caLennart Poettering dns_question_unref(q->question);
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering q->question = nq;
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering nq = NULL;
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering q->n_cname_redirects++;
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering
1716f6dcf54d4c181c2e2558e3d5414f54c8d9caLennart Poettering dns_query_stop(q);
1716f6dcf54d4c181c2e2558e3d5414f54c8d9caLennart Poettering q->state = DNS_TRANSACTION_NULL;
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering return 0;
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering}
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poetteringstatic int on_bus_track(sd_bus_track *t, void *userdata) {
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering DnsQuery *q = userdata;
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering assert(t);
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering assert(q);
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering log_debug("Client of active query vanished, aborting query.");
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering dns_query_complete(q, DNS_TRANSACTION_ABORTED);
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering return 0;
1716f6dcf54d4c181c2e2558e3d5414f54c8d9caLennart Poettering}
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poetteringint dns_query_bus_track(DnsQuery *q, sd_bus_message *m) {
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering int r;
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering assert(q);
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering assert(m);
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering if (!q->bus_track) {
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering r = sd_bus_track_new(sd_bus_message_get_bus(m), &q->bus_track, on_bus_track, q);
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering if (r < 0)
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering return r;
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering }
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering r = sd_bus_track_add_sender(q->bus_track, m);
623a4c97b9175f95c4b1c6fc34e36c56f1e4ddbfLennart Poettering if (r < 0)
1716f6dcf54d4c181c2e2558e3d5414f54c8d9caLennart Poettering return r;
1716f6dcf54d4c181c2e2558e3d5414f54c8d9caLennart Poettering
1716f6dcf54d4c181c2e2558e3d5414f54c8d9caLennart Poettering return 0;
1716f6dcf54d4c181c2e2558e3d5414f54c8d9caLennart Poettering}
1716f6dcf54d4c181c2e2558e3d5414f54c8d9caLennart Poettering