resolved-dns-scope.c revision 7bcffc2efa266823d9c2da1d8536e7f9c6e70a32
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering This file is part of systemd.
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering Copyright 2014 Lennart 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 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 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#define MULTICAST_RATELIMIT_INTERVAL_USEC (1*USEC_PER_SEC)
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)
ebcf1f97de4f6b1580ae55eb56b1a3939fe6b602Lennart Poetteringint dns_scope_new(Manager *m, DnsScope **ret, Link *l, DnsProtocol protocol, int family) {
c335068380fe8c9d843cdb2cf8a00f822cfabed3Lennart Poettering s->resend_timeout = MULTICAST_RESEND_TIMEOUT_MIN_USEC;
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));
df2d202e6ed4001a21c6512c244acad5d4706c87Lennart Poettering /* Enforce ratelimiting for the multicast protocols */
c335068380fe8c9d843cdb2cf8a00f822cfabed3Lennart Poettering RATELIMIT_INIT(s->ratelimit, MULTICAST_RATELIMIT_INTERVAL_USEC, MULTICAST_RATELIMIT_BURST);
4e724d9c5ab76c3f8327945317463ef706011082Lennart Poetteringstatic void dns_scope_abort_transactions(DnsScope *s) {
c335068380fe8c9d843cdb2cf8a00f822cfabed3Lennart Poettering /* Abort the transaction, but make sure it is not
4e724d9c5ab76c3f8327945317463ef706011082Lennart Poettering * freed while we still look at it */
c335068380fe8c9d843cdb2cf8a00f822cfabed3Lennart Poettering dns_transaction_complete(t, DNS_TRANSACTION_ABORTED);
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));
c335068380fe8c9d843cdb2cf8a00f822cfabed3Lennart Poettering dns_query_candidate_free(s->query_candidates);
c335068380fe8c9d843cdb2cf8a00f822cfabed3Lennart Poettering while ((rr = ordered_hashmap_steal_first(s->conflict_queue)))
ebcf1f97de4f6b1580ae55eb56b1a3939fe6b602Lennart Poettering sd_event_source_unref(s->conflict_event_source);
c335068380fe8c9d843cdb2cf8a00f822cfabed3Lennart Poettering LIST_REMOVE(scopes, s->manager->dns_scopes, s);
df2d202e6ed4001a21c6512c244acad5d4706c87Lennart PoetteringDnsServer *dns_scope_get_dns_server(DnsScope *s) {
c335068380fe8c9d843cdb2cf8a00f822cfabed3Lennart Poettering return manager_get_dns_server(s->manager);
c335068380fe8c9d843cdb2cf8a00f822cfabed3Lennart Poetteringvoid dns_scope_next_dns_server(DnsScope *s) {
c335068380fe8c9d843cdb2cf8a00f822cfabed3Lennart Poetteringvoid dns_scope_packet_received(DnsScope *s, usec_t rtt) {
9b5ed6feda08290edce3bf916fa7362733dd30eaLennart Poettering s->resend_timeout = MIN(MAX(MULTICAST_RESEND_TIMEOUT_MIN_USEC, s->max_rtt * 2), MULTICAST_RESEND_TIMEOUT_MAX_USEC);
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poetteringvoid dns_scope_packet_lost(DnsScope *s, usec_t usec) {
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering s->resend_timeout = MIN(s->resend_timeout * 2, MULTICAST_RESEND_TIMEOUT_MAX_USEC);
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poetteringstatic int dns_scope_emit_one(DnsScope *s, int fd, DnsServer *server, DnsPacket *p) {
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering assert((s->protocol == DNS_PROTOCOL_DNS) != (fd < 0));
9b5ed6feda08290edce3bf916fa7362733dd30eaLennart Poettering if (server->possible_features >= DNS_SERVER_FEATURE_LEVEL_EDNS0) {
9b5ed6feda08290edce3bf916fa7362733dd30eaLennart Poettering edns_do = server->possible_features >= DNS_SERVER_FEATURE_LEVEL_DO;
9b5ed6feda08290edce3bf916fa7362733dd30eaLennart Poettering if (server->possible_features >= DNS_SERVER_FEATURE_LEVEL_LARGE)
9b5ed6feda08290edce3bf916fa7362733dd30eaLennart Poettering packet_size = DNS_PACKET_UNICAST_SIZE_LARGE_MAX;
9b5ed6feda08290edce3bf916fa7362733dd30eaLennart Poettering packet_size = server->received_udp_packet_max;
9b5ed6feda08290edce3bf916fa7362733dd30eaLennart Poettering r = dns_packet_append_opt_rr(p, packet_size, edns_do, &saved_size);
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering DNS_PACKET_HEADER(p)->arcount = htobe16(be16toh(DNS_PACKET_HEADER(p)->arcount) + 1);
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering if (p->size > DNS_PACKET_UNICAST_SIZE_MAX)
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering if (p->size + UDP_PACKET_HEADER_SIZE > mtu)
5b12334d35eadf1f45cc3d631fd1a2e72ffaea0aLennart Poettering DNS_PACKET_HEADER(p)->arcount = htobe16(be16toh(DNS_PACKET_HEADER(p)->arcount) - 1);
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering fd = manager_llmnr_ipv4_udp_fd(s->manager);
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering fd = manager_llmnr_ipv6_udp_fd(s->manager);
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering r = manager_send(s->manager, fd, ifindex, family, &addr, LLMNR_PORT, p);
9b5ed6feda08290edce3bf916fa7362733dd30eaLennart Poettering r = manager_send(s->manager, fd, ifindex, family, &addr, MDNS_PORT, p);
89f7c8465cd1ab37347dd0c15920bce31e8225dfLennart Poetteringint dns_scope_emit(DnsScope *s, int fd, DnsServer *server, DnsPacket *p) {
89f7c8465cd1ab37347dd0c15920bce31e8225dfLennart Poettering assert((s->protocol == DNS_PROTOCOL_DNS) != (fd < 0));
89f7c8465cd1ab37347dd0c15920bce31e8225dfLennart Poettering /* If there are multiple linked packets, set the TC bit in all but the last of them */
ebcf1f97de4f6b1580ae55eb56b1a3939fe6b602Lennart Poettering assert(p->protocol == DNS_PROTOCOL_MDNS);
c335068380fe8c9d843cdb2cf8a00f822cfabed3Lennart Poettering r = dns_scope_emit_one(s, fd, server, p);
9b5ed6feda08290edce3bf916fa7362733dd30eaLennart Poetteringstatic int dns_scope_socket(DnsScope *s, int type, int family, const union in_addr_union *address, uint16_t port, DnsServer **server) {
89f7c8465cd1ab37347dd0c15920bce31e8225dfLennart Poettering assert((family == AF_UNSPEC) == !address);
89f7c8465cd1ab37347dd0c15920bce31e8225dfLennart Poettering srv->possible_features = dns_server_possible_features(srv);
89f7c8465cd1ab37347dd0c15920bce31e8225dfLennart Poettering if (type == SOCK_DGRAM && srv->possible_features < DNS_SERVER_FEATURE_LEVEL_UDP)
89f7c8465cd1ab37347dd0c15920bce31e8225dfLennart Poettering sa.in6.sin6_scope_id = s->link ? s->link->ifindex : 0;
9b5ed6feda08290edce3bf916fa7362733dd30eaLennart Poettering sa.in6.sin6_scope_id = s->link ? s->link->ifindex : 0;
ebcf1f97de4f6b1580ae55eb56b1a3939fe6b602Lennart Poettering fd = socket(sa.sa.sa_family, type|SOCK_CLOEXEC|SOCK_NONBLOCK, 0);
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering r = setsockopt(fd, IPPROTO_TCP, TCP_NODELAY, &one, sizeof(one));
c335068380fe8c9d843cdb2cf8a00f822cfabed3Lennart Poettering uint32_t ifindex = htobe32(s->link->ifindex);
c335068380fe8c9d843cdb2cf8a00f822cfabed3Lennart Poettering r = setsockopt(fd, IPPROTO_IP, IP_UNICAST_IF, &ifindex, sizeof(ifindex));
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 /* RFC 4795, section 2.5 requires the TTL to be set to 1 */
c335068380fe8c9d843cdb2cf8a00f822cfabed3Lennart Poettering r = setsockopt(fd, IPPROTO_IP, IP_TTL, &one, sizeof(one));
878cd7e95ca303f9851d227a22d2022bd49944b0Lennart Poettering } else if (sa.sa.sa_family == AF_INET6) {
c335068380fe8c9d843cdb2cf8a00f822cfabed3Lennart Poettering r = setsockopt(fd, IPPROTO_IPV6, IPV6_UNICAST_HOPS, &one, sizeof(one));
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);
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 PoetteringDnsScopeMatch dns_scope_good_domain(DnsScope *s, int ifindex, uint64_t flags, const char *domain) {
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 if (ifindex != 0 && (!s->link || s->link->ifindex != ifindex))
717603e391b52983ca1fd218e7333a1b9dfc5c05Lennart Poettering if ((SD_RESOLVED_FLAGS_MAKE(s->protocol, s->family, 0) & flags) == 0)
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 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 /* 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)
c335068380fe8c9d843cdb2cf8a00f822cfabed3Lennart Poettering /* Never respond to some of the domains listed in RFC6761 */
9b5ed6feda08290edce3bf916fa7362733dd30eaLennart Poettering if (dns_name_endswith(domain, "invalid") > 0)
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 /* 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 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 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 */
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering assert_not_reached("Unknown scope protocol");
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poetteringint dns_scope_good_key(DnsScope *s, DnsResourceKey *key) {
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. */
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.) */
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)));
554604b3073467af75dc94fac9e2343148603289Lennart Poettering /* On mDNS and LLMNR, send A and AAAA queries only on the
ebcf1f97de4f6b1580ae55eb56b1a3939fe6b602Lennart Poettering * respective scopes */
c335068380fe8c9d843cdb2cf8a00f822cfabed3Lennart Poettering if (s->family == AF_INET && key->class == DNS_CLASS_IN && key->type == DNS_TYPE_AAAA)
554604b3073467af75dc94fac9e2343148603289Lennart Poettering if (s->family == AF_INET6 && key->class == DNS_CLASS_IN && key->type == DNS_TYPE_A)
c335068380fe8c9d843cdb2cf8a00f822cfabed3Lennart Poetteringstatic int dns_scope_multicast_membership(DnsScope *s, bool b, struct in_addr in, struct in6_addr in6) {
ebcf1f97de4f6b1580ae55eb56b1a3939fe6b602Lennart Poettering fd = manager_llmnr_ipv4_udp_fd(s->manager);
c335068380fe8c9d843cdb2cf8a00f822cfabed3Lennart Poettering /* Always first try to drop membership before we add
554604b3073467af75dc94fac9e2343148603289Lennart Poettering * one. This is necessary on some devices, such as
c335068380fe8c9d843cdb2cf8a00f822cfabed3Lennart Poettering (void) setsockopt(fd, IPPROTO_IP, IP_DROP_MEMBERSHIP, &mreqn, sizeof(mreqn));
ebcf1f97de4f6b1580ae55eb56b1a3939fe6b602Lennart Poettering if (setsockopt(fd, IPPROTO_IP, b ? IP_ADD_MEMBERSHIP : IP_DROP_MEMBERSHIP, &mreqn, sizeof(mreqn)) < 0)
a658cafa98ab55ea948c29bc87eb3945d515fb41Lennart Poettering fd = manager_llmnr_ipv6_udp_fd(s->manager);
554604b3073467af75dc94fac9e2343148603289Lennart Poettering (void) setsockopt(fd, IPPROTO_IPV6, IPV6_DROP_MEMBERSHIP, &mreq, sizeof(mreq));
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering if (setsockopt(fd, IPPROTO_IPV6, b ? IPV6_ADD_MEMBERSHIP : IPV6_DROP_MEMBERSHIP, &mreq, sizeof(mreq)) < 0)
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poetteringint dns_scope_llmnr_membership(DnsScope *s, bool b) {
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering return dns_scope_multicast_membership(s, b, LLMNR_MULTICAST_IPV4_ADDRESS, LLMNR_MULTICAST_IPV6_ADDRESS);
c335068380fe8c9d843cdb2cf8a00f822cfabed3Lennart Poetteringint dns_scope_mdns_membership(DnsScope *s, bool b) {
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering return dns_scope_multicast_membership(s, b, MDNS_MULTICAST_IPV4_ADDRESS, MDNS_MULTICAST_IPV6_ADDRESS);
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering _cleanup_(dns_packet_unrefp) DnsPacket *p = NULL;
c335068380fe8c9d843cdb2cf8a00f822cfabed3Lennart Poettering if ((!q || q->n_keys <= 0)
a931ad47a8623163a29d898224d8a8c1177ffdafLennart Poettering DNS_PACKET_HEADER(p)->flags = htobe16(DNS_PACKET_MAKE_FLAGS(
a931ad47a8623163a29d898224d8a8c1177ffdafLennart Poettering 0 /* opcode */,
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering for (i = 0; i < q->n_keys; i++) {
86b8d289717bad2800342efca0a5023aa8374e9cLennart Poettering r = dns_packet_append_key(p, q->keys[i], NULL);
c335068380fe8c9d843cdb2cf8a00f822cfabed3Lennart Poettering DNS_PACKET_HEADER(p)->qdcount = htobe16(q->n_keys);
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering r = dns_packet_append_rr(p, answer->items[i].rr, NULL, NULL);
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering DNS_PACKET_HEADER(p)->ancount = htobe16(answer->n_rrs);
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering r = dns_packet_append_rr(p, soa->items[i].rr, NULL, NULL);
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering DNS_PACKET_HEADER(p)->arcount = htobe16(soa->n_rrs);
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poetteringstatic void dns_scope_verify_conflicts(DnsScope *s, DnsPacket *p) {
c335068380fe8c9d843cdb2cf8a00f822cfabed3Lennart Poettering for (n = 0; n < p->question->n_keys; n++)
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering dns_zone_verify_conflicts(&s->zone, p->question->keys[n]);
6797c324a653f119a3d7133122648aaa4878ddd6Lennart Poettering dns_zone_verify_conflicts(&s->zone, p->answer->items[n].rr->key);
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;
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 if (p->family == AF_INET && !in_addr_equal(AF_INET, &p->destination, (union in_addr_union*) &LLMNR_MULTICAST_IPV4_ADDRESS))
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering if (p->family == AF_INET6 && !in_addr_equal(AF_INET6, &p->destination, (union in_addr_union*) &LLMNR_MULTICAST_IPV6_ADDRESS))
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering log_debug_errno(r, "Failed to extract resources from incoming packet: %m");
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering /* Somebody notified us about a possible conflict */
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering r = dns_zone_lookup(&s->zone, key, &answer, &soa, &tentative);
c335068380fe8c9d843cdb2cf8a00f822cfabed3Lennart Poettering log_debug_errno(r, "Failed to lookup key: %m");
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering dns_answer_order_by_scope(answer, in_addr_is_link_local(p->family, &p->sender) > 0);
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering r = dns_scope_make_reply_packet(s, DNS_PACKET_ID(p), DNS_RCODE_SUCCESS, p->question, answer, soa, tentative, &reply);
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering log_debug_errno(r, "Failed to build reply packet: %m");
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering r = dns_stream_write_packet(stream, reply);
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering fd = manager_llmnr_ipv4_udp_fd(s->manager);
c335068380fe8c9d843cdb2cf8a00f822cfabed3Lennart Poettering fd = manager_llmnr_ipv6_udp_fd(s->manager);
6797c324a653f119a3d7133122648aaa4878ddd6Lennart Poettering log_debug_errno(fd, "Failed to get reply socket: %m");
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 r = manager_send(s->manager, fd, p->ifindex, p->family, &p->sender, p->sender_port, reply);
c335068380fe8c9d843cdb2cf8a00f822cfabed3Lennart Poettering log_debug_errno(r, "Failed to send reply packet: %m");
bd16acf35e13a19cd2ded0a0c2ef774a98f73808Zbigniew Jędrzejewski-SzmekDnsTransaction *dns_scope_find_transaction(DnsScope *scope, DnsResourceKey *key, bool cache_ok) {
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 /* Refuse reusing transactions that completed based on cached
c335068380fe8c9d843cdb2cf8a00f822cfabed3Lennart Poettering * data instead of a real packet, if that's requested. */
c335068380fe8c9d843cdb2cf8a00f822cfabed3Lennart Poettering IN_SET(t->state, DNS_TRANSACTION_SUCCESS, DNS_TRANSACTION_FAILURE) &&
c335068380fe8c9d843cdb2cf8a00f822cfabed3Lennart Poettering t->answer_source != DNS_TRANSACTION_NETWORK)
c335068380fe8c9d843cdb2cf8a00f822cfabed3Lennart Poetteringstatic int dns_scope_make_conflict_packet(
ab49725fd8587ef2b90dd0a67b2c915bc772d089Kay Sievers _cleanup_(dns_packet_unrefp) DnsPacket *p = NULL;
ab49725fd8587ef2b90dd0a67b2c915bc772d089Kay Sievers DNS_PACKET_HEADER(p)->flags = htobe16(DNS_PACKET_MAKE_FLAGS(
ab49725fd8587ef2b90dd0a67b2c915bc772d089Kay Sievers 0 /* opcode */,
ab49725fd8587ef2b90dd0a67b2c915bc772d089Kay Sievers 0 /* (ra) */,
ab49725fd8587ef2b90dd0a67b2c915bc772d089Kay Sievers 0 /* (ad) */,
ab49725fd8587ef2b90dd0a67b2c915bc772d089Kay Sievers 0 /* (cd) */,
ab49725fd8587ef2b90dd0a67b2c915bc772d089Kay Sievers random_bytes(&DNS_PACKET_HEADER(p)->id, sizeof(uint16_t));
ab49725fd8587ef2b90dd0a67b2c915bc772d089Kay Sieversstatic int on_conflict_dispatch(sd_event_source *es, usec_t usec, void *userdata) {
if (!rr)
log_oom();
if (r == -EEXIST || r == 0)
assert(p);
if (DNS_PACKET_RRCOUNT(p) <= 0)
if (DNS_PACKET_LLMNR_C(p) != 0)
if (DNS_PACKET_LLMNR_T(p) != 0)
r = dns_packet_extract(p);
assert(s);
f = stdout;
if (s->link) {
assert(s);
return NULL;
if (s->link)
assert(s);