resolved-dns-scope.c revision 7bcffc2efa266823d9c2da1d8536e7f9c6e70a32
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering/***
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering This file is part of systemd.
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering Copyright 2014 Lennart Poettering
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering systemd is free software; you can redistribute it and/or modify it
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering under the terms of the GNU Lesser General Public License as published by
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering the Free Software Foundation; either version 2.1 of the License, or
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering (at your option) any later version.
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering systemd is distributed in the hope that it will be useful, but
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering WITHOUT ANY WARRANTY; without even the implied warranty of
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering Lesser General Public License for more details.
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering You should have received a copy of the GNU Lesser General Public License
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering along with systemd; If not, see <http://www.gnu.org/licenses/>.
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering***/
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering#include <netinet/tcp.h>
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering#include "af-list.h"
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering#include "alloc-util.h"
adacb9575a09981fcf11279f2f661e3fc21e58ffLennart Poettering#include "dns-domain.h"
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering#include "fd-util.h"
c335068380fe8c9d843cdb2cf8a00f822cfabed3Lennart Poettering#include "hostname-util.h"
c335068380fe8c9d843cdb2cf8a00f822cfabed3Lennart Poettering#include "missing.h"
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering#include "random-util.h"
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering#include "resolved-dns-scope.h"
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering#include "resolved-llmnr.h"
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering#include "resolved-mdns.h"
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering#include "socket-util.h"
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering#include "strv.h"
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering#define MULTICAST_RATELIMIT_INTERVAL_USEC (1*USEC_PER_SEC)
c335068380fe8c9d843cdb2cf8a00f822cfabed3Lennart Poettering#define MULTICAST_RATELIMIT_BURST 1000
718db96199eb307751264e4163555662c9a389faLennart Poettering
c335068380fe8c9d843cdb2cf8a00f822cfabed3Lennart Poettering/* After how much time to repeat LLMNR requests, see RFC 4795 Section 7 */
23c80348e656a4e6fd9ba8f17523a65b6fa349a0Kay Sievers#define MULTICAST_RESEND_TIMEOUT_MIN_USEC (100 * USEC_PER_MSEC)
c335068380fe8c9d843cdb2cf8a00f822cfabed3Lennart Poettering#define MULTICAST_RESEND_TIMEOUT_MAX_USEC (1 * USEC_PER_SEC)
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering
ebcf1f97de4f6b1580ae55eb56b1a3939fe6b602Lennart Poetteringint dns_scope_new(Manager *m, DnsScope **ret, Link *l, DnsProtocol protocol, int family) {
c335068380fe8c9d843cdb2cf8a00f822cfabed3Lennart Poettering DnsScope *s;
c335068380fe8c9d843cdb2cf8a00f822cfabed3Lennart Poettering
c335068380fe8c9d843cdb2cf8a00f822cfabed3Lennart Poettering assert(m);
c335068380fe8c9d843cdb2cf8a00f822cfabed3Lennart Poettering assert(ret);
c335068380fe8c9d843cdb2cf8a00f822cfabed3Lennart Poettering
c335068380fe8c9d843cdb2cf8a00f822cfabed3Lennart Poettering s = new0(DnsScope, 1);
c335068380fe8c9d843cdb2cf8a00f822cfabed3Lennart Poettering if (!s)
c335068380fe8c9d843cdb2cf8a00f822cfabed3Lennart Poettering return -ENOMEM;
c335068380fe8c9d843cdb2cf8a00f822cfabed3Lennart Poettering
c335068380fe8c9d843cdb2cf8a00f822cfabed3Lennart Poettering s->manager = m;
c335068380fe8c9d843cdb2cf8a00f822cfabed3Lennart Poettering s->link = l;
c335068380fe8c9d843cdb2cf8a00f822cfabed3Lennart Poettering s->protocol = protocol;
ebcf1f97de4f6b1580ae55eb56b1a3939fe6b602Lennart Poettering s->family = family;
c335068380fe8c9d843cdb2cf8a00f822cfabed3Lennart Poettering s->resend_timeout = MULTICAST_RESEND_TIMEOUT_MIN_USEC;
c335068380fe8c9d843cdb2cf8a00f822cfabed3Lennart Poettering
c335068380fe8c9d843cdb2cf8a00f822cfabed3Lennart Poettering LIST_PREPEND(scopes, m->dns_scopes, s);
ebcf1f97de4f6b1580ae55eb56b1a3939fe6b602Lennart Poettering
c335068380fe8c9d843cdb2cf8a00f822cfabed3Lennart Poettering dns_scope_llmnr_membership(s, true);
c335068380fe8c9d843cdb2cf8a00f822cfabed3Lennart Poettering dns_scope_mdns_membership(s, true);
c335068380fe8c9d843cdb2cf8a00f822cfabed3Lennart Poettering
ebcf1f97de4f6b1580ae55eb56b1a3939fe6b602Lennart Poettering log_debug("New scope on link %s, protocol %s, family %s", l ? l->name : "*", dns_protocol_to_string(protocol), family == AF_UNSPEC ? "*" : af_to_name(family));
c335068380fe8c9d843cdb2cf8a00f822cfabed3Lennart Poettering
df2d202e6ed4001a21c6512c244acad5d4706c87Lennart Poettering /* Enforce ratelimiting for the multicast protocols */
c335068380fe8c9d843cdb2cf8a00f822cfabed3Lennart Poettering RATELIMIT_INIT(s->ratelimit, MULTICAST_RATELIMIT_INTERVAL_USEC, MULTICAST_RATELIMIT_BURST);
c335068380fe8c9d843cdb2cf8a00f822cfabed3Lennart Poettering
ebcf1f97de4f6b1580ae55eb56b1a3939fe6b602Lennart Poettering *ret = s;
c335068380fe8c9d843cdb2cf8a00f822cfabed3Lennart Poettering return 0;
c335068380fe8c9d843cdb2cf8a00f822cfabed3Lennart Poettering}
c335068380fe8c9d843cdb2cf8a00f822cfabed3Lennart Poettering
4e724d9c5ab76c3f8327945317463ef706011082Lennart Poetteringstatic void dns_scope_abort_transactions(DnsScope *s) {
c335068380fe8c9d843cdb2cf8a00f822cfabed3Lennart Poettering assert(s);
c335068380fe8c9d843cdb2cf8a00f822cfabed3Lennart Poettering
c335068380fe8c9d843cdb2cf8a00f822cfabed3Lennart Poettering while (s->transactions) {
c335068380fe8c9d843cdb2cf8a00f822cfabed3Lennart Poettering DnsTransaction *t = s->transactions;
c335068380fe8c9d843cdb2cf8a00f822cfabed3Lennart Poettering
c335068380fe8c9d843cdb2cf8a00f822cfabed3Lennart Poettering /* Abort the transaction, but make sure it is not
4e724d9c5ab76c3f8327945317463ef706011082Lennart Poettering * freed while we still look at it */
4e724d9c5ab76c3f8327945317463ef706011082Lennart Poettering
c335068380fe8c9d843cdb2cf8a00f822cfabed3Lennart Poettering t->block_gc++;
c335068380fe8c9d843cdb2cf8a00f822cfabed3Lennart Poettering dns_transaction_complete(t, DNS_TRANSACTION_ABORTED);
ebcf1f97de4f6b1580ae55eb56b1a3939fe6b602Lennart Poettering t->block_gc--;
c335068380fe8c9d843cdb2cf8a00f822cfabed3Lennart Poettering
4e724d9c5ab76c3f8327945317463ef706011082Lennart Poettering dns_transaction_free(t);
5b12334d35eadf1f45cc3d631fd1a2e72ffaea0aLennart Poettering }
5b12334d35eadf1f45cc3d631fd1a2e72ffaea0aLennart Poettering}
5b12334d35eadf1f45cc3d631fd1a2e72ffaea0aLennart Poettering
5b12334d35eadf1f45cc3d631fd1a2e72ffaea0aLennart PoetteringDnsScope* dns_scope_free(DnsScope *s) {
5b12334d35eadf1f45cc3d631fd1a2e72ffaea0aLennart Poettering DnsResourceRecord *rr;
5b12334d35eadf1f45cc3d631fd1a2e72ffaea0aLennart Poettering
5b12334d35eadf1f45cc3d631fd1a2e72ffaea0aLennart Poettering if (!s)
4e724d9c5ab76c3f8327945317463ef706011082Lennart Poettering return NULL;
ebcf1f97de4f6b1580ae55eb56b1a3939fe6b602Lennart Poettering
4e724d9c5ab76c3f8327945317463ef706011082Lennart Poettering log_debug("Removing scope on link %s, protocol %s, family %s", s->link ? s->link->name : "*", dns_protocol_to_string(s->protocol), s->family == AF_UNSPEC ? "*" : af_to_name(s->family));
4e724d9c5ab76c3f8327945317463ef706011082Lennart Poettering
c335068380fe8c9d843cdb2cf8a00f822cfabed3Lennart Poettering dns_scope_llmnr_membership(s, false);
c335068380fe8c9d843cdb2cf8a00f822cfabed3Lennart Poettering dns_scope_mdns_membership(s, false);
ebcf1f97de4f6b1580ae55eb56b1a3939fe6b602Lennart Poettering dns_scope_abort_transactions(s);
c335068380fe8c9d843cdb2cf8a00f822cfabed3Lennart Poettering
de0671ee7fe465e108f62dcbbbe9366f81dd9e9aZbigniew Jędrzejewski-Szmek while (s->query_candidates)
c335068380fe8c9d843cdb2cf8a00f822cfabed3Lennart Poettering dns_query_candidate_free(s->query_candidates);
c335068380fe8c9d843cdb2cf8a00f822cfabed3Lennart Poettering
c335068380fe8c9d843cdb2cf8a00f822cfabed3Lennart Poettering hashmap_free(s->transactions_by_key);
ebcf1f97de4f6b1580ae55eb56b1a3939fe6b602Lennart Poettering
c335068380fe8c9d843cdb2cf8a00f822cfabed3Lennart Poettering while ((rr = ordered_hashmap_steal_first(s->conflict_queue)))
df2d202e6ed4001a21c6512c244acad5d4706c87Lennart Poettering dns_resource_record_unref(rr);
c335068380fe8c9d843cdb2cf8a00f822cfabed3Lennart Poettering
c335068380fe8c9d843cdb2cf8a00f822cfabed3Lennart Poettering ordered_hashmap_free(s->conflict_queue);
ebcf1f97de4f6b1580ae55eb56b1a3939fe6b602Lennart Poettering sd_event_source_unref(s->conflict_event_source);
c335068380fe8c9d843cdb2cf8a00f822cfabed3Lennart Poettering
c335068380fe8c9d843cdb2cf8a00f822cfabed3Lennart Poettering dns_cache_flush(&s->cache);
c335068380fe8c9d843cdb2cf8a00f822cfabed3Lennart Poettering dns_zone_flush(&s->zone);
c335068380fe8c9d843cdb2cf8a00f822cfabed3Lennart Poettering
c335068380fe8c9d843cdb2cf8a00f822cfabed3Lennart Poettering LIST_REMOVE(scopes, s->manager->dns_scopes, s);
c335068380fe8c9d843cdb2cf8a00f822cfabed3Lennart Poettering free(s);
c335068380fe8c9d843cdb2cf8a00f822cfabed3Lennart Poettering
c335068380fe8c9d843cdb2cf8a00f822cfabed3Lennart Poettering return NULL;
c335068380fe8c9d843cdb2cf8a00f822cfabed3Lennart Poettering}
c335068380fe8c9d843cdb2cf8a00f822cfabed3Lennart Poettering
df2d202e6ed4001a21c6512c244acad5d4706c87Lennart PoetteringDnsServer *dns_scope_get_dns_server(DnsScope *s) {
c335068380fe8c9d843cdb2cf8a00f822cfabed3Lennart Poettering assert(s);
ebcf1f97de4f6b1580ae55eb56b1a3939fe6b602Lennart Poettering
c335068380fe8c9d843cdb2cf8a00f822cfabed3Lennart Poettering if (s->protocol != DNS_PROTOCOL_DNS)
c335068380fe8c9d843cdb2cf8a00f822cfabed3Lennart Poettering return NULL;
c335068380fe8c9d843cdb2cf8a00f822cfabed3Lennart Poettering
ebcf1f97de4f6b1580ae55eb56b1a3939fe6b602Lennart Poettering if (s->link)
c335068380fe8c9d843cdb2cf8a00f822cfabed3Lennart Poettering return link_get_dns_server(s->link);
c335068380fe8c9d843cdb2cf8a00f822cfabed3Lennart Poettering else
c335068380fe8c9d843cdb2cf8a00f822cfabed3Lennart Poettering return manager_get_dns_server(s->manager);
c335068380fe8c9d843cdb2cf8a00f822cfabed3Lennart Poettering}
c335068380fe8c9d843cdb2cf8a00f822cfabed3Lennart Poettering
c335068380fe8c9d843cdb2cf8a00f822cfabed3Lennart Poetteringvoid dns_scope_next_dns_server(DnsScope *s) {
ebcf1f97de4f6b1580ae55eb56b1a3939fe6b602Lennart Poettering assert(s);
c335068380fe8c9d843cdb2cf8a00f822cfabed3Lennart Poettering
c335068380fe8c9d843cdb2cf8a00f822cfabed3Lennart Poettering if (s->protocol != DNS_PROTOCOL_DNS)
c335068380fe8c9d843cdb2cf8a00f822cfabed3Lennart Poettering return;
c335068380fe8c9d843cdb2cf8a00f822cfabed3Lennart Poettering
c335068380fe8c9d843cdb2cf8a00f822cfabed3Lennart Poettering if (s->link)
c335068380fe8c9d843cdb2cf8a00f822cfabed3Lennart Poettering link_next_dns_server(s->link);
c335068380fe8c9d843cdb2cf8a00f822cfabed3Lennart Poettering else
ebcf1f97de4f6b1580ae55eb56b1a3939fe6b602Lennart Poettering manager_next_dns_server(s->manager);
c335068380fe8c9d843cdb2cf8a00f822cfabed3Lennart Poettering}
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering
c335068380fe8c9d843cdb2cf8a00f822cfabed3Lennart Poetteringvoid dns_scope_packet_received(DnsScope *s, usec_t rtt) {
c335068380fe8c9d843cdb2cf8a00f822cfabed3Lennart Poettering assert(s);
ebcf1f97de4f6b1580ae55eb56b1a3939fe6b602Lennart Poettering
c335068380fe8c9d843cdb2cf8a00f822cfabed3Lennart Poettering if (rtt <= s->max_rtt)
c335068380fe8c9d843cdb2cf8a00f822cfabed3Lennart Poettering return;
c335068380fe8c9d843cdb2cf8a00f822cfabed3Lennart Poettering
c335068380fe8c9d843cdb2cf8a00f822cfabed3Lennart Poettering s->max_rtt = rtt;
9b5ed6feda08290edce3bf916fa7362733dd30eaLennart Poettering s->resend_timeout = MIN(MAX(MULTICAST_RESEND_TIMEOUT_MIN_USEC, s->max_rtt * 2), MULTICAST_RESEND_TIMEOUT_MAX_USEC);
8aec412ff697bc14995746953912ca6fdf2c9ba8Lennart Poettering}
9b5ed6feda08290edce3bf916fa7362733dd30eaLennart Poettering
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poetteringvoid dns_scope_packet_lost(DnsScope *s, usec_t usec) {
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering assert(s);
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering
c335068380fe8c9d843cdb2cf8a00f822cfabed3Lennart Poettering if (s->resend_timeout <= usec)
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering s->resend_timeout = MIN(s->resend_timeout * 2, MULTICAST_RESEND_TIMEOUT_MAX_USEC);
9b5ed6feda08290edce3bf916fa7362733dd30eaLennart Poettering}
c335068380fe8c9d843cdb2cf8a00f822cfabed3Lennart Poettering
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poetteringstatic int dns_scope_emit_one(DnsScope *s, int fd, DnsServer *server, DnsPacket *p) {
c335068380fe8c9d843cdb2cf8a00f822cfabed3Lennart Poettering union in_addr_union addr;
89f7c8465cd1ab37347dd0c15920bce31e8225dfLennart Poettering int ifindex = 0, r;
89f7c8465cd1ab37347dd0c15920bce31e8225dfLennart Poettering int family;
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering uint32_t mtu;
c335068380fe8c9d843cdb2cf8a00f822cfabed3Lennart Poettering size_t saved_size = 0;
c335068380fe8c9d843cdb2cf8a00f822cfabed3Lennart Poettering
ebcf1f97de4f6b1580ae55eb56b1a3939fe6b602Lennart Poettering assert(s);
7f0d207d2c816e0a8cb2742b0a789911f7c99356Lennart Poettering assert(p);
ebcf1f97de4f6b1580ae55eb56b1a3939fe6b602Lennart Poettering assert(p->protocol == s->protocol);
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering assert((s->protocol == DNS_PROTOCOL_DNS) != (fd < 0));
c335068380fe8c9d843cdb2cf8a00f822cfabed3Lennart Poettering
c335068380fe8c9d843cdb2cf8a00f822cfabed3Lennart Poettering if (s->link) {
ebcf1f97de4f6b1580ae55eb56b1a3939fe6b602Lennart Poettering mtu = s->link->mtu;
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering ifindex = s->link->ifindex;
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering } else
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering mtu = manager_find_mtu(s->manager);
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering switch (s->protocol) {
ebcf1f97de4f6b1580ae55eb56b1a3939fe6b602Lennart Poettering case DNS_PROTOCOL_DNS:
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering assert(server);
c335068380fe8c9d843cdb2cf8a00f822cfabed3Lennart Poettering
c335068380fe8c9d843cdb2cf8a00f822cfabed3Lennart Poettering if (DNS_PACKET_QDCOUNT(p) > 1)
ebcf1f97de4f6b1580ae55eb56b1a3939fe6b602Lennart Poettering return -EOPNOTSUPP;
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering
9b5ed6feda08290edce3bf916fa7362733dd30eaLennart Poettering if (server->possible_features >= DNS_SERVER_FEATURE_LEVEL_EDNS0) {
9b5ed6feda08290edce3bf916fa7362733dd30eaLennart Poettering bool edns_do;
9b5ed6feda08290edce3bf916fa7362733dd30eaLennart Poettering size_t packet_size;
9b5ed6feda08290edce3bf916fa7362733dd30eaLennart Poettering
9b5ed6feda08290edce3bf916fa7362733dd30eaLennart Poettering edns_do = server->possible_features >= DNS_SERVER_FEATURE_LEVEL_DO;
9b5ed6feda08290edce3bf916fa7362733dd30eaLennart Poettering
9b5ed6feda08290edce3bf916fa7362733dd30eaLennart Poettering if (server->possible_features >= DNS_SERVER_FEATURE_LEVEL_LARGE)
9b5ed6feda08290edce3bf916fa7362733dd30eaLennart Poettering packet_size = DNS_PACKET_UNICAST_SIZE_LARGE_MAX;
9b5ed6feda08290edce3bf916fa7362733dd30eaLennart Poettering else
9b5ed6feda08290edce3bf916fa7362733dd30eaLennart Poettering packet_size = server->received_udp_packet_max;
9b5ed6feda08290edce3bf916fa7362733dd30eaLennart Poettering
9b5ed6feda08290edce3bf916fa7362733dd30eaLennart Poettering r = dns_packet_append_opt_rr(p, packet_size, edns_do, &saved_size);
9b5ed6feda08290edce3bf916fa7362733dd30eaLennart Poettering if (r < 0)
9b5ed6feda08290edce3bf916fa7362733dd30eaLennart Poettering return r;
9b5ed6feda08290edce3bf916fa7362733dd30eaLennart Poettering
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering DNS_PACKET_HEADER(p)->arcount = htobe16(be16toh(DNS_PACKET_HEADER(p)->arcount) + 1);
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering }
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering if (p->size > DNS_PACKET_UNICAST_SIZE_MAX)
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering return -EMSGSIZE;
ebcf1f97de4f6b1580ae55eb56b1a3939fe6b602Lennart Poettering
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering if (p->size + UDP_PACKET_HEADER_SIZE > mtu)
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering return -EMSGSIZE;
c335068380fe8c9d843cdb2cf8a00f822cfabed3Lennart Poettering
ebcf1f97de4f6b1580ae55eb56b1a3939fe6b602Lennart Poettering r = manager_write(s->manager, fd, p);
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering if (r < 0)
c335068380fe8c9d843cdb2cf8a00f822cfabed3Lennart Poettering return r;
ebcf1f97de4f6b1580ae55eb56b1a3939fe6b602Lennart Poettering
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering if (saved_size > 0) {
c335068380fe8c9d843cdb2cf8a00f822cfabed3Lennart Poettering dns_packet_truncate(p, saved_size);
5b12334d35eadf1f45cc3d631fd1a2e72ffaea0aLennart Poettering
5b12334d35eadf1f45cc3d631fd1a2e72ffaea0aLennart Poettering DNS_PACKET_HEADER(p)->arcount = htobe16(be16toh(DNS_PACKET_HEADER(p)->arcount) - 1);
5b12334d35eadf1f45cc3d631fd1a2e72ffaea0aLennart Poettering }
5b12334d35eadf1f45cc3d631fd1a2e72ffaea0aLennart Poettering
5b12334d35eadf1f45cc3d631fd1a2e72ffaea0aLennart Poettering break;
5b12334d35eadf1f45cc3d631fd1a2e72ffaea0aLennart Poettering
c335068380fe8c9d843cdb2cf8a00f822cfabed3Lennart Poettering case DNS_PROTOCOL_LLMNR:
554604b3073467af75dc94fac9e2343148603289Lennart Poettering if (DNS_PACKET_QDCOUNT(p) > 1)
5b12334d35eadf1f45cc3d631fd1a2e72ffaea0aLennart Poettering return -EOPNOTSUPP;
c335068380fe8c9d843cdb2cf8a00f822cfabed3Lennart Poettering
ebcf1f97de4f6b1580ae55eb56b1a3939fe6b602Lennart Poettering if (!ratelimit_test(&s->ratelimit))
c335068380fe8c9d843cdb2cf8a00f822cfabed3Lennart Poettering return -EBUSY;
554604b3073467af75dc94fac9e2343148603289Lennart Poettering
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering family = s->family;
ebcf1f97de4f6b1580ae55eb56b1a3939fe6b602Lennart Poettering
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering if (family == AF_INET) {
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering addr.in = LLMNR_MULTICAST_IPV4_ADDRESS;
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering fd = manager_llmnr_ipv4_udp_fd(s->manager);
ebcf1f97de4f6b1580ae55eb56b1a3939fe6b602Lennart Poettering } else if (family == AF_INET6) {
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering addr.in6 = LLMNR_MULTICAST_IPV6_ADDRESS;
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering fd = manager_llmnr_ipv6_udp_fd(s->manager);
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering } else
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering return -EAFNOSUPPORT;
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering if (fd < 0)
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering return fd;
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering r = manager_send(s->manager, fd, ifindex, family, &addr, LLMNR_PORT, p);
ebcf1f97de4f6b1580ae55eb56b1a3939fe6b602Lennart Poettering if (r < 0)
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering return r;
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering break;
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering case DNS_PROTOCOL_MDNS:
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering if (!ratelimit_test(&s->ratelimit))
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering return -EBUSY;
ebcf1f97de4f6b1580ae55eb56b1a3939fe6b602Lennart Poettering
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering family = s->family;
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering if (family == AF_INET) {
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering addr.in = MDNS_MULTICAST_IPV4_ADDRESS;
9b5ed6feda08290edce3bf916fa7362733dd30eaLennart Poettering fd = manager_mdns_ipv4_fd(s->manager);
9b5ed6feda08290edce3bf916fa7362733dd30eaLennart Poettering } else if (family == AF_INET6) {
9b5ed6feda08290edce3bf916fa7362733dd30eaLennart Poettering addr.in6 = MDNS_MULTICAST_IPV6_ADDRESS;
9b5ed6feda08290edce3bf916fa7362733dd30eaLennart Poettering fd = manager_mdns_ipv6_fd(s->manager);
9b5ed6feda08290edce3bf916fa7362733dd30eaLennart Poettering } else
9b5ed6feda08290edce3bf916fa7362733dd30eaLennart Poettering return -EAFNOSUPPORT;
9b5ed6feda08290edce3bf916fa7362733dd30eaLennart Poettering if (fd < 0)
9b5ed6feda08290edce3bf916fa7362733dd30eaLennart Poettering return fd;
9b5ed6feda08290edce3bf916fa7362733dd30eaLennart Poettering
9b5ed6feda08290edce3bf916fa7362733dd30eaLennart Poettering r = manager_send(s->manager, fd, ifindex, family, &addr, MDNS_PORT, p);
9b5ed6feda08290edce3bf916fa7362733dd30eaLennart Poettering if (r < 0)
89f7c8465cd1ab37347dd0c15920bce31e8225dfLennart Poettering return r;
89f7c8465cd1ab37347dd0c15920bce31e8225dfLennart Poettering
89f7c8465cd1ab37347dd0c15920bce31e8225dfLennart Poettering break;
89f7c8465cd1ab37347dd0c15920bce31e8225dfLennart Poettering
89f7c8465cd1ab37347dd0c15920bce31e8225dfLennart Poettering default:
89f7c8465cd1ab37347dd0c15920bce31e8225dfLennart Poettering return -EAFNOSUPPORT;
89f7c8465cd1ab37347dd0c15920bce31e8225dfLennart Poettering }
89f7c8465cd1ab37347dd0c15920bce31e8225dfLennart Poettering
89f7c8465cd1ab37347dd0c15920bce31e8225dfLennart Poettering return 1;
9b5ed6feda08290edce3bf916fa7362733dd30eaLennart Poettering}
89f7c8465cd1ab37347dd0c15920bce31e8225dfLennart Poettering
89f7c8465cd1ab37347dd0c15920bce31e8225dfLennart Poetteringint dns_scope_emit(DnsScope *s, int fd, DnsServer *server, DnsPacket *p) {
89f7c8465cd1ab37347dd0c15920bce31e8225dfLennart Poettering int r;
89f7c8465cd1ab37347dd0c15920bce31e8225dfLennart Poettering
9b5ed6feda08290edce3bf916fa7362733dd30eaLennart Poettering assert(s);
89f7c8465cd1ab37347dd0c15920bce31e8225dfLennart Poettering assert(p);
89f7c8465cd1ab37347dd0c15920bce31e8225dfLennart Poettering assert(p->protocol == s->protocol);
89f7c8465cd1ab37347dd0c15920bce31e8225dfLennart Poettering assert((s->protocol == DNS_PROTOCOL_DNS) != (fd < 0));
89f7c8465cd1ab37347dd0c15920bce31e8225dfLennart Poettering
89f7c8465cd1ab37347dd0c15920bce31e8225dfLennart Poettering do {
89f7c8465cd1ab37347dd0c15920bce31e8225dfLennart Poettering /* If there are multiple linked packets, set the TC bit in all but the last of them */
89f7c8465cd1ab37347dd0c15920bce31e8225dfLennart Poettering if (p->more) {
ebcf1f97de4f6b1580ae55eb56b1a3939fe6b602Lennart Poettering assert(p->protocol == DNS_PROTOCOL_MDNS);
ebcf1f97de4f6b1580ae55eb56b1a3939fe6b602Lennart Poettering dns_packet_set_flags(p, true, true);
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering }
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering
c335068380fe8c9d843cdb2cf8a00f822cfabed3Lennart Poettering r = dns_scope_emit_one(s, fd, server, p);
c335068380fe8c9d843cdb2cf8a00f822cfabed3Lennart Poettering if (r < 0)
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering return r;
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering
a3e7f417d72ba3251fd6b3a228a2721a4b725a03Zbigniew Jędrzejewski-Szmek p = p->more;
89f7c8465cd1ab37347dd0c15920bce31e8225dfLennart Poettering } while(p);
89f7c8465cd1ab37347dd0c15920bce31e8225dfLennart Poettering
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering return 0;
9b5ed6feda08290edce3bf916fa7362733dd30eaLennart Poettering}
9b5ed6feda08290edce3bf916fa7362733dd30eaLennart Poettering
9b5ed6feda08290edce3bf916fa7362733dd30eaLennart Poetteringstatic int dns_scope_socket(DnsScope *s, int type, int family, const union in_addr_union *address, uint16_t port, DnsServer **server) {
9b5ed6feda08290edce3bf916fa7362733dd30eaLennart Poettering DnsServer *srv = NULL;
9b5ed6feda08290edce3bf916fa7362733dd30eaLennart Poettering _cleanup_close_ int fd = -1;
9b5ed6feda08290edce3bf916fa7362733dd30eaLennart Poettering union sockaddr_union sa = {};
9b5ed6feda08290edce3bf916fa7362733dd30eaLennart Poettering socklen_t salen;
9b5ed6feda08290edce3bf916fa7362733dd30eaLennart Poettering static const int one = 1;
9b5ed6feda08290edce3bf916fa7362733dd30eaLennart Poettering int ret, r;
89f7c8465cd1ab37347dd0c15920bce31e8225dfLennart Poettering
89f7c8465cd1ab37347dd0c15920bce31e8225dfLennart Poettering assert(s);
89f7c8465cd1ab37347dd0c15920bce31e8225dfLennart Poettering assert((family == AF_UNSPEC) == !address);
89f7c8465cd1ab37347dd0c15920bce31e8225dfLennart Poettering
89f7c8465cd1ab37347dd0c15920bce31e8225dfLennart Poettering if (family == AF_UNSPEC) {
9b5ed6feda08290edce3bf916fa7362733dd30eaLennart Poettering srv = dns_scope_get_dns_server(s);
89f7c8465cd1ab37347dd0c15920bce31e8225dfLennart Poettering if (!srv)
89f7c8465cd1ab37347dd0c15920bce31e8225dfLennart Poettering return -ESRCH;
89f7c8465cd1ab37347dd0c15920bce31e8225dfLennart Poettering
89f7c8465cd1ab37347dd0c15920bce31e8225dfLennart Poettering srv->possible_features = dns_server_possible_features(srv);
89f7c8465cd1ab37347dd0c15920bce31e8225dfLennart Poettering
89f7c8465cd1ab37347dd0c15920bce31e8225dfLennart Poettering if (type == SOCK_DGRAM && srv->possible_features < DNS_SERVER_FEATURE_LEVEL_UDP)
89f7c8465cd1ab37347dd0c15920bce31e8225dfLennart Poettering return -EAGAIN;
89f7c8465cd1ab37347dd0c15920bce31e8225dfLennart Poettering
89f7c8465cd1ab37347dd0c15920bce31e8225dfLennart Poettering sa.sa.sa_family = srv->family;
8d90c8a8d6867ffcfb61a11b73205cd7b1a72f3aLennart Poettering if (srv->family == AF_INET) {
8d90c8a8d6867ffcfb61a11b73205cd7b1a72f3aLennart Poettering sa.in.sin_port = htobe16(port);
89f7c8465cd1ab37347dd0c15920bce31e8225dfLennart Poettering sa.in.sin_addr = srv->address.in;
89f7c8465cd1ab37347dd0c15920bce31e8225dfLennart Poettering salen = sizeof(sa.in);
89f7c8465cd1ab37347dd0c15920bce31e8225dfLennart Poettering } else if (srv->family == AF_INET6) {
89f7c8465cd1ab37347dd0c15920bce31e8225dfLennart Poettering sa.in6.sin6_port = htobe16(port);
89f7c8465cd1ab37347dd0c15920bce31e8225dfLennart Poettering sa.in6.sin6_addr = srv->address.in6;
89f7c8465cd1ab37347dd0c15920bce31e8225dfLennart Poettering sa.in6.sin6_scope_id = s->link ? s->link->ifindex : 0;
89f7c8465cd1ab37347dd0c15920bce31e8225dfLennart Poettering salen = sizeof(sa.in6);
89f7c8465cd1ab37347dd0c15920bce31e8225dfLennart Poettering } else
89f7c8465cd1ab37347dd0c15920bce31e8225dfLennart Poettering return -EAFNOSUPPORT;
89f7c8465cd1ab37347dd0c15920bce31e8225dfLennart Poettering } else {
89f7c8465cd1ab37347dd0c15920bce31e8225dfLennart Poettering sa.sa.sa_family = family;
89f7c8465cd1ab37347dd0c15920bce31e8225dfLennart Poettering
89f7c8465cd1ab37347dd0c15920bce31e8225dfLennart Poettering if (family == AF_INET) {
89f7c8465cd1ab37347dd0c15920bce31e8225dfLennart Poettering sa.in.sin_port = htobe16(port);
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering sa.in.sin_addr = address->in;
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering salen = sizeof(sa.in);
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering } else if (family == AF_INET6) {
9b5ed6feda08290edce3bf916fa7362733dd30eaLennart Poettering sa.in6.sin6_port = htobe16(port);
9b5ed6feda08290edce3bf916fa7362733dd30eaLennart Poettering sa.in6.sin6_addr = address->in6;
9b5ed6feda08290edce3bf916fa7362733dd30eaLennart Poettering sa.in6.sin6_scope_id = s->link ? s->link->ifindex : 0;
9b5ed6feda08290edce3bf916fa7362733dd30eaLennart Poettering salen = sizeof(sa.in6);
9b5ed6feda08290edce3bf916fa7362733dd30eaLennart Poettering } else
9b5ed6feda08290edce3bf916fa7362733dd30eaLennart Poettering return -EAFNOSUPPORT;
9b5ed6feda08290edce3bf916fa7362733dd30eaLennart Poettering }
9b5ed6feda08290edce3bf916fa7362733dd30eaLennart Poettering
ebcf1f97de4f6b1580ae55eb56b1a3939fe6b602Lennart Poettering fd = socket(sa.sa.sa_family, type|SOCK_CLOEXEC|SOCK_NONBLOCK, 0);
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering if (fd < 0)
c335068380fe8c9d843cdb2cf8a00f822cfabed3Lennart Poettering return -errno;
c335068380fe8c9d843cdb2cf8a00f822cfabed3Lennart Poettering
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering if (type == SOCK_STREAM) {
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering r = setsockopt(fd, IPPROTO_TCP, TCP_NODELAY, &one, sizeof(one));
c335068380fe8c9d843cdb2cf8a00f822cfabed3Lennart Poettering if (r < 0)
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering return -errno;
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering }
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering
c335068380fe8c9d843cdb2cf8a00f822cfabed3Lennart Poettering if (s->link) {
c335068380fe8c9d843cdb2cf8a00f822cfabed3Lennart Poettering uint32_t ifindex = htobe32(s->link->ifindex);
ebcf1f97de4f6b1580ae55eb56b1a3939fe6b602Lennart Poettering
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering if (sa.sa.sa_family == AF_INET) {
c335068380fe8c9d843cdb2cf8a00f822cfabed3Lennart Poettering r = setsockopt(fd, IPPROTO_IP, IP_UNICAST_IF, &ifindex, sizeof(ifindex));
c335068380fe8c9d843cdb2cf8a00f822cfabed3Lennart Poettering if (r < 0)
ebcf1f97de4f6b1580ae55eb56b1a3939fe6b602Lennart Poettering return -errno;
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering } else if (sa.sa.sa_family == AF_INET6) {
878cd7e95ca303f9851d227a22d2022bd49944b0Lennart Poettering r = setsockopt(fd, IPPROTO_IPV6, IPV6_UNICAST_IF, &ifindex, sizeof(ifindex));
c335068380fe8c9d843cdb2cf8a00f822cfabed3Lennart Poettering if (r < 0)
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering return -errno;
ebcf1f97de4f6b1580ae55eb56b1a3939fe6b602Lennart Poettering }
c335068380fe8c9d843cdb2cf8a00f822cfabed3Lennart Poettering }
c335068380fe8c9d843cdb2cf8a00f822cfabed3Lennart Poettering
c335068380fe8c9d843cdb2cf8a00f822cfabed3Lennart Poettering if (s->protocol == DNS_PROTOCOL_LLMNR) {
c335068380fe8c9d843cdb2cf8a00f822cfabed3Lennart Poettering /* RFC 4795, section 2.5 requires the TTL to be set to 1 */
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering
c335068380fe8c9d843cdb2cf8a00f822cfabed3Lennart Poettering if (sa.sa.sa_family == AF_INET) {
c335068380fe8c9d843cdb2cf8a00f822cfabed3Lennart Poettering r = setsockopt(fd, IPPROTO_IP, IP_TTL, &one, sizeof(one));
c335068380fe8c9d843cdb2cf8a00f822cfabed3Lennart Poettering if (r < 0)
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering return -errno;
878cd7e95ca303f9851d227a22d2022bd49944b0Lennart Poettering } else if (sa.sa.sa_family == AF_INET6) {
c335068380fe8c9d843cdb2cf8a00f822cfabed3Lennart Poettering r = setsockopt(fd, IPPROTO_IPV6, IPV6_UNICAST_HOPS, &one, sizeof(one));
ebcf1f97de4f6b1580ae55eb56b1a3939fe6b602Lennart Poettering if (r < 0)
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering return -errno;
c335068380fe8c9d843cdb2cf8a00f822cfabed3Lennart Poettering }
c335068380fe8c9d843cdb2cf8a00f822cfabed3Lennart Poettering }
ebcf1f97de4f6b1580ae55eb56b1a3939fe6b602Lennart Poettering
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering r = connect(fd, &sa.sa, salen);
878cd7e95ca303f9851d227a22d2022bd49944b0Lennart Poettering if (r < 0 && errno != EINPROGRESS)
878cd7e95ca303f9851d227a22d2022bd49944b0Lennart Poettering return -errno;
878cd7e95ca303f9851d227a22d2022bd49944b0Lennart Poettering
878cd7e95ca303f9851d227a22d2022bd49944b0Lennart Poettering if (server)
878cd7e95ca303f9851d227a22d2022bd49944b0Lennart Poettering *server = srv;
878cd7e95ca303f9851d227a22d2022bd49944b0Lennart Poettering
878cd7e95ca303f9851d227a22d2022bd49944b0Lennart Poettering ret = fd;
878cd7e95ca303f9851d227a22d2022bd49944b0Lennart Poettering fd = -1;
878cd7e95ca303f9851d227a22d2022bd49944b0Lennart Poettering
878cd7e95ca303f9851d227a22d2022bd49944b0Lennart Poettering return ret;
878cd7e95ca303f9851d227a22d2022bd49944b0Lennart Poettering}
878cd7e95ca303f9851d227a22d2022bd49944b0Lennart Poettering
878cd7e95ca303f9851d227a22d2022bd49944b0Lennart Poetteringint dns_scope_udp_dns_socket(DnsScope *s, DnsServer **server) {
878cd7e95ca303f9851d227a22d2022bd49944b0Lennart Poettering return dns_scope_socket(s, SOCK_DGRAM, AF_UNSPEC, NULL, 53, server);
c335068380fe8c9d843cdb2cf8a00f822cfabed3Lennart Poettering}
ebcf1f97de4f6b1580ae55eb56b1a3939fe6b602Lennart Poettering
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poetteringint dns_scope_tcp_socket(DnsScope *s, int family, const union in_addr_union *address, uint16_t port, DnsServer **server) {
878cd7e95ca303f9851d227a22d2022bd49944b0Lennart Poettering return dns_scope_socket(s, SOCK_STREAM, family, address, port, server);
878cd7e95ca303f9851d227a22d2022bd49944b0Lennart Poettering}
878cd7e95ca303f9851d227a22d2022bd49944b0Lennart Poettering
878cd7e95ca303f9851d227a22d2022bd49944b0Lennart PoetteringDnsScopeMatch dns_scope_good_domain(DnsScope *s, int ifindex, uint64_t flags, const char *domain) {
878cd7e95ca303f9851d227a22d2022bd49944b0Lennart Poettering DnsSearchDomain *d;
c335068380fe8c9d843cdb2cf8a00f822cfabed3Lennart Poettering
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering assert(s);
717603e391b52983ca1fd218e7333a1b9dfc5c05Lennart Poettering assert(domain);
717603e391b52983ca1fd218e7333a1b9dfc5c05Lennart Poettering
717603e391b52983ca1fd218e7333a1b9dfc5c05Lennart Poettering /* Checks if the specified domain is something to look up on
717603e391b52983ca1fd218e7333a1b9dfc5c05Lennart Poettering * this scope. Note that this accepts non-qualified hostnames,
717603e391b52983ca1fd218e7333a1b9dfc5c05Lennart Poettering * i.e. those without any search path prefixed yet. */
717603e391b52983ca1fd218e7333a1b9dfc5c05Lennart Poettering
717603e391b52983ca1fd218e7333a1b9dfc5c05Lennart Poettering if (ifindex != 0 && (!s->link || s->link->ifindex != ifindex))
717603e391b52983ca1fd218e7333a1b9dfc5c05Lennart Poettering return DNS_SCOPE_NO;
717603e391b52983ca1fd218e7333a1b9dfc5c05Lennart Poettering
717603e391b52983ca1fd218e7333a1b9dfc5c05Lennart Poettering if ((SD_RESOLVED_FLAGS_MAKE(s->protocol, s->family, 0) & flags) == 0)
717603e391b52983ca1fd218e7333a1b9dfc5c05Lennart Poettering return DNS_SCOPE_NO;
717603e391b52983ca1fd218e7333a1b9dfc5c05Lennart Poettering
717603e391b52983ca1fd218e7333a1b9dfc5c05Lennart Poettering /* Never resolve any loopback hostname or IP address via DNS,
717603e391b52983ca1fd218e7333a1b9dfc5c05Lennart Poettering * LLMNR or mDNS. Instead, always rely on synthesized RRs for
717603e391b52983ca1fd218e7333a1b9dfc5c05Lennart Poettering * these. */
717603e391b52983ca1fd218e7333a1b9dfc5c05Lennart Poettering if (is_localhost(domain) ||
717603e391b52983ca1fd218e7333a1b9dfc5c05Lennart Poettering dns_name_endswith(domain, "127.in-addr.arpa") > 0 ||
717603e391b52983ca1fd218e7333a1b9dfc5c05Lennart Poettering dns_name_equal(domain, "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)
717603e391b52983ca1fd218e7333a1b9dfc5c05Lennart Poettering return DNS_SCOPE_NO;
717603e391b52983ca1fd218e7333a1b9dfc5c05Lennart Poettering
717603e391b52983ca1fd218e7333a1b9dfc5c05Lennart Poettering /* Never respond to some of the domains listed in RFC6303 */
c335068380fe8c9d843cdb2cf8a00f822cfabed3Lennart Poettering if (dns_name_endswith(domain, "0.in-addr.arpa") > 0 ||
c335068380fe8c9d843cdb2cf8a00f822cfabed3Lennart Poettering dns_name_equal(domain, "255.255.255.255.in-addr.arpa") > 0 ||
adacb9575a09981fcf11279f2f661e3fc21e58ffLennart Poettering dns_name_equal(domain, "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.0.ip6.arpa") > 0)
adacb9575a09981fcf11279f2f661e3fc21e58ffLennart Poettering return DNS_SCOPE_NO;
adacb9575a09981fcf11279f2f661e3fc21e58ffLennart Poettering
c335068380fe8c9d843cdb2cf8a00f822cfabed3Lennart Poettering /* Never respond to some of the domains listed in RFC6761 */
9b5ed6feda08290edce3bf916fa7362733dd30eaLennart Poettering if (dns_name_endswith(domain, "invalid") > 0)
8d07a7c47159ebc2bcc775e2c1997cb44bd1ac95Lennart Poettering return DNS_SCOPE_NO;
9b5ed6feda08290edce3bf916fa7362733dd30eaLennart Poettering
adacb9575a09981fcf11279f2f661e3fc21e58ffLennart Poettering /* Always honour search domains for routing queries. Note that
adacb9575a09981fcf11279f2f661e3fc21e58ffLennart Poettering * we return DNS_SCOPE_YES here, rather than just
3a6fb33c54bc64398e0af1c9d7c74a6b614a849dLennart Poettering * DNS_SCOPE_MAYBE, which means wildcard scopes won't be
717603e391b52983ca1fd218e7333a1b9dfc5c05Lennart Poettering * considered anymore. */
c335068380fe8c9d843cdb2cf8a00f822cfabed3Lennart Poettering LIST_FOREACH(domains, d, dns_scope_get_search_domains(s))
c335068380fe8c9d843cdb2cf8a00f822cfabed3Lennart Poettering if (dns_name_endswith(domain, d->name) > 0)
c335068380fe8c9d843cdb2cf8a00f822cfabed3Lennart Poettering return DNS_SCOPE_YES;
c335068380fe8c9d843cdb2cf8a00f822cfabed3Lennart Poettering
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering switch (s->protocol) {
ebcf1f97de4f6b1580ae55eb56b1a3939fe6b602Lennart Poettering
c335068380fe8c9d843cdb2cf8a00f822cfabed3Lennart Poettering case DNS_PROTOCOL_DNS:
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering
c335068380fe8c9d843cdb2cf8a00f822cfabed3Lennart Poettering /* Exclude link-local IP ranges */
c335068380fe8c9d843cdb2cf8a00f822cfabed3Lennart Poettering if (dns_name_endswith(domain, "254.169.in-addr.arpa") == 0 &&
c335068380fe8c9d843cdb2cf8a00f822cfabed3Lennart Poettering dns_name_endswith(domain, "8.e.f.ip6.arpa") == 0 &&
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering dns_name_endswith(domain, "9.e.f.ip6.arpa") == 0 &&
c335068380fe8c9d843cdb2cf8a00f822cfabed3Lennart Poettering dns_name_endswith(domain, "a.e.f.ip6.arpa") == 0 &&
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering dns_name_endswith(domain, "b.e.f.ip6.arpa") == 0 &&
c335068380fe8c9d843cdb2cf8a00f822cfabed3Lennart Poettering /* If networks use .local in their private setups, they are supposed to also add .local to their search
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering * domains, which we already checked above. Otherwise, we consider .local specific to mDNS and won't
c335068380fe8c9d843cdb2cf8a00f822cfabed3Lennart Poettering * send such queries ordinary DNS servers. */
c335068380fe8c9d843cdb2cf8a00f822cfabed3Lennart Poettering dns_name_endswith(domain, "local") == 0)
ebcf1f97de4f6b1580ae55eb56b1a3939fe6b602Lennart Poettering return DNS_SCOPE_MAYBE;
ebcf1f97de4f6b1580ae55eb56b1a3939fe6b602Lennart Poettering
c335068380fe8c9d843cdb2cf8a00f822cfabed3Lennart Poettering return DNS_SCOPE_NO;
6797c324a653f119a3d7133122648aaa4878ddd6Lennart Poettering
c335068380fe8c9d843cdb2cf8a00f822cfabed3Lennart Poettering case DNS_PROTOCOL_MDNS:
c335068380fe8c9d843cdb2cf8a00f822cfabed3Lennart Poettering if ((s->family == AF_INET && dns_name_endswith(domain, "in-addr.arpa") > 0) ||
c335068380fe8c9d843cdb2cf8a00f822cfabed3Lennart Poettering (s->family == AF_INET6 && dns_name_endswith(domain, "ip6.arpa") > 0) ||
6797c324a653f119a3d7133122648aaa4878ddd6Lennart Poettering (dns_name_endswith(domain, "local") > 0 && /* only resolve names ending in .local via mDNS */
c335068380fe8c9d843cdb2cf8a00f822cfabed3Lennart Poettering dns_name_equal(domain, "local") == 0 && /* but not the single-label "local" name itself */
c335068380fe8c9d843cdb2cf8a00f822cfabed3Lennart Poettering manager_is_own_hostname(s->manager, domain) <= 0)) /* never resolve the local hostname via mDNS */
c335068380fe8c9d843cdb2cf8a00f822cfabed3Lennart Poettering return DNS_SCOPE_MAYBE;
6797c324a653f119a3d7133122648aaa4878ddd6Lennart Poettering
c335068380fe8c9d843cdb2cf8a00f822cfabed3Lennart Poettering return DNS_SCOPE_NO;
c335068380fe8c9d843cdb2cf8a00f822cfabed3Lennart Poettering
c335068380fe8c9d843cdb2cf8a00f822cfabed3Lennart Poettering case DNS_PROTOCOL_LLMNR:
c335068380fe8c9d843cdb2cf8a00f822cfabed3Lennart Poettering if ((s->family == AF_INET && dns_name_endswith(domain, "in-addr.arpa") > 0) ||
ebcf1f97de4f6b1580ae55eb56b1a3939fe6b602Lennart Poettering (s->family == AF_INET6 && dns_name_endswith(domain, "ip6.arpa") > 0) ||
6797c324a653f119a3d7133122648aaa4878ddd6Lennart Poettering (dns_name_is_single_label(domain) && /* only resolve single label names via LLMNR */
ebcf1f97de4f6b1580ae55eb56b1a3939fe6b602Lennart Poettering !is_gateway_hostname(domain) && /* don't resolve "gateway" with LLMNR, let nss-myhostname handle this */
6797c324a653f119a3d7133122648aaa4878ddd6Lennart Poettering manager_is_own_hostname(s->manager, domain) <= 0)) /* never resolve the local hostname via LLMNR */
ebcf1f97de4f6b1580ae55eb56b1a3939fe6b602Lennart Poettering return DNS_SCOPE_MAYBE;
c335068380fe8c9d843cdb2cf8a00f822cfabed3Lennart Poettering
c335068380fe8c9d843cdb2cf8a00f822cfabed3Lennart Poettering return DNS_SCOPE_NO;
c335068380fe8c9d843cdb2cf8a00f822cfabed3Lennart Poettering
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering default:
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering assert_not_reached("Unknown scope protocol");
c335068380fe8c9d843cdb2cf8a00f822cfabed3Lennart Poettering }
c335068380fe8c9d843cdb2cf8a00f822cfabed3Lennart Poettering}
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poetteringint dns_scope_good_key(DnsScope *s, DnsResourceKey *key) {
ebcf1f97de4f6b1580ae55eb56b1a3939fe6b602Lennart Poettering assert(s);
c335068380fe8c9d843cdb2cf8a00f822cfabed3Lennart Poettering assert(key);
c335068380fe8c9d843cdb2cf8a00f822cfabed3Lennart Poettering
c335068380fe8c9d843cdb2cf8a00f822cfabed3Lennart Poettering /* Check if it makes sense to resolve the specified key on
c335068380fe8c9d843cdb2cf8a00f822cfabed3Lennart Poettering * this scope. Note that this call assumes as fully qualified
ebcf1f97de4f6b1580ae55eb56b1a3939fe6b602Lennart Poettering * name, i.e. the search suffixes already appended. */
554604b3073467af75dc94fac9e2343148603289Lennart Poettering
c335068380fe8c9d843cdb2cf8a00f822cfabed3Lennart Poettering if (s->protocol == DNS_PROTOCOL_DNS) {
c335068380fe8c9d843cdb2cf8a00f822cfabed3Lennart Poettering
c335068380fe8c9d843cdb2cf8a00f822cfabed3Lennart Poettering /* On classic DNS, lookin up non-address RRs is always
554604b3073467af75dc94fac9e2343148603289Lennart Poettering * fine. (Specifically, we want to permit looking up
c335068380fe8c9d843cdb2cf8a00f822cfabed3Lennart Poettering * DNSKEY and DS records on the root and top-level
c335068380fe8c9d843cdb2cf8a00f822cfabed3Lennart Poettering * domains.) */
554604b3073467af75dc94fac9e2343148603289Lennart Poettering if (!dns_resource_key_is_address(key))
554604b3073467af75dc94fac9e2343148603289Lennart Poettering return true;
ebcf1f97de4f6b1580ae55eb56b1a3939fe6b602Lennart Poettering
ebcf1f97de4f6b1580ae55eb56b1a3939fe6b602Lennart Poettering /* However, we refuse to look up A and AAAA RRs on the
ebcf1f97de4f6b1580ae55eb56b1a3939fe6b602Lennart Poettering * root and single-label domains, under the assumption
554604b3073467af75dc94fac9e2343148603289Lennart Poettering * that those should be resolved via LLMNR or search
c335068380fe8c9d843cdb2cf8a00f822cfabed3Lennart Poettering * path only, and should not be leaked onto the
c335068380fe8c9d843cdb2cf8a00f822cfabed3Lennart Poettering * internet. */
c335068380fe8c9d843cdb2cf8a00f822cfabed3Lennart Poettering return !(dns_name_is_single_label(DNS_RESOURCE_KEY_NAME(key)) ||
554604b3073467af75dc94fac9e2343148603289Lennart Poettering dns_name_is_root(DNS_RESOURCE_KEY_NAME(key)));
c335068380fe8c9d843cdb2cf8a00f822cfabed3Lennart Poettering }
c335068380fe8c9d843cdb2cf8a00f822cfabed3Lennart Poettering
554604b3073467af75dc94fac9e2343148603289Lennart Poettering /* On mDNS and LLMNR, send A and AAAA queries only on the
ebcf1f97de4f6b1580ae55eb56b1a3939fe6b602Lennart Poettering * respective scopes */
c335068380fe8c9d843cdb2cf8a00f822cfabed3Lennart Poettering
c335068380fe8c9d843cdb2cf8a00f822cfabed3Lennart Poettering if (s->family == AF_INET && key->class == DNS_CLASS_IN && key->type == DNS_TYPE_AAAA)
c335068380fe8c9d843cdb2cf8a00f822cfabed3Lennart Poettering return false;
c335068380fe8c9d843cdb2cf8a00f822cfabed3Lennart Poettering
554604b3073467af75dc94fac9e2343148603289Lennart Poettering if (s->family == AF_INET6 && key->class == DNS_CLASS_IN && key->type == DNS_TYPE_A)
c335068380fe8c9d843cdb2cf8a00f822cfabed3Lennart Poettering return false;
c335068380fe8c9d843cdb2cf8a00f822cfabed3Lennart Poettering
c335068380fe8c9d843cdb2cf8a00f822cfabed3Lennart Poettering return true;
554604b3073467af75dc94fac9e2343148603289Lennart Poettering}
c335068380fe8c9d843cdb2cf8a00f822cfabed3Lennart Poettering
c335068380fe8c9d843cdb2cf8a00f822cfabed3Lennart Poetteringstatic int dns_scope_multicast_membership(DnsScope *s, bool b, struct in_addr in, struct in6_addr in6) {
ebcf1f97de4f6b1580ae55eb56b1a3939fe6b602Lennart Poettering int fd;
ebcf1f97de4f6b1580ae55eb56b1a3939fe6b602Lennart Poettering
554604b3073467af75dc94fac9e2343148603289Lennart Poettering assert(s);
554604b3073467af75dc94fac9e2343148603289Lennart Poettering assert(s->link);
c335068380fe8c9d843cdb2cf8a00f822cfabed3Lennart Poettering
c335068380fe8c9d843cdb2cf8a00f822cfabed3Lennart Poettering if (s->family == AF_INET) {
c335068380fe8c9d843cdb2cf8a00f822cfabed3Lennart Poettering struct ip_mreqn mreqn = {
554604b3073467af75dc94fac9e2343148603289Lennart Poettering .imr_multiaddr = in,
c335068380fe8c9d843cdb2cf8a00f822cfabed3Lennart Poettering .imr_ifindex = s->link->ifindex,
c335068380fe8c9d843cdb2cf8a00f822cfabed3Lennart Poettering };
554604b3073467af75dc94fac9e2343148603289Lennart Poettering
ebcf1f97de4f6b1580ae55eb56b1a3939fe6b602Lennart Poettering fd = manager_llmnr_ipv4_udp_fd(s->manager);
c335068380fe8c9d843cdb2cf8a00f822cfabed3Lennart Poettering if (fd < 0)
a658cafa98ab55ea948c29bc87eb3945d515fb41Lennart Poettering return fd;
a658cafa98ab55ea948c29bc87eb3945d515fb41Lennart Poettering
c335068380fe8c9d843cdb2cf8a00f822cfabed3Lennart Poettering /* Always first try to drop membership before we add
554604b3073467af75dc94fac9e2343148603289Lennart Poettering * one. This is necessary on some devices, such as
c335068380fe8c9d843cdb2cf8a00f822cfabed3Lennart Poettering * veth. */
554604b3073467af75dc94fac9e2343148603289Lennart Poettering if (b)
c335068380fe8c9d843cdb2cf8a00f822cfabed3Lennart Poettering (void) setsockopt(fd, IPPROTO_IP, IP_DROP_MEMBERSHIP, &mreqn, sizeof(mreqn));
c335068380fe8c9d843cdb2cf8a00f822cfabed3Lennart Poettering
ebcf1f97de4f6b1580ae55eb56b1a3939fe6b602Lennart Poettering if (setsockopt(fd, IPPROTO_IP, b ? IP_ADD_MEMBERSHIP : IP_DROP_MEMBERSHIP, &mreqn, sizeof(mreqn)) < 0)
ebcf1f97de4f6b1580ae55eb56b1a3939fe6b602Lennart Poettering return -errno;
554604b3073467af75dc94fac9e2343148603289Lennart Poettering
a658cafa98ab55ea948c29bc87eb3945d515fb41Lennart Poettering } else if (s->family == AF_INET6) {
a658cafa98ab55ea948c29bc87eb3945d515fb41Lennart Poettering struct ipv6_mreq mreq = {
554604b3073467af75dc94fac9e2343148603289Lennart Poettering .ipv6mr_multiaddr = in6,
a658cafa98ab55ea948c29bc87eb3945d515fb41Lennart Poettering .ipv6mr_interface = s->link->ifindex,
a658cafa98ab55ea948c29bc87eb3945d515fb41Lennart Poettering };
554604b3073467af75dc94fac9e2343148603289Lennart Poettering
a658cafa98ab55ea948c29bc87eb3945d515fb41Lennart Poettering fd = manager_llmnr_ipv6_udp_fd(s->manager);
a658cafa98ab55ea948c29bc87eb3945d515fb41Lennart Poettering if (fd < 0)
554604b3073467af75dc94fac9e2343148603289Lennart Poettering return fd;
554604b3073467af75dc94fac9e2343148603289Lennart Poettering
554604b3073467af75dc94fac9e2343148603289Lennart Poettering if (b)
554604b3073467af75dc94fac9e2343148603289Lennart Poettering (void) setsockopt(fd, IPPROTO_IPV6, IPV6_DROP_MEMBERSHIP, &mreq, sizeof(mreq));
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering if (setsockopt(fd, IPPROTO_IPV6, b ? IPV6_ADD_MEMBERSHIP : IPV6_DROP_MEMBERSHIP, &mreq, sizeof(mreq)) < 0)
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering return -errno;
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering } else
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering return -EAFNOSUPPORT;
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering
c335068380fe8c9d843cdb2cf8a00f822cfabed3Lennart Poettering return 0;
c335068380fe8c9d843cdb2cf8a00f822cfabed3Lennart Poettering}
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poetteringint dns_scope_llmnr_membership(DnsScope *s, bool b) {
c335068380fe8c9d843cdb2cf8a00f822cfabed3Lennart Poettering
554604b3073467af75dc94fac9e2343148603289Lennart Poettering if (s->protocol != DNS_PROTOCOL_LLMNR)
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering return 0;
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering return dns_scope_multicast_membership(s, b, LLMNR_MULTICAST_IPV4_ADDRESS, LLMNR_MULTICAST_IPV6_ADDRESS);
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering}
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering
c335068380fe8c9d843cdb2cf8a00f822cfabed3Lennart Poetteringint dns_scope_mdns_membership(DnsScope *s, bool b) {
c335068380fe8c9d843cdb2cf8a00f822cfabed3Lennart Poettering
151b9b9662a90455262ce575a8a8ae74bf4ff336Lennart Poettering if (s->protocol != DNS_PROTOCOL_MDNS)
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering return 0;
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering return dns_scope_multicast_membership(s, b, MDNS_MULTICAST_IPV4_ADDRESS, MDNS_MULTICAST_IPV6_ADDRESS);
151b9b9662a90455262ce575a8a8ae74bf4ff336Lennart Poettering}
c335068380fe8c9d843cdb2cf8a00f822cfabed3Lennart Poettering
c335068380fe8c9d843cdb2cf8a00f822cfabed3Lennart Poetteringstatic int dns_scope_make_reply_packet(
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering DnsScope *s,
a658cafa98ab55ea948c29bc87eb3945d515fb41Lennart Poettering uint16_t id,
c335068380fe8c9d843cdb2cf8a00f822cfabed3Lennart Poettering int rcode,
c335068380fe8c9d843cdb2cf8a00f822cfabed3Lennart Poettering DnsQuestion *q,
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering DnsAnswer *answer,
c335068380fe8c9d843cdb2cf8a00f822cfabed3Lennart Poettering DnsAnswer *soa,
c335068380fe8c9d843cdb2cf8a00f822cfabed3Lennart Poettering bool tentative,
c335068380fe8c9d843cdb2cf8a00f822cfabed3Lennart Poettering DnsPacket **ret) {
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering _cleanup_(dns_packet_unrefp) DnsPacket *p = NULL;
c335068380fe8c9d843cdb2cf8a00f822cfabed3Lennart Poettering unsigned i;
c335068380fe8c9d843cdb2cf8a00f822cfabed3Lennart Poettering int r;
c335068380fe8c9d843cdb2cf8a00f822cfabed3Lennart Poettering
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering assert(s);
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering assert(ret);
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering
c335068380fe8c9d843cdb2cf8a00f822cfabed3Lennart Poettering if ((!q || q->n_keys <= 0)
c335068380fe8c9d843cdb2cf8a00f822cfabed3Lennart Poettering && (!answer || answer->n_rrs <= 0)
c335068380fe8c9d843cdb2cf8a00f822cfabed3Lennart Poettering && (!soa || soa->n_rrs <= 0))
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering return -EINVAL;
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering
c335068380fe8c9d843cdb2cf8a00f822cfabed3Lennart Poettering r = dns_packet_new(&p, s->protocol, 0);
c335068380fe8c9d843cdb2cf8a00f822cfabed3Lennart Poettering if (r < 0)
c335068380fe8c9d843cdb2cf8a00f822cfabed3Lennart Poettering return r;
554604b3073467af75dc94fac9e2343148603289Lennart Poettering
a931ad47a8623163a29d898224d8a8c1177ffdafLennart Poettering DNS_PACKET_HEADER(p)->id = id;
a931ad47a8623163a29d898224d8a8c1177ffdafLennart Poettering DNS_PACKET_HEADER(p)->flags = htobe16(DNS_PACKET_MAKE_FLAGS(
a931ad47a8623163a29d898224d8a8c1177ffdafLennart Poettering 1 /* qr */,
a931ad47a8623163a29d898224d8a8c1177ffdafLennart Poettering 0 /* opcode */,
554604b3073467af75dc94fac9e2343148603289Lennart Poettering 0 /* c */,
c335068380fe8c9d843cdb2cf8a00f822cfabed3Lennart Poettering 0 /* tc */,
554604b3073467af75dc94fac9e2343148603289Lennart Poettering tentative,
554604b3073467af75dc94fac9e2343148603289Lennart Poettering 0 /* (ra) */,
554604b3073467af75dc94fac9e2343148603289Lennart Poettering 0 /* (ad) */,
554604b3073467af75dc94fac9e2343148603289Lennart Poettering 0 /* (cd) */,
c335068380fe8c9d843cdb2cf8a00f822cfabed3Lennart Poettering rcode));
c335068380fe8c9d843cdb2cf8a00f822cfabed3Lennart Poettering
c335068380fe8c9d843cdb2cf8a00f822cfabed3Lennart Poettering if (q) {
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering for (i = 0; i < q->n_keys; i++) {
86b8d289717bad2800342efca0a5023aa8374e9cLennart Poettering r = dns_packet_append_key(p, q->keys[i], NULL);
86b8d289717bad2800342efca0a5023aa8374e9cLennart Poettering if (r < 0)
86b8d289717bad2800342efca0a5023aa8374e9cLennart Poettering return r;
86b8d289717bad2800342efca0a5023aa8374e9cLennart Poettering }
c49b30a23583ff39daaa26696bcab478d2fee0bbLennart Poettering
c335068380fe8c9d843cdb2cf8a00f822cfabed3Lennart Poettering DNS_PACKET_HEADER(p)->qdcount = htobe16(q->n_keys);
c335068380fe8c9d843cdb2cf8a00f822cfabed3Lennart Poettering }
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering if (answer) {
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering for (i = 0; i < answer->n_rrs; i++) {
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering r = dns_packet_append_rr(p, answer->items[i].rr, NULL, NULL);
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering if (r < 0)
c335068380fe8c9d843cdb2cf8a00f822cfabed3Lennart Poettering return r;
c335068380fe8c9d843cdb2cf8a00f822cfabed3Lennart Poettering }
c335068380fe8c9d843cdb2cf8a00f822cfabed3Lennart Poettering
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering DNS_PACKET_HEADER(p)->ancount = htobe16(answer->n_rrs);
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering }
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering if (soa) {
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering for (i = 0; i < soa->n_rrs; i++) {
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering r = dns_packet_append_rr(p, soa->items[i].rr, NULL, NULL);
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering if (r < 0)
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering return r;
c335068380fe8c9d843cdb2cf8a00f822cfabed3Lennart Poettering }
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering DNS_PACKET_HEADER(p)->arcount = htobe16(soa->n_rrs);
c335068380fe8c9d843cdb2cf8a00f822cfabed3Lennart Poettering }
c335068380fe8c9d843cdb2cf8a00f822cfabed3Lennart Poettering
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering *ret = p;
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering p = NULL;
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering return 0;
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering}
c335068380fe8c9d843cdb2cf8a00f822cfabed3Lennart Poettering
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poetteringstatic void dns_scope_verify_conflicts(DnsScope *s, DnsPacket *p) {
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering unsigned n;
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering assert(s);
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering assert(p);
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering
c335068380fe8c9d843cdb2cf8a00f822cfabed3Lennart Poettering if (p->question)
c335068380fe8c9d843cdb2cf8a00f822cfabed3Lennart Poettering for (n = 0; n < p->question->n_keys; n++)
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering dns_zone_verify_conflicts(&s->zone, p->question->keys[n]);
c335068380fe8c9d843cdb2cf8a00f822cfabed3Lennart Poettering if (p->answer)
c335068380fe8c9d843cdb2cf8a00f822cfabed3Lennart Poettering for (n = 0; n < p->answer->n_rrs; n++)
6797c324a653f119a3d7133122648aaa4878ddd6Lennart Poettering dns_zone_verify_conflicts(&s->zone, p->answer->items[n].rr->key);
6797c324a653f119a3d7133122648aaa4878ddd6Lennart Poettering}
6797c324a653f119a3d7133122648aaa4878ddd6Lennart Poettering
6797c324a653f119a3d7133122648aaa4878ddd6Lennart Poetteringvoid dns_scope_process_query(DnsScope *s, DnsStream *stream, DnsPacket *p) {
c335068380fe8c9d843cdb2cf8a00f822cfabed3Lennart Poettering _cleanup_(dns_packet_unrefp) DnsPacket *reply = NULL;
6797c324a653f119a3d7133122648aaa4878ddd6Lennart Poettering _cleanup_(dns_answer_unrefp) DnsAnswer *answer = NULL, *soa = NULL;
6797c324a653f119a3d7133122648aaa4878ddd6Lennart Poettering DnsResourceKey *key = NULL;
6797c324a653f119a3d7133122648aaa4878ddd6Lennart Poettering bool tentative = false;
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering int r, fd;
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering assert(s);
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering assert(p);
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering if (p->protocol != DNS_PROTOCOL_LLMNR)
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering return;
c335068380fe8c9d843cdb2cf8a00f822cfabed3Lennart Poettering
c335068380fe8c9d843cdb2cf8a00f822cfabed3Lennart Poettering if (p->ipproto == IPPROTO_UDP) {
c335068380fe8c9d843cdb2cf8a00f822cfabed3Lennart Poettering /* Don't accept UDP queries directed to anything but
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering * the LLMNR multicast addresses. See RFC 4795,
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering * section 2.5. */
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering if (p->family == AF_INET && !in_addr_equal(AF_INET, &p->destination, (union in_addr_union*) &LLMNR_MULTICAST_IPV4_ADDRESS))
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering return;
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering if (p->family == AF_INET6 && !in_addr_equal(AF_INET6, &p->destination, (union in_addr_union*) &LLMNR_MULTICAST_IPV6_ADDRESS))
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering return;
6797c324a653f119a3d7133122648aaa4878ddd6Lennart Poettering }
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering r = dns_packet_extract(p);
de58a50e24a0d55e3bbcc77f8f6170a7322acf52Lennart Poettering if (r < 0) {
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering log_debug_errno(r, "Failed to extract resources from incoming packet: %m");
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering return;
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering }
a658cafa98ab55ea948c29bc87eb3945d515fb41Lennart Poettering
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering if (DNS_PACKET_LLMNR_C(p)) {
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering /* Somebody notified us about a possible conflict */
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering dns_scope_verify_conflicts(s, p);
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering return;
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering }
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering
a658cafa98ab55ea948c29bc87eb3945d515fb41Lennart Poettering assert(p->question->n_keys == 1);
de58a50e24a0d55e3bbcc77f8f6170a7322acf52Lennart Poettering key = p->question->keys[0];
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering r = dns_zone_lookup(&s->zone, key, &answer, &soa, &tentative);
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering if (r < 0) {
c335068380fe8c9d843cdb2cf8a00f822cfabed3Lennart Poettering log_debug_errno(r, "Failed to lookup key: %m");
c335068380fe8c9d843cdb2cf8a00f822cfabed3Lennart Poettering return;
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering }
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering if (r == 0)
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering return;
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering if (answer)
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering dns_answer_order_by_scope(answer, in_addr_is_link_local(p->family, &p->sender) > 0);
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering r = dns_scope_make_reply_packet(s, DNS_PACKET_ID(p), DNS_RCODE_SUCCESS, p->question, answer, soa, tentative, &reply);
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering if (r < 0) {
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering log_debug_errno(r, "Failed to build reply packet: %m");
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering return;
c335068380fe8c9d843cdb2cf8a00f822cfabed3Lennart Poettering }
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering if (stream)
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering r = dns_stream_write_packet(stream, reply);
c335068380fe8c9d843cdb2cf8a00f822cfabed3Lennart Poettering else {
c335068380fe8c9d843cdb2cf8a00f822cfabed3Lennart Poettering if (!ratelimit_test(&s->ratelimit))
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering return;
c335068380fe8c9d843cdb2cf8a00f822cfabed3Lennart Poettering
c335068380fe8c9d843cdb2cf8a00f822cfabed3Lennart Poettering if (p->family == AF_INET)
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering fd = manager_llmnr_ipv4_udp_fd(s->manager);
c335068380fe8c9d843cdb2cf8a00f822cfabed3Lennart Poettering else if (p->family == AF_INET6)
c335068380fe8c9d843cdb2cf8a00f822cfabed3Lennart Poettering fd = manager_llmnr_ipv6_udp_fd(s->manager);
6797c324a653f119a3d7133122648aaa4878ddd6Lennart Poettering else {
6797c324a653f119a3d7133122648aaa4878ddd6Lennart Poettering log_debug("Unknown protocol");
c335068380fe8c9d843cdb2cf8a00f822cfabed3Lennart Poettering return;
c335068380fe8c9d843cdb2cf8a00f822cfabed3Lennart Poettering }
6797c324a653f119a3d7133122648aaa4878ddd6Lennart Poettering if (fd < 0) {
6797c324a653f119a3d7133122648aaa4878ddd6Lennart Poettering log_debug_errno(fd, "Failed to get reply socket: %m");
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering return;
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering }
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering
c335068380fe8c9d843cdb2cf8a00f822cfabed3Lennart Poettering /* Note that we always immediately reply to all LLMNR
c335068380fe8c9d843cdb2cf8a00f822cfabed3Lennart Poettering * requests, and do not wait any time, since we
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering * verified uniqueness for all records. Also see RFC
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering * 4795, Section 2.7 */
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering r = manager_send(s->manager, fd, p->ifindex, p->family, &p->sender, p->sender_port, reply);
bd16acf35e13a19cd2ded0a0c2ef774a98f73808Zbigniew Jędrzejewski-Szmek }
c335068380fe8c9d843cdb2cf8a00f822cfabed3Lennart Poettering
c335068380fe8c9d843cdb2cf8a00f822cfabed3Lennart Poettering if (r < 0) {
c335068380fe8c9d843cdb2cf8a00f822cfabed3Lennart Poettering log_debug_errno(r, "Failed to send reply packet: %m");
c335068380fe8c9d843cdb2cf8a00f822cfabed3Lennart Poettering return;
bd16acf35e13a19cd2ded0a0c2ef774a98f73808Zbigniew Jędrzejewski-Szmek }
c335068380fe8c9d843cdb2cf8a00f822cfabed3Lennart Poettering}
c335068380fe8c9d843cdb2cf8a00f822cfabed3Lennart Poettering
bd16acf35e13a19cd2ded0a0c2ef774a98f73808Zbigniew Jędrzejewski-SzmekDnsTransaction *dns_scope_find_transaction(DnsScope *scope, DnsResourceKey *key, bool cache_ok) {
c335068380fe8c9d843cdb2cf8a00f822cfabed3Lennart Poettering DnsTransaction *t;
c335068380fe8c9d843cdb2cf8a00f822cfabed3Lennart Poettering
c335068380fe8c9d843cdb2cf8a00f822cfabed3Lennart Poettering assert(scope);
c335068380fe8c9d843cdb2cf8a00f822cfabed3Lennart Poettering assert(key);
c335068380fe8c9d843cdb2cf8a00f822cfabed3Lennart Poettering
c335068380fe8c9d843cdb2cf8a00f822cfabed3Lennart Poettering /* Try to find an ongoing transaction that is a equal to the
c335068380fe8c9d843cdb2cf8a00f822cfabed3Lennart Poettering * specified question */
c335068380fe8c9d843cdb2cf8a00f822cfabed3Lennart Poettering t = hashmap_get(scope->transactions_by_key, key);
c335068380fe8c9d843cdb2cf8a00f822cfabed3Lennart Poettering if (!t)
c335068380fe8c9d843cdb2cf8a00f822cfabed3Lennart Poettering return NULL;
c335068380fe8c9d843cdb2cf8a00f822cfabed3Lennart Poettering
c335068380fe8c9d843cdb2cf8a00f822cfabed3Lennart Poettering /* Refuse reusing transactions that completed based on cached
c335068380fe8c9d843cdb2cf8a00f822cfabed3Lennart Poettering * data instead of a real packet, if that's requested. */
bd16acf35e13a19cd2ded0a0c2ef774a98f73808Zbigniew Jędrzejewski-Szmek if (!cache_ok &&
c335068380fe8c9d843cdb2cf8a00f822cfabed3Lennart Poettering IN_SET(t->state, DNS_TRANSACTION_SUCCESS, DNS_TRANSACTION_FAILURE) &&
c335068380fe8c9d843cdb2cf8a00f822cfabed3Lennart Poettering t->answer_source != DNS_TRANSACTION_NETWORK)
bd16acf35e13a19cd2ded0a0c2ef774a98f73808Zbigniew Jędrzejewski-Szmek return NULL;
bd16acf35e13a19cd2ded0a0c2ef774a98f73808Zbigniew Jędrzejewski-Szmek
c335068380fe8c9d843cdb2cf8a00f822cfabed3Lennart Poettering return t;
bd16acf35e13a19cd2ded0a0c2ef774a98f73808Zbigniew Jędrzejewski-Szmek}
c335068380fe8c9d843cdb2cf8a00f822cfabed3Lennart Poettering
c335068380fe8c9d843cdb2cf8a00f822cfabed3Lennart Poetteringstatic int dns_scope_make_conflict_packet(
bd16acf35e13a19cd2ded0a0c2ef774a98f73808Zbigniew Jędrzejewski-Szmek DnsScope *s,
c335068380fe8c9d843cdb2cf8a00f822cfabed3Lennart Poettering DnsResourceRecord *rr,
bd16acf35e13a19cd2ded0a0c2ef774a98f73808Zbigniew Jędrzejewski-Szmek DnsPacket **ret) {
ab49725fd8587ef2b90dd0a67b2c915bc772d089Kay Sievers
ab49725fd8587ef2b90dd0a67b2c915bc772d089Kay Sievers _cleanup_(dns_packet_unrefp) DnsPacket *p = NULL;
ab49725fd8587ef2b90dd0a67b2c915bc772d089Kay Sievers int r;
ab49725fd8587ef2b90dd0a67b2c915bc772d089Kay Sievers
ab49725fd8587ef2b90dd0a67b2c915bc772d089Kay Sievers assert(s);
ab49725fd8587ef2b90dd0a67b2c915bc772d089Kay Sievers assert(rr);
ab49725fd8587ef2b90dd0a67b2c915bc772d089Kay Sievers assert(ret);
ab49725fd8587ef2b90dd0a67b2c915bc772d089Kay Sievers
ab49725fd8587ef2b90dd0a67b2c915bc772d089Kay Sievers r = dns_packet_new(&p, s->protocol, 0);
ab49725fd8587ef2b90dd0a67b2c915bc772d089Kay Sievers if (r < 0)
ab49725fd8587ef2b90dd0a67b2c915bc772d089Kay Sievers return r;
ab49725fd8587ef2b90dd0a67b2c915bc772d089Kay Sievers
ab49725fd8587ef2b90dd0a67b2c915bc772d089Kay Sievers DNS_PACKET_HEADER(p)->flags = htobe16(DNS_PACKET_MAKE_FLAGS(
ab49725fd8587ef2b90dd0a67b2c915bc772d089Kay Sievers 0 /* qr */,
ab49725fd8587ef2b90dd0a67b2c915bc772d089Kay Sievers 0 /* opcode */,
ab49725fd8587ef2b90dd0a67b2c915bc772d089Kay Sievers 1 /* conflict */,
ab49725fd8587ef2b90dd0a67b2c915bc772d089Kay Sievers 0 /* tc */,
ab49725fd8587ef2b90dd0a67b2c915bc772d089Kay Sievers 0 /* t */,
ab49725fd8587ef2b90dd0a67b2c915bc772d089Kay Sievers 0 /* (ra) */,
ab49725fd8587ef2b90dd0a67b2c915bc772d089Kay Sievers 0 /* (ad) */,
ab49725fd8587ef2b90dd0a67b2c915bc772d089Kay Sievers 0 /* (cd) */,
ab49725fd8587ef2b90dd0a67b2c915bc772d089Kay Sievers 0));
ab49725fd8587ef2b90dd0a67b2c915bc772d089Kay Sievers random_bytes(&DNS_PACKET_HEADER(p)->id, sizeof(uint16_t));
ab49725fd8587ef2b90dd0a67b2c915bc772d089Kay Sievers DNS_PACKET_HEADER(p)->qdcount = htobe16(1);
ab49725fd8587ef2b90dd0a67b2c915bc772d089Kay Sievers DNS_PACKET_HEADER(p)->arcount = htobe16(1);
ab49725fd8587ef2b90dd0a67b2c915bc772d089Kay Sievers
ab49725fd8587ef2b90dd0a67b2c915bc772d089Kay Sievers r = dns_packet_append_key(p, rr->key, NULL);
ab49725fd8587ef2b90dd0a67b2c915bc772d089Kay Sievers if (r < 0)
ab49725fd8587ef2b90dd0a67b2c915bc772d089Kay Sievers return r;
ab49725fd8587ef2b90dd0a67b2c915bc772d089Kay Sievers
ab49725fd8587ef2b90dd0a67b2c915bc772d089Kay Sievers r = dns_packet_append_rr(p, rr, NULL, NULL);
ab49725fd8587ef2b90dd0a67b2c915bc772d089Kay Sievers if (r < 0)
ab49725fd8587ef2b90dd0a67b2c915bc772d089Kay Sievers return r;
ab49725fd8587ef2b90dd0a67b2c915bc772d089Kay Sievers
ab49725fd8587ef2b90dd0a67b2c915bc772d089Kay Sievers *ret = p;
ab49725fd8587ef2b90dd0a67b2c915bc772d089Kay Sievers p = NULL;
ab49725fd8587ef2b90dd0a67b2c915bc772d089Kay Sievers
ab49725fd8587ef2b90dd0a67b2c915bc772d089Kay Sievers return 0;
ab49725fd8587ef2b90dd0a67b2c915bc772d089Kay Sievers}
ab49725fd8587ef2b90dd0a67b2c915bc772d089Kay Sievers
ab49725fd8587ef2b90dd0a67b2c915bc772d089Kay Sieversstatic int on_conflict_dispatch(sd_event_source *es, usec_t usec, void *userdata) {
DnsScope *scope = userdata;
int r;
assert(es);
assert(scope);
scope->conflict_event_source = sd_event_source_unref(scope->conflict_event_source);
for (;;) {
_cleanup_(dns_resource_record_unrefp) DnsResourceRecord *rr = NULL;
_cleanup_(dns_packet_unrefp) DnsPacket *p = NULL;
rr = ordered_hashmap_steal_first(scope->conflict_queue);
if (!rr)
break;
r = dns_scope_make_conflict_packet(scope, rr, &p);
if (r < 0) {
log_error_errno(r, "Failed to make conflict packet: %m");
return 0;
}
r = dns_scope_emit(scope, -1, NULL, p);
if (r < 0)
log_debug_errno(r, "Failed to send conflict packet: %m");
}
return 0;
}
int dns_scope_notify_conflict(DnsScope *scope, DnsResourceRecord *rr) {
usec_t jitter;
int r;
assert(scope);
assert(rr);
/* We don't send these queries immediately. Instead, we queue
* them, and send them after some jitter delay. */
r = ordered_hashmap_ensure_allocated(&scope->conflict_queue, &dns_resource_key_hash_ops);
if (r < 0) {
log_oom();
return r;
}
/* We only place one RR per key in the conflict
* messages, not all of them. That should be enough to
* indicate where there might be a conflict */
r = ordered_hashmap_put(scope->conflict_queue, rr->key, rr);
if (r == -EEXIST || r == 0)
return 0;
if (r < 0)
return log_debug_errno(r, "Failed to queue conflicting RR: %m");
dns_resource_record_ref(rr);
if (scope->conflict_event_source)
return 0;
random_bytes(&jitter, sizeof(jitter));
jitter %= LLMNR_JITTER_INTERVAL_USEC;
r = sd_event_add_time(scope->manager->event,
&scope->conflict_event_source,
clock_boottime_or_monotonic(),
now(clock_boottime_or_monotonic()) + jitter,
LLMNR_JITTER_INTERVAL_USEC,
on_conflict_dispatch, scope);
if (r < 0)
return log_debug_errno(r, "Failed to add conflict dispatch event: %m");
return 0;
}
void dns_scope_check_conflicts(DnsScope *scope, DnsPacket *p) {
unsigned i;
int r;
assert(scope);
assert(p);
if (p->protocol != DNS_PROTOCOL_LLMNR)
return;
if (DNS_PACKET_RRCOUNT(p) <= 0)
return;
if (DNS_PACKET_LLMNR_C(p) != 0)
return;
if (DNS_PACKET_LLMNR_T(p) != 0)
return;
if (manager_our_packet(scope->manager, p))
return;
r = dns_packet_extract(p);
if (r < 0) {
log_debug_errno(r, "Failed to extract packet: %m");
return;
}
log_debug("Checking for conflicts...");
for (i = 0; i < p->answer->n_rrs; i++) {
/* Check for conflicts against the local zone. If we
* found one, we won't check any further */
r = dns_zone_check_conflicts(&scope->zone, p->answer->items[i].rr);
if (r != 0)
continue;
/* Check for conflicts against the local cache. If so,
* send out an advisory query, to inform everybody */
r = dns_cache_check_conflicts(&scope->cache, p->answer->items[i].rr, p->family, &p->sender);
if (r <= 0)
continue;
dns_scope_notify_conflict(scope, p->answer->items[i].rr);
}
}
void dns_scope_dump(DnsScope *s, FILE *f) {
assert(s);
if (!f)
f = stdout;
fputs("[Scope protocol=", f);
fputs(dns_protocol_to_string(s->protocol), f);
if (s->link) {
fputs(" interface=", f);
fputs(s->link->name, f);
}
if (s->family != AF_UNSPEC) {
fputs(" family=", f);
fputs(af_to_name(s->family), f);
}
fputs("]\n", f);
if (!dns_zone_is_empty(&s->zone)) {
fputs("ZONE:\n", f);
dns_zone_dump(&s->zone, f);
}
if (!dns_cache_is_empty(&s->cache)) {
fputs("CACHE:\n", f);
dns_cache_dump(&s->cache, f);
}
}
DnsSearchDomain *dns_scope_get_search_domains(DnsScope *s) {
assert(s);
if (s->protocol != DNS_PROTOCOL_DNS)
return NULL;
if (s->link)
return s->link->search_domains;
return s->manager->search_domains;
}
bool dns_scope_name_needs_search_domain(DnsScope *s, const char *name) {
assert(s);
if (s->protocol != DNS_PROTOCOL_DNS)
return false;
return dns_name_is_single_label(name);
}