summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAndy Wingo <wingo@pobox.com>2015-04-19 13:28:46 +0200
committerAndy Wingo <wingo@pobox.com>2015-04-19 13:32:26 +0200
commit2dd57213e1114c1e034e52b7ff8eaeaee752d9f3 (patch)
tree524803384d8065fd99a70fdbc1dff6ede6dce3f4
parent1dcca8e5fe679b21a7203d6e35d58aa7aa83bbe1 (diff)
Remove src/resolve
-rw-r--r--src/resolve/.gitignore6
l---------src/resolve/Makefile1
-rw-r--r--src/resolve/dns-type.c45
-rw-r--r--src/resolve/dns-type.h120
-rw-r--r--src/resolve/org.freedesktop.resolve1.conf27
-rw-r--r--src/resolve/org.freedesktop.resolve1.service12
-rw-r--r--src/resolve/resolved-bus.c755
-rw-r--r--src/resolve/resolved-bus.h26
-rw-r--r--src/resolve/resolved-conf.c153
-rw-r--r--src/resolve/resolved-conf.h32
-rw-r--r--src/resolve/resolved-def.h30
-rw-r--r--src/resolve/resolved-dns-answer.c238
-rw-r--r--src/resolve/resolved-dns-answer.h48
-rw-r--r--src/resolve/resolved-dns-cache.c564
-rw-r--r--src/resolve/resolved-dns-cache.h45
-rw-r--r--src/resolve/resolved-dns-domain.c613
-rw-r--r--src/resolve/resolved-dns-domain.h50
-rw-r--r--src/resolve/resolved-dns-packet.c1478
-rw-r--r--src/resolve/resolved-dns-packet.h235
-rw-r--r--src/resolve/resolved-dns-query.c487
-rw-r--r--src/resolve/resolved-dns-query.h80
-rw-r--r--src/resolve/resolved-dns-question.c274
-rw-r--r--src/resolve/resolved-dns-question.h52
-rw-r--r--src/resolve/resolved-dns-rr.c698
-rw-r--r--src/resolve/resolved-dns-rr.h175
-rw-r--r--src/resolve/resolved-dns-scope.c794
-rw-r--r--src/resolve/resolved-dns-scope.h85
-rw-r--r--src/resolve/resolved-dns-server.c127
-rw-r--r--src/resolve/resolved-dns-server.h62
-rw-r--r--src/resolve/resolved-dns-stream.c402
-rw-r--r--src/resolve/resolved-dns-stream.h63
-rw-r--r--src/resolve/resolved-dns-transaction.c619
-rw-r--r--src/resolve/resolved-dns-transaction.h108
-rw-r--r--src/resolve/resolved-dns-zone.c648
-rw-r--r--src/resolve/resolved-dns-zone.h80
-rw-r--r--src/resolve/resolved-gperf.gperf19
-rw-r--r--src/resolve/resolved-link.c552
-rw-r--r--src/resolve/resolved-link.h89
-rw-r--r--src/resolve/resolved-manager.c1841
-rw-r--r--src/resolve/resolved-manager.h156
-rw-r--r--src/resolve/resolved.c115
-rw-r--r--src/resolve/resolved.conf.in17
-rw-r--r--src/resolve/test-dns-domain.c192
43 files changed, 0 insertions, 12213 deletions
diff --git a/src/resolve/.gitignore b/src/resolve/.gitignore
deleted file mode 100644
index f0835923b7..0000000000
--- a/src/resolve/.gitignore
+++ /dev/null
@@ -1,6 +0,0 @@
-/resolved-gperf.c
-/resolved.conf
-/dns_type-from-name.gperf
-/dns_type-from-name.h
-/dns_type-list.txt
-/dns_type-to-name.h
diff --git a/src/resolve/Makefile b/src/resolve/Makefile
deleted file mode 120000
index d0b0e8e008..0000000000
--- a/src/resolve/Makefile
+++ /dev/null
@@ -1 +0,0 @@
-../Makefile \ No newline at end of file
diff --git a/src/resolve/dns-type.c b/src/resolve/dns-type.c
deleted file mode 100644
index a3e740896f..0000000000
--- a/src/resolve/dns-type.c
+++ /dev/null
@@ -1,45 +0,0 @@
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
-/***
- This file is part of systemd.
-
- Copyright 2014 Zbigniew Jędrzejewski-Szmek
-
- systemd is free software; you can redistribute it and/or modify it
- under the terms of the GNU Lesser General Public License as published by
- the Free Software Foundation; either version 2.1 of the License, or
- (at your option) any later version.
-
- systemd is distributed in the hope that it will be useful, but
- WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Lesser General Public License for more details.
-
- You should have received a copy of the GNU Lesser General Public License
- along with systemd; If not, see <http://www.gnu.org/licenses/>.
-***/
-
-#include "dns-type.h"
-
-typedef const struct {
- uint16_t type;
- const char *name;
-} dns_type;
-
-static const struct dns_type_name *
-lookup_dns_type (register const char *str, register unsigned int len);
-
-#include "dns_type-from-name.h"
-#include "dns_type-to-name.h"
-
-int dns_type_from_string(const char *s) {
- const struct dns_type_name *sc;
-
- assert(s);
-
- sc = lookup_dns_type(s, strlen(s));
- if (!sc)
- return _DNS_TYPE_INVALID;
-
- return sc->id;
-}
diff --git a/src/resolve/dns-type.h b/src/resolve/dns-type.h
deleted file mode 100644
index 86951d233a..0000000000
--- a/src/resolve/dns-type.h
+++ /dev/null
@@ -1,120 +0,0 @@
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
-/***
- This file is part of systemd.
-
- Copyright 2014 Zbigniew Jędrzejewski-Szmek
-
- systemd is free software; you can redistribute it and/or modify it
- under the terms of the GNU Lesser General Public License as published by
- the Free Software Foundation; either version 2.1 of the License, or
- (at your option) any later version.
-
- systemd is distributed in the hope that it will be useful, but
- WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Lesser General Public License for more details.
-
- You should have received a copy of the GNU Lesser General Public License
- along with systemd; If not, see <http://www.gnu.org/licenses/>.
-***/
-
-#pragma once
-
-#include "macro.h"
-
-const char *dns_type_to_string(int type);
-int dns_type_from_string(const char *s);
-
-/* DNS record types, taken from
- * http://www.iana.org/assignments/dns-parameters/dns-parameters.xhtml.
- */
-enum {
- /* Normal records */
- DNS_TYPE_A = 0x01,
- DNS_TYPE_NS,
- DNS_TYPE_MD,
- DNS_TYPE_MF,
- DNS_TYPE_CNAME,
- DNS_TYPE_SOA,
- DNS_TYPE_MB,
- DNS_TYPE_MG,
- DNS_TYPE_MR,
- DNS_TYPE_NULL,
- DNS_TYPE_WKS,
- DNS_TYPE_PTR,
- DNS_TYPE_HINFO,
- DNS_TYPE_MINFO,
- DNS_TYPE_MX,
- DNS_TYPE_TXT,
- DNS_TYPE_RP,
- DNS_TYPE_AFSDB,
- DNS_TYPE_X25,
- DNS_TYPE_ISDN,
- DNS_TYPE_RT,
- DNS_TYPE_NSAP,
- DNS_TYPE_NSAP_PTR,
- DNS_TYPE_SIG,
- DNS_TYPE_KEY,
- DNS_TYPE_PX,
- DNS_TYPE_GPOS,
- DNS_TYPE_AAAA,
- DNS_TYPE_LOC,
- DNS_TYPE_NXT,
- DNS_TYPE_EID,
- DNS_TYPE_NIMLOC,
- DNS_TYPE_SRV,
- DNS_TYPE_ATMA,
- DNS_TYPE_NAPTR,
- DNS_TYPE_KX,
- DNS_TYPE_CERT,
- DNS_TYPE_A6,
- DNS_TYPE_DNAME,
- DNS_TYPE_SINK,
- DNS_TYPE_OPT, /* EDNS0 option */
- DNS_TYPE_APL,
- DNS_TYPE_DS,
- DNS_TYPE_SSHFP,
- DNS_TYPE_IPSECKEY,
- DNS_TYPE_RRSIG,
- DNS_TYPE_NSEC,
- DNS_TYPE_DNSKEY,
- DNS_TYPE_DHCID,
- DNS_TYPE_NSEC3,
- DNS_TYPE_NSEC3PARAM,
- DNS_TYPE_TLSA,
-
- DNS_TYPE_HIP = 0x37,
- DNS_TYPE_NINFO,
- DNS_TYPE_RKEY,
- DNS_TYPE_TALINK,
- DNS_TYPE_CDS,
- DNS_TYPE_CDNSKEY,
-
- DNS_TYPE_SPF = 0x63,
- DNS_TYPE_NID,
- DNS_TYPE_L32,
- DNS_TYPE_L64,
- DNS_TYPE_LP,
- DNS_TYPE_EUI48,
- DNS_TYPE_EUI64,
-
- DNS_TYPE_TKEY = 0xF9,
- DNS_TYPE_TSIG,
- DNS_TYPE_IXFR,
- DNS_TYPE_AXFR,
- DNS_TYPE_MAILB,
- DNS_TYPE_MAILA,
- DNS_TYPE_ANY,
- DNS_TYPE_URI,
- DNS_TYPE_CAA,
- DNS_TYPE_TA = 0x8000,
- DNS_TYPE_DLV,
-
- _DNS_TYPE_MAX,
- _DNS_TYPE_INVALID = -1
-};
-
-assert_cc(DNS_TYPE_SSHFP == 44);
-assert_cc(DNS_TYPE_TLSA == 52);
-assert_cc(DNS_TYPE_ANY == 255);
diff --git a/src/resolve/org.freedesktop.resolve1.conf b/src/resolve/org.freedesktop.resolve1.conf
deleted file mode 100644
index 25b09774e5..0000000000
--- a/src/resolve/org.freedesktop.resolve1.conf
+++ /dev/null
@@ -1,27 +0,0 @@
-<?xml version="1.0"?> <!--*-nxml-*-->
-<!DOCTYPE busconfig PUBLIC "-//freedesktop//DTD D-BUS Bus Configuration 1.0//EN"
- "http://www.freedesktop.org/standards/dbus/1.0/busconfig.dtd">
-
-<!--
- This file is part of systemd.
-
- systemd is free software; you can redistribute it and/or modify it
- under the terms of the GNU Lesser General Public License as published by
- the Free Software Foundation; either version 2.1 of the License, or
- (at your option) any later version.
--->
-
-<busconfig>
-
- <policy user="systemd-resolve">
- <allow own="org.freedesktop.resolve1"/>
- <allow send_destination="org.freedesktop.resolve1"/>
- <allow receive_sender="org.freedesktop.resolve1"/>
- </policy>
-
- <policy context="default">
- <allow send_destination="org.freedesktop.resolve1"/>
- <allow receive_sender="org.freedesktop.resolve1"/>
- </policy>
-
-</busconfig>
diff --git a/src/resolve/org.freedesktop.resolve1.service b/src/resolve/org.freedesktop.resolve1.service
deleted file mode 100644
index 7ac5c323f0..0000000000
--- a/src/resolve/org.freedesktop.resolve1.service
+++ /dev/null
@@ -1,12 +0,0 @@
-# This file is part of systemd.
-#
-# systemd is free software; you can redistribute it and/or modify it
-# under the terms of the GNU Lesser General Public License as published by
-# the Free Software Foundation; either version 2.1 of the License, or
-# (at your option) any later version.
-
-[D-BUS Service]
-Name=org.freedesktop.resolve1
-Exec=/bin/false
-User=root
-SystemdService=dbus-org.freedesktop.resolve1.service
diff --git a/src/resolve/resolved-bus.c b/src/resolve/resolved-bus.c
deleted file mode 100644
index fba2afcc8d..0000000000
--- a/src/resolve/resolved-bus.c
+++ /dev/null
@@ -1,755 +0,0 @@
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
-/***
- This file is part of systemd.
-
- Copyright 2014 Lennart Poettering
-
- systemd is free software; you can redistribute it and/or modify it
- under the terms of the GNU Lesser General Public License as published by
- the Free Software Foundation; either version 2.1 of the License, or
- (at your option) any later version.
-
- systemd is distributed in the hope that it will be useful, but
- WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Lesser General Public License for more details.
-
- You should have received a copy of the GNU Lesser General Public License
- along with systemd; If not, see <http://www.gnu.org/licenses/>.
-***/
-
-#include "bus-common-errors.h"
-#include "bus-util.h"
-
-#include "resolved-dns-domain.h"
-#include "resolved-bus.h"
-#include "resolved-def.h"
-
-static int reply_query_state(DnsQuery *q) {
- _cleanup_free_ char *ip = NULL;
- const char *name;
- int r;
-
- if (q->request_hostname)
- name = q->request_hostname;
- else {
- r = in_addr_to_string(q->request_family, &q->request_address, &ip);
- if (r < 0)
- return r;
-
- name = ip;
- }
-
- switch (q->state) {
-
- case DNS_TRANSACTION_NO_SERVERS:
- return sd_bus_reply_method_errorf(q->request, BUS_ERROR_NO_NAME_SERVERS, "No appropriate name servers or networks for name found");
-
- case DNS_TRANSACTION_TIMEOUT:
- return sd_bus_reply_method_errorf(q->request, SD_BUS_ERROR_TIMEOUT, "Query timed out");
-
- case DNS_TRANSACTION_ATTEMPTS_MAX_REACHED:
- return sd_bus_reply_method_errorf(q->request, SD_BUS_ERROR_TIMEOUT, "All attempts to contact name servers or networks failed");
-
- case DNS_TRANSACTION_INVALID_REPLY:
- return sd_bus_reply_method_errorf(q->request, BUS_ERROR_INVALID_REPLY, "Received invalid reply");
-
- case DNS_TRANSACTION_RESOURCES:
- return sd_bus_reply_method_errorf(q->request, BUS_ERROR_NO_RESOURCES, "Not enough resources");
-
- case DNS_TRANSACTION_ABORTED:
- return sd_bus_reply_method_errorf(q->request, BUS_ERROR_ABORTED, "Query aborted");
-
- case DNS_TRANSACTION_FAILURE: {
- _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
-
- if (q->answer_rcode == DNS_RCODE_NXDOMAIN)
- sd_bus_error_setf(&error, _BUS_ERROR_DNS "NXDOMAIN", "'%s' not found", name);
- else {
- const char *rc, *n;
- char p[3]; /* the rcode is 4 bits long */
-
- rc = dns_rcode_to_string(q->answer_rcode);
- if (!rc) {
- sprintf(p, "%i", q->answer_rcode);
- rc = p;
- }
-
- n = strjoina(_BUS_ERROR_DNS, rc);
- sd_bus_error_setf(&error, n, "Could not resolve '%s', server or network returned error %s", name, rc);
- }
-
- return sd_bus_reply_method_error(q->request, &error);
- }
-
- case DNS_TRANSACTION_NULL:
- case DNS_TRANSACTION_PENDING:
- case DNS_TRANSACTION_SUCCESS:
- default:
- assert_not_reached("Impossible state");
- }
-}
-
-static int append_address(sd_bus_message *reply, DnsResourceRecord *rr) {
- int r;
-
- assert(reply);
- assert(rr);
-
- r = sd_bus_message_open_container(reply, 'r', "iay");
- if (r < 0)
- return r;
-
- if (rr->key->type == DNS_TYPE_A) {
- r = sd_bus_message_append(reply, "i", AF_INET);
- if (r < 0)
- return r;
-
- r = sd_bus_message_append_array(reply, 'y', &rr->a.in_addr, sizeof(struct in_addr));
-
- } else if (rr->key->type == DNS_TYPE_AAAA) {
- r = sd_bus_message_append(reply, "i", AF_INET6);
- if (r < 0)
- return r;
-
- r = sd_bus_message_append_array(reply, 'y', &rr->aaaa.in6_addr, sizeof(struct in6_addr));
- } else
- return -EAFNOSUPPORT;
-
- if (r < 0)
- return r;
-
- r = sd_bus_message_close_container(reply);
- if (r < 0)
- return r;
-
- return 0;
-}
-
-static void bus_method_resolve_hostname_complete(DnsQuery *q) {
- _cleanup_(dns_resource_record_unrefp) DnsResourceRecord *cname = NULL, *canonical = NULL;
- _cleanup_bus_message_unref_ sd_bus_message *reply = NULL;
- _cleanup_(dns_answer_unrefp) DnsAnswer *answer = NULL;
- unsigned added = 0, i;
- int r;
-
- assert(q);
-
- if (q->state != DNS_TRANSACTION_SUCCESS) {
- r = reply_query_state(q);
- goto finish;
- }
-
- r = sd_bus_message_new_method_return(q->request, &reply);
- if (r < 0)
- goto finish;
-
- r = sd_bus_message_append(reply, "i", q->answer_ifindex);
- if (r < 0)
- goto finish;
-
- r = sd_bus_message_open_container(reply, 'a', "(iay)");
- if (r < 0)
- goto finish;
-
- if (q->answer) {
- answer = dns_answer_ref(q->answer);
-
- for (i = 0; i < answer->n_rrs; i++) {
- r = dns_question_matches_rr(q->question, answer->rrs[i]);
- if (r < 0)
- goto finish;
- if (r == 0) {
- /* Hmm, if this is not an address record,
- maybe it's a cname? If so, remember this */
- r = dns_question_matches_cname(q->question, answer->rrs[i]);
- if (r < 0)
- goto finish;
- if (r > 0)
- cname = dns_resource_record_ref(answer->rrs[i]);
-
- continue;
- }
-
- r = append_address(reply, answer->rrs[i]);
- if (r < 0)
- goto finish;
-
- if (!canonical)
- canonical = dns_resource_record_ref(answer->rrs[i]);
-
- added ++;
- }
- }
-
- if (added == 0) {
- if (!cname) {
- r = sd_bus_reply_method_errorf(q->request, BUS_ERROR_NO_SUCH_RR, "'%s' does not have any RR of requested type", q->request_hostname);
- goto finish;
- }
-
- /* This has a cname? Then update the query with the
- * new cname. */
- r = dns_query_cname_redirect(q, cname->cname.name);
- if (r < 0) {
- if (r == -ELOOP)
- r = sd_bus_reply_method_errorf(q->request, BUS_ERROR_CNAME_LOOP, "CNAME loop on '%s'", q->request_hostname);
- else
- r = sd_bus_reply_method_errno(q->request, -r, NULL);
-
- goto finish;
- }
-
- /* Before we restart the query, let's see if any of
- * the RRs we already got already answers our query */
- for (i = 0; i < answer->n_rrs; i++) {
- r = dns_question_matches_rr(q->question, answer->rrs[i]);
- if (r < 0)
- goto finish;
- if (r == 0)
- continue;
-
- r = append_address(reply, answer->rrs[i]);
- if (r < 0)
- goto finish;
-
- if (!canonical)
- canonical = dns_resource_record_ref(answer->rrs[i]);
-
- added++;
- }
-
- // what about the cache?
-
- /* If we didn't find anything, then let's restart the
- * query, this time with the cname */
- if (added <= 0) {
- r = dns_query_go(q);
- if (r == -ESRCH) {
- r = sd_bus_reply_method_errorf(q->request, BUS_ERROR_NO_NAME_SERVERS, "No appropriate name servers or networks for name found");
- goto finish;
- }
- if (r < 0) {
- r = sd_bus_reply_method_errno(q->request, -r, NULL);
- goto finish;
- }
-
- return;
- }
- }
-
- r = sd_bus_message_close_container(reply);
- if (r < 0)
- goto finish;
-
- /* Return the precise spelling and uppercasing reported by the server */
- assert(canonical);
- r = sd_bus_message_append(reply, "st", DNS_RESOURCE_KEY_NAME(canonical->key), SD_RESOLVED_FLAGS_MAKE(q->answer_protocol, q->answer_family));
- if (r < 0)
- goto finish;
-
- r = sd_bus_send(q->manager->bus, reply, NULL);
-
-finish:
- if (r < 0) {
- log_error_errno(r, "Failed to send hostname reply: %m");
- sd_bus_reply_method_errno(q->request, -r, NULL);
- }
-
- dns_query_free(q);
-}
-
-static int check_ifindex_flags(int ifindex, uint64_t *flags, sd_bus_error *error) {
- assert(flags);
-
- if (ifindex < 0)
- return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Invalid interface index");
-
- if (*flags & ~SD_RESOLVED_FLAGS_ALL)
- return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Invalid flags parameter");
-
- if (*flags == 0)
- *flags = SD_RESOLVED_FLAGS_DEFAULT;
-
- return 0;
-}
-
-static int bus_method_resolve_hostname(sd_bus *bus, sd_bus_message *message, void *userdata, sd_bus_error *error) {
- _cleanup_(dns_question_unrefp) DnsQuestion *question = NULL;
- Manager *m = userdata;
- const char *hostname;
- int family, ifindex;
- uint64_t flags;
- DnsQuery *q;
- int r;
-
- assert(bus);
- assert(message);
- assert(m);
-
- r = sd_bus_message_read(message, "isit", &ifindex, &hostname, &family, &flags);
- if (r < 0)
- return r;
-
- if (!IN_SET(family, AF_INET, AF_INET6, AF_UNSPEC))
- return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Unknown address family %i", family);
-
- r = dns_name_normalize(hostname, NULL);
- if (r < 0)
- return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Invalid hostname '%s'", hostname);
-
- r = check_ifindex_flags(ifindex, &flags, error);
- if (r < 0)
- return r;
-
- question = dns_question_new(family == AF_UNSPEC ? 2 : 1);
- if (!question)
- return -ENOMEM;
-
- if (family != AF_INET6) {
- _cleanup_(dns_resource_key_unrefp) DnsResourceKey *key = NULL;
-
- key = dns_resource_key_new(DNS_CLASS_IN, DNS_TYPE_A, hostname);
- if (!key)
- return -ENOMEM;
-
- r = dns_question_add(question, key);
- if (r < 0)
- return r;
- }
-
- if (family != AF_INET) {
- _cleanup_(dns_resource_key_unrefp) DnsResourceKey *key = NULL;
-
- key = dns_resource_key_new(DNS_CLASS_IN, DNS_TYPE_AAAA, hostname);
- if (!key)
- return -ENOMEM;
-
- r = dns_question_add(question, key);
- if (r < 0)
- return r;
- }
-
- r = dns_query_new(m, &q, question, ifindex, flags);
- if (r < 0)
- return r;
-
- q->request = sd_bus_message_ref(message);
- q->request_family = family;
- q->request_hostname = hostname;
- q->complete = bus_method_resolve_hostname_complete;
-
- r = dns_query_bus_track(q, bus, message);
- if (r < 0)
- return r;
-
- r = dns_query_go(q);
- if (r < 0) {
- dns_query_free(q);
-
- if (r == -ESRCH)
- sd_bus_error_setf(error, BUS_ERROR_NO_NAME_SERVERS, "No appropriate name servers or networks for name found");
-
- return r;
- }
-
- return 1;
-}
-
-static void bus_method_resolve_address_complete(DnsQuery *q) {
- _cleanup_bus_message_unref_ sd_bus_message *reply = NULL;
- _cleanup_(dns_answer_unrefp) DnsAnswer *answer = NULL;
- unsigned added = 0, i;
- int r;
-
- assert(q);
-
- if (q->state != DNS_TRANSACTION_SUCCESS) {
- r = reply_query_state(q);
- goto finish;
- }
-
- r = sd_bus_message_new_method_return(q->request, &reply);
- if (r < 0)
- goto finish;
-
- r = sd_bus_message_append(reply, "i", q->answer_ifindex);
- if (r < 0)
- goto finish;
-
- r = sd_bus_message_open_container(reply, 'a', "s");
- if (r < 0)
- goto finish;
-
- if (q->answer) {
- answer = dns_answer_ref(q->answer);
-
- for (i = 0; i < answer->n_rrs; i++) {
- r = dns_question_matches_rr(q->question, answer->rrs[i]);
- if (r < 0)
- goto finish;
- if (r == 0)
- continue;
-
- r = sd_bus_message_append(reply, "s", answer->rrs[i]->ptr.name);
- if (r < 0)
- goto finish;
-
- added ++;
- }
- }
-
- if (added == 0) {
- _cleanup_free_ char *ip = NULL;
-
- in_addr_to_string(q->request_family, &q->request_address, &ip);
-
- r = sd_bus_reply_method_errorf(q->request, BUS_ERROR_NO_SUCH_RR, "Address '%s' does not have any RR of requested type", ip);
- goto finish;
- }
-
- r = sd_bus_message_close_container(reply);
- if (r < 0)
- goto finish;
-
- r = sd_bus_message_append(reply, "t", SD_RESOLVED_FLAGS_MAKE(q->answer_protocol, q->answer_family));
- if (r < 0)
- goto finish;
-
- r = sd_bus_send(q->manager->bus, reply, NULL);
-
-finish:
- if (r < 0) {
- log_error_errno(r, "Failed to send address reply: %m");
- sd_bus_reply_method_errno(q->request, -r, NULL);
- }
-
- dns_query_free(q);
-}
-
-static int bus_method_resolve_address(sd_bus *bus, sd_bus_message *message, void *userdata, sd_bus_error *error) {
- _cleanup_(dns_resource_key_unrefp) DnsResourceKey *key = NULL;
- _cleanup_(dns_question_unrefp) DnsQuestion *question = NULL;
- _cleanup_free_ char *reverse = NULL;
- Manager *m = userdata;
- int family, ifindex;
- uint64_t flags;
- const void *d;
- DnsQuery *q;
- size_t sz;
- int r;
-
- assert(bus);
- assert(message);
- assert(m);
-
- r = sd_bus_message_read(message, "ii", &ifindex, &family);
- if (r < 0)
- return r;
-
- if (!IN_SET(family, AF_INET, AF_INET6))
- return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Unknown address family %i", family);
-
- r = sd_bus_message_read_array(message, 'y', &d, &sz);
- if (r < 0)
- return r;
-
- if (sz != FAMILY_ADDRESS_SIZE(family))
- return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Invalid address size");
-
- r = sd_bus_message_read(message, "t", &flags);
- if (r < 0)
- return r;
-
- r = check_ifindex_flags(ifindex, &flags, error);
- if (r < 0)
- return r;
-
- r = dns_name_reverse(family, d, &reverse);
- if (r < 0)
- return r;
-
- question = dns_question_new(1);
- if (!question)
- return -ENOMEM;
-
- key = dns_resource_key_new_consume(DNS_CLASS_IN, DNS_TYPE_PTR, reverse);
- if (!key)
- return -ENOMEM;
-
- reverse = NULL;
-
- r = dns_question_add(question, key);
- if (r < 0)
- return r;
-
- r = dns_query_new(m, &q, question, ifindex, flags);
- if (r < 0)
- return r;
-
- q->request = sd_bus_message_ref(message);
- q->request_family = family;
- memcpy(&q->request_address, d, sz);
- q->complete = bus_method_resolve_address_complete;
-
- r = dns_query_bus_track(q, bus, message);
- if (r < 0)
- return r;
-
- r = dns_query_go(q);
- if (r < 0) {
- dns_query_free(q);
-
- if (r == -ESRCH)
- sd_bus_error_setf(error, BUS_ERROR_NO_NAME_SERVERS, "No appropriate name servers or networks for name found");
-
- return r;
- }
-
- return 1;
-}
-
-static void bus_method_resolve_record_complete(DnsQuery *q) {
- _cleanup_bus_message_unref_ sd_bus_message *reply = NULL;
- _cleanup_(dns_answer_unrefp) DnsAnswer *answer = NULL;
- unsigned added = 0, i;
- int r;
-
- assert(q);
-
- if (q->state != DNS_TRANSACTION_SUCCESS) {
- r = reply_query_state(q);
- goto finish;
- }
-
- r = sd_bus_message_new_method_return(q->request, &reply);
- if (r < 0)
- goto finish;
-
- r = sd_bus_message_append(reply, "i", q->answer_ifindex);
- if (r < 0)
- goto finish;
-
- r = sd_bus_message_open_container(reply, 'a', "(qqay)");
- if (r < 0)
- goto finish;
-
- if (q->answer) {
- answer = dns_answer_ref(q->answer);
-
- for (i = 0; i < answer->n_rrs; i++) {
- _cleanup_(dns_packet_unrefp) DnsPacket *p = NULL;
- size_t start;
-
- r = dns_question_matches_rr(q->question, answer->rrs[i]);
- if (r < 0)
- goto finish;
- if (r == 0)
- continue;
-
- r = dns_packet_new(&p, DNS_PROTOCOL_DNS, 0);
- if (r < 0)
- goto finish;
-
- r = dns_packet_append_rr(p, answer->rrs[i], &start);
- if (r < 0)
- goto finish;
-
- r = sd_bus_message_open_container(reply, 'r', "qqay");
- if (r < 0)
- goto finish;
-
- r = sd_bus_message_append(reply, "qq", answer->rrs[i]->key->class, answer->rrs[i]->key->type);
- if (r < 0)
- goto finish;
-
- r = sd_bus_message_append_array(reply, 'y', DNS_PACKET_DATA(p) + start, p->size - start);
- if (r < 0)
- goto finish;
-
- r = sd_bus_message_close_container(reply);
- if (r < 0)
- goto finish;
-
- added ++;
- }
- }
-
- if (added <= 0) {
- r = sd_bus_reply_method_errorf(q->request, BUS_ERROR_NO_SUCH_RR, "Name '%s' does not have any RR of the requested type", q->request_hostname);
- goto finish;
- }
-
- r = sd_bus_message_close_container(reply);
- if (r < 0)
- goto finish;
-
- r = sd_bus_message_append(reply, "t", SD_RESOLVED_FLAGS_MAKE(q->answer_protocol, q->answer_family));
- if (r < 0)
- goto finish;
-
- r = sd_bus_send(q->manager->bus, reply, NULL);
-
-finish:
- if (r < 0) {
- log_error_errno(r, "Failed to send record reply: %m");
- sd_bus_reply_method_errno(q->request, -r, NULL);
- }
-
- dns_query_free(q);
-}
-
-static int bus_method_resolve_record(sd_bus *bus, sd_bus_message *message, void *userdata, sd_bus_error *error) {
- _cleanup_(dns_resource_key_unrefp) DnsResourceKey *key = NULL;
- _cleanup_(dns_question_unrefp) DnsQuestion *question = NULL;
- Manager *m = userdata;
- uint16_t class, type;
- const char *name;
- int r, ifindex;
- uint64_t flags;
- DnsQuery *q;
-
- assert(bus);
- assert(message);
- assert(m);
-
- r = sd_bus_message_read(message, "isqqt", &ifindex, &name, &class, &type, &flags);
- if (r < 0)
- return r;
-
- r = dns_name_normalize(name, NULL);
- if (r < 0)
- return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Invalid name '%s'", name);
-
- r = check_ifindex_flags(ifindex, &flags, error);
- if (r < 0)
- return r;
-
- question = dns_question_new(1);
- if (!question)
- return -ENOMEM;
-
- key = dns_resource_key_new(class, type, name);
- if (!key)
- return -ENOMEM;
-
- r = dns_question_add(question, key);
- if (r < 0)
- return r;
-
- r = dns_query_new(m, &q, question, ifindex, flags);
- if (r < 0)
- return r;
-
- q->request = sd_bus_message_ref(message);
- q->request_hostname = name;
- q->complete = bus_method_resolve_record_complete;
-
- r = dns_query_bus_track(q, bus, message);
- if (r < 0)
- return r;
-
- r = dns_query_go(q);
- if (r < 0) {
- dns_query_free(q);
-
- if (r == -ESRCH)
- sd_bus_error_setf(error, BUS_ERROR_NO_NAME_SERVERS, "No appropriate name servers or networks for name found");
-
- return r;
- }
-
- return 1;
-}
-
-static const sd_bus_vtable resolve_vtable[] = {
- SD_BUS_VTABLE_START(0),
- SD_BUS_METHOD("ResolveHostname", "isit", "ia(iay)st", bus_method_resolve_hostname, SD_BUS_VTABLE_UNPRIVILEGED),
- SD_BUS_METHOD("ResolveAddress", "iiayt", "iast", bus_method_resolve_address, SD_BUS_VTABLE_UNPRIVILEGED),
- SD_BUS_METHOD("ResolveRecord", "isqqt", "ia(qqay)t", bus_method_resolve_record, SD_BUS_VTABLE_UNPRIVILEGED),
- SD_BUS_VTABLE_END,
-};
-
-static int on_bus_retry(sd_event_source *s, usec_t usec, void *userdata) {
- Manager *m = userdata;
-
- assert(s);
- assert(m);
-
- m->bus_retry_event_source = sd_event_source_unref(m->bus_retry_event_source);
-
- manager_connect_bus(m);
- return 0;
-}
-
-static int match_prepare_for_sleep(sd_bus *bus, sd_bus_message *message, void *userdata, sd_bus_error *ret_error) {
- Manager *m = userdata;
- int b, r;
-
- assert(bus);
- assert(bus);
-
- r = sd_bus_message_read(message, "b", &b);
- if (r < 0) {
- log_debug_errno(r, "Failed to parse PrepareForSleep signal: %m");
- return 0;
- }
-
- if (b)
- return 0;
-
- log_debug("Coming back from suspend, verifying all RRs...");
-
- manager_verify_all(m);
- return 0;
-}
-
-int manager_connect_bus(Manager *m) {
- int r;
-
- assert(m);
-
- if (m->bus)
- return 0;
-
- r = sd_bus_default_system(&m->bus);
- if (r < 0) {
- /* We failed to connect? Yuck, we must be in early
- * boot. Let's try in 5s again. As soon as we have
- * kdbus we can stop doing this... */
-
- log_debug_errno(r, "Failed to connect to bus, trying again in 5s: %m");
-
- r = sd_event_add_time(m->event, &m->bus_retry_event_source, CLOCK_MONOTONIC, now(CLOCK_MONOTONIC) + 5*USEC_PER_SEC, 0, on_bus_retry, m);
- if (r < 0)
- return log_error_errno(r, "Failed to install bus reconnect time event: %m");
-
- return 0;
- }
-
- r = sd_bus_add_object_vtable(m->bus, NULL, "/org/freedesktop/resolve1", "org.freedesktop.resolve1.Manager", resolve_vtable, m);
- if (r < 0)
- return log_error_errno(r, "Failed to register object: %m");
-
- r = sd_bus_request_name(m->bus, "org.freedesktop.resolve1", 0);
- if (r < 0)
- return log_error_errno(r, "Failed to register name: %m");
-
- r = sd_bus_attach_event(m->bus, m->event, 0);
- if (r < 0)
- return log_error_errno(r, "Failed to attach bus to event loop: %m");
-
- r = sd_bus_add_match(m->bus, &m->prepare_for_sleep_slot,
- "type='signal',"
- "sender='org.freedesktop.login1',"
- "interface='org.freedesktop.login1.Manager',"
- "member='PrepareForSleep',"
- "path='/org/freedesktop/login1'",
- match_prepare_for_sleep,
- m);
- if (r < 0)
- log_error_errno(r, "Failed to add match for PrepareForSleep: %m");
-
- return 0;
-}
diff --git a/src/resolve/resolved-bus.h b/src/resolve/resolved-bus.h
deleted file mode 100644
index 1e72891178..0000000000
--- a/src/resolve/resolved-bus.h
+++ /dev/null
@@ -1,26 +0,0 @@
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
-#pragma once
-
-/***
- This file is part of systemd.
-
- Copyright 2014 Lennart Poettering
-
- systemd is free software; you can redistribute it and/or modify it
- under the terms of the GNU Lesser General Public License as published by
- the Free Software Foundation; either version 2.1 of the License, or
- (at your option) any later version.
-
- systemd is distributed in the hope that it will be useful, but
- WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Lesser General Public License for more details.
-
- You should have received a copy of the GNU Lesser General Public License
- along with systemd; If not, see <http://www.gnu.org/licenses/>.
-***/
-
-#include "resolved-manager.h"
-
-int manager_connect_bus(Manager *m);
diff --git a/src/resolve/resolved-conf.c b/src/resolve/resolved-conf.c
deleted file mode 100644
index 7af63b0a82..0000000000
--- a/src/resolve/resolved-conf.c
+++ /dev/null
@@ -1,153 +0,0 @@
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
-/***
- This file is part of systemd.
-
- Copyright 2014 Tom Gundersen <teg@jklm.no>
-
- systemd is free software; you can redistribute it and/or modify it
- under the terms of the GNU Lesser General Public License as published by
- the Free Software Foundation; either version 2.1 of the License, or
- (at your option) any later version.
-
- systemd is distributed in the hope that it will be useful, but
- WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Lesser General Public License for more details.
-
- You should have received a copy of the GNU Lesser General Public License
- along with systemd; If not, see <http://www.gnu.org/licenses/>.
- ***/
-
-#include "conf-parser.h"
-
-#include "resolved-conf.h"
-
-int manager_parse_dns_server(Manager *m, DnsServerType type, const char *string) {
- const char *word, *state;
- size_t length;
- DnsServer *first;
- int r;
-
- assert(m);
- assert(string);
-
- first = type == DNS_SERVER_FALLBACK ? m->fallback_dns_servers : m->dns_servers;
-
- FOREACH_WORD_QUOTED(word, length, string, state) {
- char buffer[length+1];
- int family;
- union in_addr_union addr;
- bool found = false;
- DnsServer *s;
-
- memcpy(buffer, word, length);
- buffer[length] = 0;
-
- r = in_addr_from_string_auto(buffer, &family, &addr);
- if (r < 0) {
- log_warning("Ignoring invalid DNS address '%s'", buffer);
- continue;
- }
-
- /* Filter out duplicates */
- LIST_FOREACH(servers, s, first)
- if (s->family == family && in_addr_equal(family, &s->address, &addr)) {
- found = true;
- break;
- }
-
- if (found)
- continue;
-
- r = dns_server_new(m, NULL, type, NULL, family, &addr);
- if (r < 0)
- return r;
- }
-
- return 0;
-}
-
-int config_parse_dnsv(
- const char *unit,
- const char *filename,
- unsigned line,
- const char *section,
- unsigned section_line,
- const char *lvalue,
- int ltype,
- const char *rvalue,
- void *data,
- void *userdata) {
-
- Manager *m = userdata;
- int r;
-
- assert(filename);
- assert(lvalue);
- assert(rvalue);
- assert(m);
-
- if (isempty(rvalue))
- /* Empty assignment means clear the list */
- manager_flush_dns_servers(m, ltype);
- else {
- /* Otherwise add to the list */
- r = manager_parse_dns_server(m, ltype, rvalue);
- if (r < 0) {
- log_syntax(unit, LOG_ERR, filename, line, -r, "Failed to parse DNS server string '%s'. Ignoring.", rvalue);
- return 0;
- }
- }
-
- /* If we have a manual setting, then we stop reading
- * /etc/resolv.conf */
- if (ltype == DNS_SERVER_SYSTEM)
- m->read_resolv_conf = false;
-
- return 0;
-}
-
-int config_parse_support(
- const char *unit,
- const char *filename,
- unsigned line,
- const char *section,
- unsigned section_line,
- const char *lvalue,
- int ltype,
- const char *rvalue,
- void *data,
- void *userdata) {
-
- Support support, *v = data;
- int r;
-
- assert(filename);
- assert(lvalue);
- assert(rvalue);
-
- support = support_from_string(rvalue);
- if (support < 0) {
- r = parse_boolean(rvalue);
- if (r < 0) {
- log_syntax(unit, LOG_ERR, filename, line, -r, "Failed to parse support level '%s'. Ignoring.", rvalue);
- return 0;
- }
-
- support = r ? SUPPORT_YES : SUPPORT_NO;
- }
-
- *v = support;
- return 0;
-}
-
-int manager_parse_config_file(Manager *m) {
- assert(m);
-
- return config_parse_many("/etc/systemd/resolved.conf",
- CONF_DIRS_NULSTR("systemd/resolved.conf"),
- "Resolve\0",
- config_item_perf_lookup, resolved_gperf_lookup,
- false, m);
-}
diff --git a/src/resolve/resolved-conf.h b/src/resolve/resolved-conf.h
deleted file mode 100644
index b3dbea7b6b..0000000000
--- a/src/resolve/resolved-conf.h
+++ /dev/null
@@ -1,32 +0,0 @@
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
-#pragma once
-
-/***
- This file is part of systemd.
-
- Copyright 2014 Tom Gundersen <teg@jklm.no>
-
- systemd is free software; you can redistribute it and/or modify it
- under the terms of the GNU Lesser General Public License as published by
- the Free Software Foundation; either version 2.1 of the License, or
- (at your option) any later version.
-
- systemd is distributed in the hope that it will be useful, but
- WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Lesser General Public License for more details.
-
- You should have received a copy of the GNU Lesser General Public License
- along with systemd; If not, see <http://www.gnu.org/licenses/>.
-***/
-
-#include "resolved-manager.h"
-
-int manager_parse_dns_server(Manager *m, DnsServerType type, const char *string);
-int manager_parse_config_file(Manager *m);
-
-const struct ConfigPerfItem* resolved_gperf_lookup(const char *key, unsigned length);
-
-int config_parse_dnsv(const char *unit, const char *filename, unsigned line, const char *section, unsigned section_line, const char *lvalue, int ltype, const char *rvalue, void *data, void *userdata);
-int config_parse_support(const char *unit, const char *filename, unsigned line, const char *section, unsigned section_line, const char *lvalue, int ltype, const char *rvalue, void *data, void *userdata);
diff --git a/src/resolve/resolved-def.h b/src/resolve/resolved-def.h
deleted file mode 100644
index 086d111205..0000000000
--- a/src/resolve/resolved-def.h
+++ /dev/null
@@ -1,30 +0,0 @@
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
-#pragma once
-
-/***
- This file is part of systemd.
-
- Copyright 2014 Lennart Poettering
-
- systemd is free software; you can redistribute it and/or modify it
- under the terms of the GNU Lesser General Public License as published by
- the Free Software Foundation; either version 2.1 of the License, or
- (at your option) any later version.
-
- systemd is distributed in the hope that it will be useful, but
- WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Lesser General Public License for more details.
-
- You should have received a copy of the GNU Lesser General Public License
- along with systemd; If not, see <http://www.gnu.org/licenses/>.
-***/
-
-#define SD_RESOLVED_DNS ((uint64_t) 1)
-#define SD_RESOLVED_LLMNR_IPV4 ((uint64_t) 2)
-#define SD_RESOLVED_LLMNR_IPV6 ((uint64_t) 4)
-#define SD_RESOLVED_LLMNR (SD_RESOLVED_LLMNR_IPV4|SD_RESOLVED_LLMNR_IPV6)
-
-#define SD_RESOLVED_FLAGS_ALL (SD_RESOLVED_DNS|SD_RESOLVED_LLMNR_IPV4|SD_RESOLVED_LLMNR_IPV6)
-#define SD_RESOLVED_FLAGS_DEFAULT SD_RESOLVED_FLAGS_ALL
diff --git a/src/resolve/resolved-dns-answer.c b/src/resolve/resolved-dns-answer.c
deleted file mode 100644
index 7c4ab18b58..0000000000
--- a/src/resolve/resolved-dns-answer.c
+++ /dev/null
@@ -1,238 +0,0 @@
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
-/***
- This file is part of systemd.
-
- Copyright 2014 Lennart Poettering
-
- systemd is free software; you can redistribute it and/or modify it
- under the terms of the GNU Lesser General Public License as published by
- the Free Software Foundation; either version 2.1 of the License, or
- (at your option) any later version.
-
- systemd is distributed in the hope that it will be useful, but
- WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Lesser General Public License for more details.
-
- You should have received a copy of the GNU Lesser General Public License
- along with systemd; If not, see <http://www.gnu.org/licenses/>.
-***/
-
-#include "resolved-dns-answer.h"
-#include "resolved-dns-domain.h"
-
-DnsAnswer *dns_answer_new(unsigned n) {
- DnsAnswer *a;
-
- assert(n > 0);
-
- a = malloc0(offsetof(DnsAnswer, rrs) + sizeof(DnsResourceRecord*) * n);
- if (!a)
- return NULL;
-
- a->n_ref = 1;
- a->n_allocated = n;
-
- return a;
-}
-
-DnsAnswer *dns_answer_ref(DnsAnswer *a) {
- if (!a)
- return NULL;
-
- assert(a->n_ref > 0);
- a->n_ref++;
- return a;
-}
-
-DnsAnswer *dns_answer_unref(DnsAnswer *a) {
- if (!a)
- return NULL;
-
- assert(a->n_ref > 0);
-
- if (a->n_ref == 1) {
- unsigned i;
-
- for (i = 0; i < a->n_rrs; i++)
- dns_resource_record_unref(a->rrs[i]);
-
- free(a);
- } else
- a->n_ref--;
-
- return NULL;
-}
-
-int dns_answer_add(DnsAnswer *a, DnsResourceRecord *rr) {
- unsigned i;
- int r;
-
- assert(a);
- assert(rr);
-
- for (i = 0; i < a->n_rrs; i++) {
- r = dns_resource_record_equal(a->rrs[i], rr);
- if (r < 0)
- return r;
- if (r > 0) {
- /* Entry already exists, keep the entry with
- * the higher RR, or the one with TTL 0 */
-
- if (rr->ttl == 0 || (rr->ttl > a->rrs[i]->ttl && a->rrs[i]->ttl != 0)) {
- dns_resource_record_ref(rr);
- dns_resource_record_unref(a->rrs[i]);
- a->rrs[i] = rr;
- }
-
- return 0;
- }
- }
-
- if (a->n_rrs >= a->n_allocated)
- return -ENOSPC;
-
- a->rrs[a->n_rrs++] = dns_resource_record_ref(rr);
- return 1;
-}
-
-int dns_answer_add_soa(DnsAnswer *a, const char *name, uint32_t ttl) {
- _cleanup_(dns_resource_record_unrefp) DnsResourceRecord *soa = NULL;
-
- soa = dns_resource_record_new_full(DNS_CLASS_IN, DNS_TYPE_SOA, name);
- if (!soa)
- return -ENOMEM;
-
- soa->ttl = ttl;
-
- soa->soa.mname = strdup(name);
- if (!soa->soa.mname)
- return -ENOMEM;
-
- soa->soa.rname = strappend("root.", name);
- if (!soa->soa.rname)
- return -ENOMEM;
-
- soa->soa.serial = 1;
- soa->soa.refresh = 1;
- soa->soa.retry = 1;
- soa->soa.expire = 1;
- soa->soa.minimum = ttl;
-
- return dns_answer_add(a, soa);
-}
-
-int dns_answer_contains(DnsAnswer *a, DnsResourceKey *key) {
- unsigned i;
- int r;
-
- assert(a);
- assert(key);
-
- for (i = 0; i < a->n_rrs; i++) {
- r = dns_resource_key_match_rr(key, a->rrs[i]);
- if (r < 0)
- return r;
- if (r > 0)
- return 1;
- }
-
- return 0;
-}
-
-int dns_answer_find_soa(DnsAnswer *a, DnsResourceKey *key, DnsResourceRecord **ret) {
- unsigned i;
-
- assert(a);
- assert(key);
- assert(ret);
-
- /* For a SOA record we can never find a matching SOA record */
- if (key->type == DNS_TYPE_SOA)
- return 0;
-
- for (i = 0; i < a->n_rrs; i++) {
-
- if (a->rrs[i]->key->class != DNS_CLASS_IN)
- continue;
-
- if (a->rrs[i]->key->type != DNS_TYPE_SOA)
- continue;
-
- if (dns_name_endswith(DNS_RESOURCE_KEY_NAME(key), DNS_RESOURCE_KEY_NAME(a->rrs[i]->key))) {
- *ret = a->rrs[i];
- return 1;
- }
- }
-
- return 0;
-}
-
-DnsAnswer *dns_answer_merge(DnsAnswer *a, DnsAnswer *b) {
- _cleanup_(dns_answer_unrefp) DnsAnswer *ret = NULL;
- DnsAnswer *k;
- unsigned i;
- int r;
-
- if (a && (!b || b->n_rrs <= 0))
- return dns_answer_ref(a);
- if ((!a || a->n_rrs <= 0) && b)
- return dns_answer_ref(b);
-
- ret = dns_answer_new((a ? a->n_rrs : 0) + (b ? b->n_rrs : 0));
- if (!ret)
- return NULL;
-
- if (a) {
- for (i = 0; i < a->n_rrs; i++) {
- r = dns_answer_add(ret, a->rrs[i]);
- if (r < 0)
- return NULL;
- }
- }
-
- if (b) {
- for (i = 0; i < b->n_rrs; i++) {
- r = dns_answer_add(ret, b->rrs[i]);
- if (r < 0)
- return NULL;
- }
- }
-
- k = ret;
- ret = NULL;
-
- return k;
-}
-
-void dns_answer_order_by_scope(DnsAnswer *a, bool prefer_link_local) {
- DnsResourceRecord **rrs;
- unsigned i, start, end;
- assert(a);
-
- if (a->n_rrs <= 1)
- return;
-
- start = 0;
- end = a->n_rrs-1;
-
- /* RFC 4795, Section 2.6 suggests we should order entries
- * depending on whether the sender is a link-local address. */
-
- rrs = newa(DnsResourceRecord*, a->n_rrs);
- for (i = 0; i < a->n_rrs; i++) {
-
- if (a->rrs[i]->key->class == DNS_CLASS_IN &&
- ((a->rrs[i]->key->type == DNS_TYPE_A && in_addr_is_link_local(AF_INET, (union in_addr_union*) &a->rrs[i]->a.in_addr) != prefer_link_local) ||
- (a->rrs[i]->key->type == DNS_TYPE_AAAA && in_addr_is_link_local(AF_INET6, (union in_addr_union*) &a->rrs[i]->aaaa.in6_addr) != prefer_link_local)))
- /* Order address records that are are not preferred to the end of the array */
- rrs[end--] = a->rrs[i];
- else
- /* Order all other records to the beginning of the array */
- rrs[start++] = a->rrs[i];
- }
-
- assert(start == end+1);
- memcpy(a->rrs, rrs, sizeof(DnsResourceRecord*) * a->n_rrs);
-}
diff --git a/src/resolve/resolved-dns-answer.h b/src/resolve/resolved-dns-answer.h
deleted file mode 100644
index af3e462ed5..0000000000
--- a/src/resolve/resolved-dns-answer.h
+++ /dev/null
@@ -1,48 +0,0 @@
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
-#pragma once
-
-/***
- This file is part of systemd.
-
- Copyright 2014 Lennart Poettering
-
- systemd is free software; you can redistribute it and/or modify it
- under the terms of the GNU Lesser General Public License as published by
- the Free Software Foundation; either version 2.1 of the License, or
- (at your option) any later version.
-
- systemd is distributed in the hope that it will be useful, but
- WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Lesser General Public License for more details.
-
- You should have received a copy of the GNU Lesser General Public License
- along with systemd; If not, see <http://www.gnu.org/licenses/>.
-***/
-
-typedef struct DnsAnswer DnsAnswer;
-
-#include "resolved-dns-rr.h"
-
-/* A simple array of resource records */
-
-struct DnsAnswer {
- unsigned n_ref;
- unsigned n_rrs, n_allocated;
- DnsResourceRecord* rrs[0];
-};
-
-DnsAnswer *dns_answer_new(unsigned n);
-DnsAnswer *dns_answer_ref(DnsAnswer *a);
-DnsAnswer *dns_answer_unref(DnsAnswer *a);
-
-int dns_answer_add(DnsAnswer *a, DnsResourceRecord *rr);
-int dns_answer_add_soa(DnsAnswer *a, const char *name, uint32_t ttl);
-int dns_answer_contains(DnsAnswer *a, DnsResourceKey *key);
-int dns_answer_find_soa(DnsAnswer *a, DnsResourceKey *key, DnsResourceRecord **ret);
-
-DnsAnswer *dns_answer_merge(DnsAnswer *a, DnsAnswer *b);
-void dns_answer_order_by_scope(DnsAnswer *a, bool prefer_link_local);
-
-DEFINE_TRIVIAL_CLEANUP_FUNC(DnsAnswer*, dns_answer_unref);
diff --git a/src/resolve/resolved-dns-cache.c b/src/resolve/resolved-dns-cache.c
deleted file mode 100644
index 33ca4d1a45..0000000000
--- a/src/resolve/resolved-dns-cache.c
+++ /dev/null
@@ -1,564 +0,0 @@
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
-/***
- This file is part of systemd.
-
- Copyright 2014 Lennart Poettering
-
- systemd is free software; you can redistribute it and/or modify it
- under the terms of the GNU Lesser General Public License as published by
- the Free Software Foundation; either version 2.1 of the License, or
- (at your option) any later version.
-
- systemd is distributed in the hope that it will be useful, but
- WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Lesser General Public License for more details.
-
- You should have received a copy of the GNU Lesser General Public License
- along with systemd; If not, see <http://www.gnu.org/licenses/>.
-***/
-
-#include "resolved-dns-cache.h"
-#include "resolved-dns-packet.h"
-
-/* Never cache more than 1K entries */
-#define CACHE_MAX 1024
-
-/* We never keep any item longer than 10min in our cache */
-#define CACHE_TTL_MAX_USEC (10 * USEC_PER_MINUTE)
-
-typedef enum DnsCacheItemType DnsCacheItemType;
-typedef struct DnsCacheItem DnsCacheItem;
-
-enum DnsCacheItemType {
- DNS_CACHE_POSITIVE,
- DNS_CACHE_NODATA,
- DNS_CACHE_NXDOMAIN,
-};
-
-struct DnsCacheItem {
- DnsResourceKey *key;
- DnsResourceRecord *rr;
- usec_t until;
- DnsCacheItemType type;
- unsigned prioq_idx;
- int owner_family;
- union in_addr_union owner_address;
- LIST_FIELDS(DnsCacheItem, by_key);
-};
-
-static void dns_cache_item_free(DnsCacheItem *i) {
- if (!i)
- return;
-
- dns_resource_record_unref(i->rr);
- dns_resource_key_unref(i->key);
- free(i);
-}
-
-DEFINE_TRIVIAL_CLEANUP_FUNC(DnsCacheItem*, dns_cache_item_free);
-
-static void dns_cache_item_remove_and_free(DnsCache *c, DnsCacheItem *i) {
- DnsCacheItem *first;
-
- assert(c);
-
- if (!i)
- return;
-
- first = hashmap_get(c->by_key, i->key);
- LIST_REMOVE(by_key, first, i);
-
- if (first)
- assert_se(hashmap_replace(c->by_key, first->key, first) >= 0);
- else
- hashmap_remove(c->by_key, i->key);
-
- prioq_remove(c->by_expiry, i, &i->prioq_idx);
-
- dns_cache_item_free(i);
-}
-
-void dns_cache_flush(DnsCache *c) {
- DnsCacheItem *i;
-
- assert(c);
-
- while ((i = hashmap_first(c->by_key)))
- dns_cache_item_remove_and_free(c, i);
-
- assert(hashmap_size(c->by_key) == 0);
- assert(prioq_size(c->by_expiry) == 0);
-
- hashmap_free(c->by_key);
- c->by_key = NULL;
-
- prioq_free(c->by_expiry);
- c->by_expiry = NULL;
-}
-
-static void dns_cache_remove(DnsCache *c, DnsResourceKey *key) {
- DnsCacheItem *i;
-
- assert(c);
- assert(key);
-
- while ((i = hashmap_get(c->by_key, key)))
- dns_cache_item_remove_and_free(c, i);
-}
-
-static void dns_cache_make_space(DnsCache *c, unsigned add) {
- assert(c);
-
- if (add <= 0)
- return;
-
- /* Makes space for n new entries. Note that we actually allow
- * the cache to grow beyond CACHE_MAX, but only when we shall
- * add more RRs to the cache than CACHE_MAX at once. In that
- * case the cache will be emptied completely otherwise. */
-
- for (;;) {
- _cleanup_(dns_resource_key_unrefp) DnsResourceKey *key = NULL;
- DnsCacheItem *i;
-
- if (prioq_size(c->by_expiry) <= 0)
- break;
-
- if (prioq_size(c->by_expiry) + add < CACHE_MAX)
- break;
-
- i = prioq_peek(c->by_expiry);
- assert(i);
-
- /* Take an extra reference to the key so that it
- * doesn't go away in the middle of the remove call */
- key = dns_resource_key_ref(i->key);
- dns_cache_remove(c, key);
- }
-}
-
-void dns_cache_prune(DnsCache *c) {
- usec_t t = 0;
-
- assert(c);
-
- /* Remove all entries that are past their TTL */
-
- for (;;) {
- _cleanup_(dns_resource_key_unrefp) DnsResourceKey *key = NULL;
- DnsCacheItem *i;
-
- i = prioq_peek(c->by_expiry);
- if (!i)
- break;
-
- if (t <= 0)
- t = now(CLOCK_BOOTTIME);
-
- if (i->until > t)
- break;
-
- /* Take an extra reference to the key so that it
- * doesn't go away in the middle of the remove call */
- key = dns_resource_key_ref(i->key);
- dns_cache_remove(c, key);
- }
-}
-
-static int dns_cache_item_prioq_compare_func(const void *a, const void *b) {
- const DnsCacheItem *x = a, *y = b;
-
- if (x->until < y->until)
- return -1;
- if (x->until > y->until)
- return 1;
- return 0;
-}
-
-static int dns_cache_init(DnsCache *c) {
- int r;
-
- assert(c);
-
- r = prioq_ensure_allocated(&c->by_expiry, dns_cache_item_prioq_compare_func);
- if (r < 0)
- return r;
-
- r = hashmap_ensure_allocated(&c->by_key, &dns_resource_key_hash_ops);
- if (r < 0)
- return r;
-
- return r;
-}
-
-static int dns_cache_link_item(DnsCache *c, DnsCacheItem *i) {
- DnsCacheItem *first;
- int r;
-
- assert(c);
- assert(i);
-
- r = prioq_put(c->by_expiry, i, &i->prioq_idx);
- if (r < 0)
- return r;
-
- first = hashmap_get(c->by_key, i->key);
- if (first) {
- LIST_PREPEND(by_key, first, i);
- assert_se(hashmap_replace(c->by_key, first->key, first) >= 0);
- } else {
- r = hashmap_put(c->by_key, i->key, i);
- if (r < 0) {
- prioq_remove(c->by_expiry, i, &i->prioq_idx);
- return r;
- }
- }
-
- return 0;
-}
-
-static DnsCacheItem* dns_cache_get(DnsCache *c, DnsResourceRecord *rr) {
- DnsCacheItem *i;
-
- assert(c);
- assert(rr);
-
- LIST_FOREACH(by_key, i, hashmap_get(c->by_key, rr->key))
- if (i->rr && dns_resource_record_equal(i->rr, rr) > 0)
- return i;
-
- return NULL;
-}
-
-static void dns_cache_item_update_positive(DnsCache *c, DnsCacheItem *i, DnsResourceRecord *rr, usec_t timestamp) {
- assert(c);
- assert(i);
- assert(rr);
-
- i->type = DNS_CACHE_POSITIVE;
-
- if (!i->by_key_prev) {
- /* We are the first item in the list, we need to
- * update the key used in the hashmap */
-
- assert_se(hashmap_replace(c->by_key, rr->key, i) >= 0);
- }
-
- dns_resource_record_ref(rr);
- dns_resource_record_unref(i->rr);
- i->rr = rr;
-
- dns_resource_key_unref(i->key);
- i->key = dns_resource_key_ref(rr->key);
-
- i->until = timestamp + MIN(rr->ttl * USEC_PER_SEC, CACHE_TTL_MAX_USEC);
-
- prioq_reshuffle(c->by_expiry, i, &i->prioq_idx);
-}
-
-static int dns_cache_put_positive(
- DnsCache *c,
- DnsResourceRecord *rr,
- usec_t timestamp,
- int owner_family,
- const union in_addr_union *owner_address) {
-
- _cleanup_(dns_cache_item_freep) DnsCacheItem *i = NULL;
- DnsCacheItem *existing;
- int r;
-
- assert(c);
- assert(rr);
- assert(owner_address);
-
- /* New TTL is 0? Delete the entry... */
- if (rr->ttl <= 0) {
- dns_cache_remove(c, rr->key);
- return 0;
- }
-
- if (rr->key->class == DNS_CLASS_ANY)
- return 0;
- if (rr->key->type == DNS_TYPE_ANY)
- return 0;
-
- /* Entry exists already? Update TTL and timestamp */
- existing = dns_cache_get(c, rr);
- if (existing) {
- dns_cache_item_update_positive(c, existing, rr, timestamp);
- return 0;
- }
-
- /* Otherwise, add the new RR */
- r = dns_cache_init(c);
- if (r < 0)
- return r;
-
- dns_cache_make_space(c, 1);
-
- i = new0(DnsCacheItem, 1);
- if (!i)
- return -ENOMEM;
-
- i->type = DNS_CACHE_POSITIVE;
- i->key = dns_resource_key_ref(rr->key);
- i->rr = dns_resource_record_ref(rr);
- i->until = timestamp + MIN(i->rr->ttl * USEC_PER_SEC, CACHE_TTL_MAX_USEC);
- i->prioq_idx = PRIOQ_IDX_NULL;
- i->owner_family = owner_family;
- i->owner_address = *owner_address;
-
- r = dns_cache_link_item(c, i);
- if (r < 0)
- return r;
-
- i = NULL;
- return 0;
-}
-
-static int dns_cache_put_negative(
- DnsCache *c,
- DnsResourceKey *key,
- int rcode,
- usec_t timestamp,
- uint32_t soa_ttl,
- int owner_family,
- const union in_addr_union *owner_address) {
-
- _cleanup_(dns_cache_item_freep) DnsCacheItem *i = NULL;
- int r;
-
- assert(c);
- assert(key);
- assert(owner_address);
-
- dns_cache_remove(c, key);
-
- if (key->class == DNS_CLASS_ANY)
- return 0;
- if (key->type == DNS_TYPE_ANY)
- return 0;
- if (soa_ttl <= 0)
- return 0;
-
- if (!IN_SET(rcode, DNS_RCODE_SUCCESS, DNS_RCODE_NXDOMAIN))
- return 0;
-
- r = dns_cache_init(c);
- if (r < 0)
- return r;
-
- dns_cache_make_space(c, 1);
-
- i = new0(DnsCacheItem, 1);
- if (!i)
- return -ENOMEM;
-
- i->type = rcode == DNS_RCODE_SUCCESS ? DNS_CACHE_NODATA : DNS_CACHE_NXDOMAIN;
- i->key = dns_resource_key_ref(key);
- i->until = timestamp + MIN(soa_ttl * USEC_PER_SEC, CACHE_TTL_MAX_USEC);
- i->prioq_idx = PRIOQ_IDX_NULL;
- i->owner_family = owner_family;
- i->owner_address = *owner_address;
-
- r = dns_cache_link_item(c, i);
- if (r < 0)
- return r;
-
- i = NULL;
- return 0;
-}
-
-int dns_cache_put(
- DnsCache *c,
- DnsQuestion *q,
- int rcode,
- DnsAnswer *answer,
- unsigned max_rrs,
- usec_t timestamp,
- int owner_family,
- const union in_addr_union *owner_address) {
-
- unsigned i;
- int r;
-
- assert(c);
- assert(q);
-
- /* First, delete all matching old RRs, so that we only keep
- * complete by_key in place. */
- for (i = 0; i < q->n_keys; i++)
- dns_cache_remove(c, q->keys[i]);
-
- if (!answer)
- return 0;
-
- for (i = 0; i < answer->n_rrs; i++)
- dns_cache_remove(c, answer->rrs[i]->key);
-
- /* We only care for positive replies and NXDOMAINs, on all
- * other replies we will simply flush the respective entries,
- * and that's it */
-
- if (!IN_SET(rcode, DNS_RCODE_SUCCESS, DNS_RCODE_NXDOMAIN))
- return 0;
-
- /* Make some space for our new entries */
- dns_cache_make_space(c, answer->n_rrs + q->n_keys);
-
- if (timestamp <= 0)
- timestamp = now(CLOCK_BOOTTIME);
-
- /* Second, add in positive entries for all contained RRs */
- for (i = 0; i < MIN(max_rrs, answer->n_rrs); i++) {
- r = dns_cache_put_positive(c, answer->rrs[i], timestamp, owner_family, owner_address);
- if (r < 0)
- goto fail;
- }
-
- /* Third, add in negative entries for all keys with no RR */
- for (i = 0; i < q->n_keys; i++) {
- DnsResourceRecord *soa = NULL;
-
- r = dns_answer_contains(answer, q->keys[i]);
- if (r < 0)
- goto fail;
- if (r > 0)
- continue;
-
- r = dns_answer_find_soa(answer, q->keys[i], &soa);
- if (r < 0)
- goto fail;
- if (r == 0)
- continue;
-
- r = dns_cache_put_negative(c, q->keys[i], rcode, timestamp, MIN(soa->soa.minimum, soa->ttl), owner_family, owner_address);
- if (r < 0)
- goto fail;
- }
-
- return 0;
-
-fail:
- /* Adding all RRs failed. Let's clean up what we already
- * added, just in case */
-
- for (i = 0; i < q->n_keys; i++)
- dns_cache_remove(c, q->keys[i]);
- for (i = 0; i < answer->n_rrs; i++)
- dns_cache_remove(c, answer->rrs[i]->key);
-
- return r;
-}
-
-int dns_cache_lookup(DnsCache *c, DnsQuestion *q, int *rcode, DnsAnswer **ret) {
- _cleanup_(dns_answer_unrefp) DnsAnswer *answer = NULL;
- unsigned i, n = 0;
- int r;
- bool nxdomain = false;
-
- assert(c);
- assert(q);
- assert(rcode);
- assert(ret);
-
- if (q->n_keys <= 0) {
- *ret = NULL;
- *rcode = 0;
- return 0;
- }
-
- for (i = 0; i < q->n_keys; i++) {
- DnsCacheItem *j;
-
- if (q->keys[i]->type == DNS_TYPE_ANY ||
- q->keys[i]->class == DNS_CLASS_ANY) {
- /* If we have ANY lookups we simply refresh */
- *ret = NULL;
- *rcode = 0;
- return 0;
- }
-
- j = hashmap_get(c->by_key, q->keys[i]);
- if (!j) {
- /* If one question cannot be answered we need to refresh */
- *ret = NULL;
- *rcode = 0;
- return 0;
- }
-
- LIST_FOREACH(by_key, j, j) {
- if (j->rr)
- n++;
- else if (j->type == DNS_CACHE_NXDOMAIN)
- nxdomain = true;
- }
- }
-
- if (n <= 0) {
- *ret = NULL;
- *rcode = nxdomain ? DNS_RCODE_NXDOMAIN : DNS_RCODE_SUCCESS;
- return 1;
- }
-
- answer = dns_answer_new(n);
- if (!answer)
- return -ENOMEM;
-
- for (i = 0; i < q->n_keys; i++) {
- DnsCacheItem *j;
-
- j = hashmap_get(c->by_key, q->keys[i]);
- LIST_FOREACH(by_key, j, j) {
- if (j->rr) {
- r = dns_answer_add(answer, j->rr);
- if (r < 0)
- return r;
- }
- }
- }
-
- *ret = answer;
- *rcode = DNS_RCODE_SUCCESS;
- answer = NULL;
-
- return n;
-}
-
-int dns_cache_check_conflicts(DnsCache *cache, DnsResourceRecord *rr, int owner_family, const union in_addr_union *owner_address) {
- DnsCacheItem *i, *first;
- bool same_owner = true;
-
- assert(cache);
- assert(rr);
-
- dns_cache_prune(cache);
-
- /* See if there's a cache entry for the same key. If there
- * isn't there's no conflict */
- first = hashmap_get(cache->by_key, rr->key);
- if (!first)
- return 0;
-
- /* See if the RR key is owned by the same owner, if so, there
- * isn't a conflict either */
- LIST_FOREACH(by_key, i, first) {
- if (i->owner_family != owner_family ||
- !in_addr_equal(owner_family, &i->owner_address, owner_address)) {
- same_owner = false;
- break;
- }
- }
- if (same_owner)
- return 0;
-
- /* See if there's the exact same RR in the cache. If yes, then
- * there's no conflict. */
- if (dns_cache_get(cache, rr))
- return 0;
-
- /* There's a conflict */
- return 1;
-}
diff --git a/src/resolve/resolved-dns-cache.h b/src/resolve/resolved-dns-cache.h
deleted file mode 100644
index 8a9b3d459d..0000000000
--- a/src/resolve/resolved-dns-cache.h
+++ /dev/null
@@ -1,45 +0,0 @@
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
-#pragma once
-
-/***
- This file is part of systemd.
-
- Copyright 2014 Lennart Poettering
-
- systemd is free software; you can redistribute it and/or modify it
- under the terms of the GNU Lesser General Public License as published by
- the Free Software Foundation; either version 2.1 of the License, or
- (at your option) any later version.
-
- systemd is distributed in the hope that it will be useful, but
- WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Lesser General Public License for more details.
-
- You should have received a copy of the GNU Lesser General Public License
- along with systemd; If not, see <http://www.gnu.org/licenses/>.
-***/
-
-
-#include "hashmap.h"
-#include "prioq.h"
-#include "time-util.h"
-#include "list.h"
-
-typedef struct DnsCache {
- Hashmap *by_key;
- Prioq *by_expiry;
-} DnsCache;
-
-#include "resolved-dns-rr.h"
-#include "resolved-dns-question.h"
-#include "resolved-dns-answer.h"
-
-void dns_cache_flush(DnsCache *c);
-void dns_cache_prune(DnsCache *c);
-
-int dns_cache_put(DnsCache *c, DnsQuestion *q, int rcode, DnsAnswer *answer, unsigned max_rrs, usec_t timestamp, int owner_family, const union in_addr_union *owner_address);
-int dns_cache_lookup(DnsCache *c, DnsQuestion *q, int *rcode, DnsAnswer **answer);
-
-int dns_cache_check_conflicts(DnsCache *cache, DnsResourceRecord *rr, int owner_family, const union in_addr_union *owner_address);
diff --git a/src/resolve/resolved-dns-domain.c b/src/resolve/resolved-dns-domain.c
deleted file mode 100644
index e1eb3ddfe5..0000000000
--- a/src/resolve/resolved-dns-domain.c
+++ /dev/null
@@ -1,613 +0,0 @@
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
-/***
- This file is part of systemd.
-
- Copyright 2014 Lennart Poettering
-
- systemd is free software; you can redistribute it and/or modify it
- under the terms of the GNU Lesser General Public License as published by
- the Free Software Foundation; either version 2.1 of the License, or
- (at your option) any later version.
-
- systemd is distributed in the hope that it will be useful, but
- WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Lesser General Public License for more details.
-
- You should have received a copy of the GNU Lesser General Public License
- along with systemd; If not, see <http://www.gnu.org/licenses/>.
- ***/
-
-#ifdef HAVE_LIBIDN
-#include <idna.h>
-#include <stringprep.h>
-#endif
-
-#include "resolved-dns-domain.h"
-
-int dns_label_unescape(const char **name, char *dest, size_t sz) {
- const char *n;
- char *d;
- int r = 0;
-
- assert(name);
- assert(*name);
- assert(dest);
-
- n = *name;
- d = dest;
-
- for (;;) {
- if (*n == '.') {
- n++;
- break;
- }
-
- if (*n == 0)
- break;
-
- if (sz <= 0)
- return -ENOSPC;
-
- if (r >= DNS_LABEL_MAX)
- return -EINVAL;
-
- if (*n == '\\') {
- /* Escaped character */
-
- n++;
-
- if (*n == 0)
- /* Ending NUL */
- return -EINVAL;
-
- else if (*n == '\\' || *n == '.') {
- /* Escaped backslash or dot */
- *(d++) = *(n++);
- sz--;
- r++;
-
- } else if (n[0] >= '0' && n[0] <= '9') {
- unsigned k;
-
- /* Escaped literal ASCII character */
-
- if (!(n[1] >= '0' && n[1] <= '9') ||
- !(n[2] >= '0' && n[2] <= '9'))
- return -EINVAL;
-
- k = ((unsigned) (n[0] - '0') * 100) +
- ((unsigned) (n[1] - '0') * 10) +
- ((unsigned) (n[2] - '0'));
-
- /* Don't allow CC characters or anything that doesn't fit in 8bit */
- if (k < ' ' || k > 255 || k == 127)
- return -EINVAL;
-
- *(d++) = (char) k;
- sz--;
- r++;
-
- n += 3;
- } else
- return -EINVAL;
-
- } else if ((uint8_t) *n >= (uint8_t) ' ' && *n != 127) {
-
- /* Normal character */
- *(d++) = *(n++);
- sz--;
- r++;
- } else
- return -EINVAL;
- }
-
- /* Empty label that is not at the end? */
- if (r == 0 && *n)
- return -EINVAL;
-
- if (sz >= 1)
- *d = 0;
-
- *name = n;
- return r;
-}
-
-int dns_label_escape(const char *p, size_t l, char **ret) {
- _cleanup_free_ char *s = NULL;
- char *q;
- int r;
-
- assert(p);
- assert(ret);
-
- if (l > DNS_LABEL_MAX)
- return -EINVAL;
-
- s = malloc(l * 4 + 1);
- if (!s)
- return -ENOMEM;
-
- q = s;
- while (l > 0) {
-
- if (*p == '.' || *p == '\\') {
-
- /* Dot or backslash */
- *(q++) = '\\';
- *(q++) = *p;
-
- } else if (*p == '_' ||
- *p == '-' ||
- (*p >= '0' && *p <= '9') ||
- (*p >= 'a' && *p <= 'z') ||
- (*p >= 'A' && *p <= 'Z')) {
-
- /* Proper character */
- *(q++) = *p;
- } else if ((uint8_t) *p >= (uint8_t) ' ' && *p != 127) {
-
- /* Everything else */
- *(q++) = '\\';
- *(q++) = '0' + (char) ((uint8_t) *p / 100);
- *(q++) = '0' + (char) (((uint8_t) *p / 10) % 10);
- *(q++) = '0' + (char) ((uint8_t) *p % 10);
-
- } else
- return -EINVAL;
-
- p++;
- l--;
- }
-
- *q = 0;
- *ret = s;
- r = q - s;
- s = NULL;
-
- return r;
-}
-
-int dns_label_apply_idna(const char *encoded, size_t encoded_size, char *decoded, size_t decoded_max) {
-#ifdef HAVE_LIBIDN
- _cleanup_free_ uint32_t *input = NULL;
- size_t input_size;
- const char *p;
- bool contains_8bit = false;
-
- assert(encoded);
- assert(decoded);
- assert(decoded_max >= DNS_LABEL_MAX);
-
- if (encoded_size <= 0)
- return 0;
-
- for (p = encoded; p < encoded + encoded_size; p++)
- if ((uint8_t) *p > 127)
- contains_8bit = true;
-
- if (!contains_8bit)
- return 0;
-
- input = stringprep_utf8_to_ucs4(encoded, encoded_size, &input_size);
- if (!input)
- return -ENOMEM;
-
- if (idna_to_ascii_4i(input, input_size, decoded, 0) != 0)
- return -EINVAL;
-
- return strlen(decoded);
-#else
- return 0;
-#endif
-}
-
-int dns_label_undo_idna(const char *encoded, size_t encoded_size, char *decoded, size_t decoded_max) {
-#ifdef HAVE_LIBIDN
- size_t input_size, output_size;
- _cleanup_free_ uint32_t *input = NULL;
- _cleanup_free_ char *result = NULL;
- uint32_t *output = NULL;
- size_t w;
-
- /* To be invoked after unescaping */
-
- assert(encoded);
- assert(decoded);
-
- if (encoded_size < sizeof(IDNA_ACE_PREFIX)-1)
- return 0;
-
- if (memcmp(encoded, IDNA_ACE_PREFIX, sizeof(IDNA_ACE_PREFIX) -1) != 0)
- return 0;
-
- input = stringprep_utf8_to_ucs4(encoded, encoded_size, &input_size);
- if (!input)
- return -ENOMEM;
-
- output_size = input_size;
- output = newa(uint32_t, output_size);
-
- idna_to_unicode_44i(input, input_size, output, &output_size, 0);
-
- result = stringprep_ucs4_to_utf8(output, output_size, NULL, &w);
- if (!result)
- return -ENOMEM;
- if (w <= 0)
- return 0;
- if (w+1 > decoded_max)
- return -EINVAL;
-
- memcpy(decoded, result, w+1);
- return w;
-#else
- return 0;
-#endif
-}
-
-int dns_name_normalize(const char *s, char **_ret) {
- _cleanup_free_ char *ret = NULL;
- size_t n = 0, allocated = 0;
- const char *p = s;
- bool first = true;
- int r;
-
- assert(s);
-
- for (;;) {
- _cleanup_free_ char *t = NULL;
- char label[DNS_LABEL_MAX];
- int k;
-
- r = dns_label_unescape(&p, label, sizeof(label));
- if (r < 0)
- return r;
- if (r == 0) {
- if (*p != 0)
- return -EINVAL;
- break;
- }
-
- k = dns_label_undo_idna(label, r, label, sizeof(label));
- if (k < 0)
- return k;
- if (k > 0)
- r = k;
-
- r = dns_label_escape(label, r, &t);
- if (r < 0)
- return r;
-
- if (!GREEDY_REALLOC(ret, allocated, n + !first + strlen(t) + 1))
- return -ENOMEM;
-
- if (!first)
- ret[n++] = '.';
- else
- first = false;
-
- memcpy(ret + n, t, r);
- n += r;
- }
-
- if (n > DNS_NAME_MAX)
- return -EINVAL;
-
- if (!GREEDY_REALLOC(ret, allocated, n + 1))
- return -ENOMEM;
-
- ret[n] = 0;
-
- if (_ret) {
- *_ret = ret;
- ret = NULL;
- }
-
- return 0;
-}
-
-unsigned long dns_name_hash_func(const void *s, const uint8_t hash_key[HASH_KEY_SIZE]) {
- const char *p = s;
- unsigned long ul = hash_key[0];
- int r;
-
- assert(p);
-
- while (*p) {
- char label[DNS_LABEL_MAX+1];
- int k;
-
- r = dns_label_unescape(&p, label, sizeof(label));
- if (r < 0)
- break;
-
- k = dns_label_undo_idna(label, r, label, sizeof(label));
- if (k < 0)
- break;
- if (k > 0)
- r = k;
-
- label[r] = 0;
- ascii_strlower(label);
-
- ul = ul * hash_key[1] + ul + string_hash_func(label, hash_key);
- }
-
- return ul;
-}
-
-int dns_name_compare_func(const void *a, const void *b) {
- const char *x = a, *y = b;
- int r, q, k, w;
-
- assert(a);
- assert(b);
-
- for (;;) {
- char la[DNS_LABEL_MAX+1], lb[DNS_LABEL_MAX+1];
-
- if (*x == 0 && *y == 0)
- return 0;
-
- r = dns_label_unescape(&x, la, sizeof(la));
- q = dns_label_unescape(&y, lb, sizeof(lb));
- if (r < 0 || q < 0)
- return r - q;
-
- k = dns_label_undo_idna(la, r, la, sizeof(la));
- w = dns_label_undo_idna(lb, q, lb, sizeof(lb));
- if (k < 0 || w < 0)
- return k - w;
- if (k > 0)
- r = k;
- if (w > 0)
- r = w;
-
- la[r] = lb[q] = 0;
- r = strcasecmp(la, lb);
- if (r != 0)
- return r;
- }
-}
-
-const struct hash_ops dns_name_hash_ops = {
- .hash = dns_name_hash_func,
- .compare = dns_name_compare_func
-};
-
-int dns_name_equal(const char *x, const char *y) {
- int r, q, k, w;
-
- assert(x);
- assert(y);
-
- for (;;) {
- char la[DNS_LABEL_MAX+1], lb[DNS_LABEL_MAX+1];
-
- if (*x == 0 && *y == 0)
- return true;
-
- r = dns_label_unescape(&x, la, sizeof(la));
- if (r < 0)
- return r;
-
- k = dns_label_undo_idna(la, r, la, sizeof(la));
- if (k < 0)
- return k;
- if (k > 0)
- r = k;
-
- q = dns_label_unescape(&y, lb, sizeof(lb));
- if (q < 0)
- return q;
- w = dns_label_undo_idna(lb, q, lb, sizeof(lb));
- if (w < 0)
- return w;
- if (w > 0)
- q = w;
-
- la[r] = lb[q] = 0;
- if (strcasecmp(la, lb))
- return false;
- }
-}
-
-int dns_name_endswith(const char *name, const char *suffix) {
- const char *n, *s, *saved_n = NULL;
- int r, q, k, w;
-
- assert(name);
- assert(suffix);
-
- n = name;
- s = suffix;
-
- for (;;) {
- char ln[DNS_LABEL_MAX+1], ls[DNS_LABEL_MAX+1];
-
- r = dns_label_unescape(&n, ln, sizeof(ln));
- if (r < 0)
- return r;
- k = dns_label_undo_idna(ln, r, ln, sizeof(ln));
- if (k < 0)
- return k;
- if (k > 0)
- r = k;
-
- if (!saved_n)
- saved_n = n;
-
- q = dns_label_unescape(&s, ls, sizeof(ls));
- if (q < 0)
- return q;
- w = dns_label_undo_idna(ls, q, ls, sizeof(ls));
- if (w < 0)
- return w;
- if (w > 0)
- q = w;
-
- if (r == 0 && q == 0)
- return true;
- if (r == 0 && saved_n == n)
- return false;
-
- ln[r] = ls[q] = 0;
-
- if (r != q || strcasecmp(ln, ls)) {
-
- /* Not the same, let's jump back, and try with the next label again */
- s = suffix;
- n = saved_n;
- saved_n = NULL;
- }
- }
-}
-
-int dns_name_reverse(int family, const union in_addr_union *a, char **ret) {
- const uint8_t *p;
- int r;
-
- assert(a);
- assert(ret);
-
- p = (const uint8_t*) a;
-
- if (family == AF_INET)
- r = asprintf(ret, "%u.%u.%u.%u.in-addr.arpa", p[3], p[2], p[1], p[0]);
- else if (family == AF_INET6)
- r = asprintf(ret, "%c.%c.%c.%c.%c.%c.%c.%c.%c.%c.%c.%c.%c.%c.%c.%c.%c.%c.%c.%c.%c.%c.%c.%c.%c.%c.%c.%c.%c.%c.%c.%c.ip6.arpa",
- hexchar(p[15] & 0xF), hexchar(p[15] >> 4), hexchar(p[14] & 0xF), hexchar(p[14] >> 4),
- hexchar(p[13] & 0xF), hexchar(p[13] >> 4), hexchar(p[12] & 0xF), hexchar(p[12] >> 4),
- hexchar(p[11] & 0xF), hexchar(p[11] >> 4), hexchar(p[10] & 0xF), hexchar(p[10] >> 4),
- hexchar(p[ 9] & 0xF), hexchar(p[ 9] >> 4), hexchar(p[ 8] & 0xF), hexchar(p[ 8] >> 4),
- hexchar(p[ 7] & 0xF), hexchar(p[ 7] >> 4), hexchar(p[ 6] & 0xF), hexchar(p[ 6] >> 4),
- hexchar(p[ 5] & 0xF), hexchar(p[ 5] >> 4), hexchar(p[ 4] & 0xF), hexchar(p[ 4] >> 4),
- hexchar(p[ 3] & 0xF), hexchar(p[ 3] >> 4), hexchar(p[ 2] & 0xF), hexchar(p[ 2] >> 4),
- hexchar(p[ 1] & 0xF), hexchar(p[ 1] >> 4), hexchar(p[ 0] & 0xF), hexchar(p[ 0] >> 4));
- else
- return -EAFNOSUPPORT;
- if (r < 0)
- return -ENOMEM;
-
- return 0;
-}
-
-int dns_name_address(const char *p, int *family, union in_addr_union *address) {
- int r;
-
- assert(p);
- assert(family);
- assert(address);
-
- r = dns_name_endswith(p, "in-addr.arpa");
- if (r < 0)
- return r;
- if (r > 0) {
- uint8_t a[4];
- unsigned i;
-
- for (i = 0; i < ELEMENTSOF(a); i++) {
- char label[DNS_LABEL_MAX+1];
-
- r = dns_label_unescape(&p, label, sizeof(label));
- if (r < 0)
- return r;
- if (r == 0)
- return -EINVAL;
- if (r > 3)
- return -EINVAL;
-
- r = safe_atou8(label, &a[i]);
- if (r < 0)
- return r;
- }
-
- r = dns_name_equal(p, "in-addr.arpa");
- if (r <= 0)
- return r;
-
- *family = AF_INET;
- address->in.s_addr = htobe32(((uint32_t) a[3] << 24) |
- ((uint32_t) a[2] << 16) |
- ((uint32_t) a[1] << 8) |
- (uint32_t) a[0]);
-
- return 1;
- }
-
- r = dns_name_endswith(p, "ip6.arpa");
- if (r < 0)
- return r;
- if (r > 0) {
- struct in6_addr a;
- unsigned i;
-
- for (i = 0; i < ELEMENTSOF(a.s6_addr); i++) {
- char label[DNS_LABEL_MAX+1];
- int x, y;
-
- r = dns_label_unescape(&p, label, sizeof(label));
- if (r <= 0)
- return r;
- if (r != 1)
- return -EINVAL;
- x = unhexchar(label[0]);
- if (x < 0)
- return -EINVAL;
-
- r = dns_label_unescape(&p, label, sizeof(label));
- if (r <= 0)
- return r;
- if (r != 1)
- return -EINVAL;
- y = unhexchar(label[0]);
- if (y < 0)
- return -EINVAL;
-
- a.s6_addr[ELEMENTSOF(a.s6_addr) - i - 1] = (uint8_t) y << 4 | (uint8_t) x;
- }
-
- r = dns_name_equal(p, "ip6.arpa");
- if (r <= 0)
- return r;
-
- *family = AF_INET6;
- address->in6 = a;
- return 1;
- }
-
- return 0;
-}
-
-int dns_name_root(const char *name) {
- char label[DNS_LABEL_MAX+1];
- int r;
-
- assert(name);
-
- r = dns_label_unescape(&name, label, sizeof(label));
- if (r < 0)
- return r;
-
- return r == 0 && *name == 0;
-}
-
-int dns_name_single_label(const char *name) {
- char label[DNS_LABEL_MAX+1];
- int r;
-
- assert(name);
-
- r = dns_label_unescape(&name, label, sizeof(label));
- if (r < 0)
- return r;
- if (r == 0)
- return 0;
-
- r = dns_label_unescape(&name, label, sizeof(label));
- if (r < 0)
- return r;
-
- return r == 0 && *name == 0;
-}
diff --git a/src/resolve/resolved-dns-domain.h b/src/resolve/resolved-dns-domain.h
deleted file mode 100644
index 516d244f7a..0000000000
--- a/src/resolve/resolved-dns-domain.h
+++ /dev/null
@@ -1,50 +0,0 @@
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
-/***
- This file is part of systemd.
-
- Copyright 2014 Lennart Poettering
-
- systemd is free software; you can redistribute it and/or modify it
- under the terms of the GNU Lesser General Public License as published by
- the Free Software Foundation; either version 2.1 of the License, or
- (at your option) any later version.
-
- systemd is distributed in the hope that it will be useful, but
- WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Lesser General Public License for more details.
-
- You should have received a copy of the GNU Lesser General Public License
- along with systemd; If not, see <http://www.gnu.org/licenses/>.
- ***/
-
-#pragma once
-
-
-#include "hashmap.h"
-#include "in-addr-util.h"
-
-#define DNS_LABEL_MAX 63
-#define DNS_NAME_MAX 255
-
-int dns_label_unescape(const char **name, char *dest, size_t sz);
-int dns_label_escape(const char *p, size_t l, char **ret);
-
-int dns_label_apply_idna(const char *encoded, size_t encoded_size, char *decoded, size_t decoded_max);
-int dns_label_undo_idna(const char *encoded, size_t encoded_size, char *decoded, size_t decoded_max);
-
-int dns_name_normalize(const char *s, char **_ret);
-
-unsigned long dns_name_hash_func(const void *s, const uint8_t hash_key[HASH_KEY_SIZE]);
-int dns_name_compare_func(const void *a, const void *b);
-extern const struct hash_ops dns_name_hash_ops;
-
-int dns_name_equal(const char *x, const char *y);
-int dns_name_endswith(const char *name, const char *suffix);
-
-int dns_name_reverse(int family, const union in_addr_union *a, char **ret);
-int dns_name_address(const char *p, int *family, union in_addr_union *a);
-
-int dns_name_root(const char *name);
-int dns_name_single_label(const char *name);
diff --git a/src/resolve/resolved-dns-packet.c b/src/resolve/resolved-dns-packet.c
deleted file mode 100644
index 21756f566f..0000000000
--- a/src/resolve/resolved-dns-packet.c
+++ /dev/null
@@ -1,1478 +0,0 @@
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
-/***
- This file is part of systemd.
-
- Copyright 2014 Lennart Poettering
-
- systemd is free software; you can redistribute it and/or modify it
- under the terms of the GNU Lesser General Public License as published by
- the Free Software Foundation; either version 2.1 of the License, or
- (at your option) any later version.
-
- systemd is distributed in the hope that it will be useful, but
- WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Lesser General Public License for more details.
-
- You should have received a copy of the GNU Lesser General Public License
- along with systemd; If not, see <http://www.gnu.org/licenses/>.
- ***/
-
-#include "utf8.h"
-#include "util.h"
-#include "strv.h"
-#include "unaligned.h"
-#include "resolved-dns-domain.h"
-#include "resolved-dns-packet.h"
-
-int dns_packet_new(DnsPacket **ret, DnsProtocol protocol, size_t mtu) {
- DnsPacket *p;
- size_t a;
-
- assert(ret);
-
- if (mtu <= 0)
- a = DNS_PACKET_SIZE_START;
- else
- a = mtu;
-
- if (a < DNS_PACKET_HEADER_SIZE)
- a = DNS_PACKET_HEADER_SIZE;
-
- /* round up to next page size */
- a = PAGE_ALIGN(ALIGN(sizeof(DnsPacket)) + a) - ALIGN(sizeof(DnsPacket));
-
- /* make sure we never allocate more than useful */
- if (a > DNS_PACKET_SIZE_MAX)
- a = DNS_PACKET_SIZE_MAX;
-
- p = malloc0(ALIGN(sizeof(DnsPacket)) + a);
- if (!p)
- return -ENOMEM;
-
- p->size = p->rindex = DNS_PACKET_HEADER_SIZE;
- p->allocated = a;
- p->protocol = protocol;
- p->n_ref = 1;
-
- *ret = p;
-
- return 0;
-}
-
-int dns_packet_new_query(DnsPacket **ret, DnsProtocol protocol, size_t mtu) {
- DnsPacket *p;
- DnsPacketHeader *h;
- int r;
-
- assert(ret);
-
- r = dns_packet_new(&p, protocol, mtu);
- if (r < 0)
- return r;
-
- h = DNS_PACKET_HEADER(p);
-
- if (protocol == DNS_PROTOCOL_LLMNR)
- h->flags = htobe16(DNS_PACKET_MAKE_FLAGS(0 /* qr */,
- 0 /* opcode */,
- 0 /* c */,
- 0 /* tc */,
- 0 /* t */,
- 0 /* ra */,
- 0 /* ad */,
- 0 /* cd */,
- 0 /* rcode */));
- else
- h->flags = htobe16(DNS_PACKET_MAKE_FLAGS(0 /* qr */,
- 0 /* opcode */,
- 0 /* aa */,
- 0 /* tc */,
- 1 /* rd (ask for recursion) */,
- 0 /* ra */,
- 0 /* ad */,
- 0 /* cd */,
- 0 /* rcode */));
-
- *ret = p;
- return 0;
-}
-
-DnsPacket *dns_packet_ref(DnsPacket *p) {
-
- if (!p)
- return NULL;
-
- assert(p->n_ref > 0);
- p->n_ref++;
- return p;
-}
-
-static void dns_packet_free(DnsPacket *p) {
- char *s;
-
- assert(p);
-
- dns_question_unref(p->question);
- dns_answer_unref(p->answer);
-
- while ((s = hashmap_steal_first_key(p->names)))
- free(s);
- hashmap_free(p->names);
-
- free(p->_data);
- free(p);
-}
-
-DnsPacket *dns_packet_unref(DnsPacket *p) {
- if (!p)
- return NULL;
-
- assert(p->n_ref > 0);
-
- if (p->n_ref == 1)
- dns_packet_free(p);
- else
- p->n_ref--;
-
- return NULL;
-}
-
-int dns_packet_validate(DnsPacket *p) {
- assert(p);
-
- if (p->size < DNS_PACKET_HEADER_SIZE)
- return -EBADMSG;
-
- if (p->size > DNS_PACKET_SIZE_MAX)
- return -EBADMSG;
-
- return 1;
-}
-
-int dns_packet_validate_reply(DnsPacket *p) {
- int r;
-
- assert(p);
-
- r = dns_packet_validate(p);
- if (r < 0)
- return r;
-
- if (DNS_PACKET_QR(p) != 1)
- return 0;
-
- if (DNS_PACKET_OPCODE(p) != 0)
- return -EBADMSG;
-
- /* RFC 4795, Section 2.1.1. says to discard all replies with QDCOUNT != 1 */
- if (p->protocol == DNS_PROTOCOL_LLMNR &&
- DNS_PACKET_QDCOUNT(p) != 1)
- return -EBADMSG;
-
- return 1;
-}
-
-int dns_packet_validate_query(DnsPacket *p) {
- int r;
-
- assert(p);
-
- r = dns_packet_validate(p);
- if (r < 0)
- return r;
-
- if (DNS_PACKET_QR(p) != 0)
- return 0;
-
- if (DNS_PACKET_OPCODE(p) != 0)
- return -EBADMSG;
-
- if (DNS_PACKET_TC(p))
- return -EBADMSG;
-
- /* RFC 4795, Section 2.1.1. says to discard all queries with QDCOUNT != 1 */
- if (p->protocol == DNS_PROTOCOL_LLMNR &&
- DNS_PACKET_QDCOUNT(p) != 1)
- return -EBADMSG;
-
- /* RFC 4795, Section 2.1.1. says to discard all queries with ANCOUNT != 0 */
- if (DNS_PACKET_ANCOUNT(p) > 0)
- return -EBADMSG;
-
- /* RFC 4795, Section 2.1.1. says to discard all queries with NSCOUNT != 0 */
- if (DNS_PACKET_NSCOUNT(p) > 0)
- return -EBADMSG;
-
- return 1;
-}
-
-static int dns_packet_extend(DnsPacket *p, size_t add, void **ret, size_t *start) {
- assert(p);
-
- if (p->size + add > p->allocated) {
- size_t a;
-
- a = PAGE_ALIGN((p->size + add) * 2);
- if (a > DNS_PACKET_SIZE_MAX)
- a = DNS_PACKET_SIZE_MAX;
-
- if (p->size + add > a)
- return -EMSGSIZE;
-
- if (p->_data) {
- void *d;
-
- d = realloc(p->_data, a);
- if (!d)
- return -ENOMEM;
-
- p->_data = d;
- } else {
- p->_data = malloc(a);
- if (!p->_data)
- return -ENOMEM;
-
- memcpy(p->_data, (uint8_t*) p + ALIGN(sizeof(DnsPacket)), p->size);
- memzero((uint8_t*) p->_data + p->size, a - p->size);
- }
-
- p->allocated = a;
- }
-
- if (start)
- *start = p->size;
-
- if (ret)
- *ret = (uint8_t*) DNS_PACKET_DATA(p) + p->size;
-
- p->size += add;
- return 0;
-}
-
-static void dns_packet_truncate(DnsPacket *p, size_t sz) {
- Iterator i;
- char *s;
- void *n;
-
- assert(p);
-
- if (p->size <= sz)
- return;
-
- HASHMAP_FOREACH_KEY(s, n, p->names, i) {
-
- if (PTR_TO_SIZE(n) < sz)
- continue;
-
- hashmap_remove(p->names, s);
- free(s);
- }
-
- p->size = sz;
-}
-
-int dns_packet_append_blob(DnsPacket *p, const void *d, size_t l, size_t *start) {
- void *q;
- int r;
-
- assert(p);
-
- r = dns_packet_extend(p, l, &q, start);
- if (r < 0)
- return r;
-
- memcpy(q, d, l);
- return 0;
-}
-
-int dns_packet_append_uint8(DnsPacket *p, uint8_t v, size_t *start) {
- void *d;
- int r;
-
- assert(p);
-
- r = dns_packet_extend(p, sizeof(uint8_t), &d, start);
- if (r < 0)
- return r;
-
- ((uint8_t*) d)[0] = v;
-
- return 0;
-}
-
-int dns_packet_append_uint16(DnsPacket *p, uint16_t v, size_t *start) {
- void *d;
- int r;
-
- assert(p);
-
- r = dns_packet_extend(p, sizeof(uint16_t), &d, start);
- if (r < 0)
- return r;
-
- unaligned_write_be16(d, v);
-
- return 0;
-}
-
-int dns_packet_append_uint32(DnsPacket *p, uint32_t v, size_t *start) {
- void *d;
- int r;
-
- assert(p);
-
- r = dns_packet_extend(p, sizeof(uint32_t), &d, start);
- if (r < 0)
- return r;
-
- unaligned_write_be32(d, v);
-
- return 0;
-}
-
-int dns_packet_append_string(DnsPacket *p, const char *s, size_t *start) {
- void *d;
- size_t l;
- int r;
-
- assert(p);
- assert(s);
-
- l = strlen(s);
- if (l > 255)
- return -E2BIG;
-
- r = dns_packet_extend(p, 1 + l, &d, start);
- if (r < 0)
- return r;
-
- ((uint8_t*) d)[0] = (uint8_t) l;
- memcpy(((uint8_t*) d) + 1, s, l);
-
- return 0;
-}
-
-int dns_packet_append_label(DnsPacket *p, const char *d, size_t l, size_t *start) {
- void *w;
- int r;
-
- assert(p);
- assert(d);
-
- if (l > DNS_LABEL_MAX)
- return -E2BIG;
-
- r = dns_packet_extend(p, 1 + l, &w, start);
- if (r < 0)
- return r;
-
- ((uint8_t*) w)[0] = (uint8_t) l;
- memcpy(((uint8_t*) w) + 1, d, l);
-
- return 0;
-}
-
-int dns_packet_append_name(DnsPacket *p, const char *name,
- bool allow_compression, size_t *start) {
- size_t saved_size;
- int r;
-
- assert(p);
- assert(name);
-
- saved_size = p->size;
-
- while (*name) {
- _cleanup_free_ char *s = NULL;
- char label[DNS_LABEL_MAX];
- size_t n = 0;
- int k;
-
- if (allow_compression)
- n = PTR_TO_SIZE(hashmap_get(p->names, name));
- if (n > 0) {
- assert(n < p->size);
-
- if (n < 0x4000) {
- r = dns_packet_append_uint16(p, 0xC000 | n, NULL);
- if (r < 0)
- goto fail;
-
- goto done;
- }
- }
-
- s = strdup(name);
- if (!s) {
- r = -ENOMEM;
- goto fail;
- }
-
- r = dns_label_unescape(&name, label, sizeof(label));
- if (r < 0)
- goto fail;
-
- if (p->protocol == DNS_PROTOCOL_DNS)
- k = dns_label_apply_idna(label, r, label, sizeof(label));
- else
- k = dns_label_undo_idna(label, r, label, sizeof(label));
- if (k < 0) {
- r = k;
- goto fail;
- }
- if (k > 0)
- r = k;
-
- r = dns_packet_append_label(p, label, r, &n);
- if (r < 0)
- goto fail;
-
- if (allow_compression) {
- r = hashmap_ensure_allocated(&p->names, &dns_name_hash_ops);
- if (r < 0)
- goto fail;
-
- r = hashmap_put(p->names, s, SIZE_TO_PTR(n));
- if (r < 0)
- goto fail;
-
- s = NULL;
- }
- }
-
- r = dns_packet_append_uint8(p, 0, NULL);
- if (r < 0)
- return r;
-
-done:
- if (start)
- *start = saved_size;
-
- return 0;
-
-fail:
- dns_packet_truncate(p, saved_size);
- return r;
-}
-
-int dns_packet_append_key(DnsPacket *p, const DnsResourceKey *k, size_t *start) {
- size_t saved_size;
- int r;
-
- assert(p);
- assert(k);
-
- saved_size = p->size;
-
- r = dns_packet_append_name(p, DNS_RESOURCE_KEY_NAME(k), true, NULL);
- if (r < 0)
- goto fail;
-
- r = dns_packet_append_uint16(p, k->type, NULL);
- if (r < 0)
- goto fail;
-
- r = dns_packet_append_uint16(p, k->class, NULL);
- if (r < 0)
- goto fail;
-
- if (start)
- *start = saved_size;
-
- return 0;
-
-fail:
- dns_packet_truncate(p, saved_size);
- return r;
-}
-
-int dns_packet_append_rr(DnsPacket *p, const DnsResourceRecord *rr, size_t *start) {
- size_t saved_size, rdlength_offset, end, rdlength;
- int r;
-
- assert(p);
- assert(rr);
-
- saved_size = p->size;
-
- r = dns_packet_append_key(p, rr->key, NULL);
- if (r < 0)
- goto fail;
-
- r = dns_packet_append_uint32(p, rr->ttl, NULL);
- if (r < 0)
- goto fail;
-
- /* Initially we write 0 here */
- r = dns_packet_append_uint16(p, 0, &rdlength_offset);
- if (r < 0)
- goto fail;
-
- switch (rr->unparseable ? _DNS_TYPE_INVALID : rr->key->type) {
-
- case DNS_TYPE_SRV:
- r = dns_packet_append_uint16(p, rr->srv.priority, NULL);
- if (r < 0)
- goto fail;
-
- r = dns_packet_append_uint16(p, rr->srv.weight, NULL);
- if (r < 0)
- goto fail;
-
- r = dns_packet_append_uint16(p, rr->srv.port, NULL);
- if (r < 0)
- goto fail;
-
- r = dns_packet_append_name(p, rr->srv.name, true, NULL);
- break;
-
- case DNS_TYPE_PTR:
- case DNS_TYPE_NS:
- case DNS_TYPE_CNAME:
- case DNS_TYPE_DNAME:
- r = dns_packet_append_name(p, rr->ptr.name, true, NULL);
- break;
-
- case DNS_TYPE_HINFO:
- r = dns_packet_append_string(p, rr->hinfo.cpu, NULL);
- if (r < 0)
- goto fail;
-
- r = dns_packet_append_string(p, rr->hinfo.os, NULL);
- break;
-
- case DNS_TYPE_SPF: /* exactly the same as TXT */
- case DNS_TYPE_TXT: {
- char **s;
-
- if (strv_isempty(rr->txt.strings)) {
- /* RFC 6763, section 6.1 suggests to generate
- * single empty string for an empty array. */
-
- r = dns_packet_append_string(p, "", NULL);
- if (r < 0)
- goto fail;
- } else {
- STRV_FOREACH(s, rr->txt.strings) {
- r = dns_packet_append_string(p, *s, NULL);
- if (r < 0)
- goto fail;
- }
- }
-
- r = 0;
- break;
- }
-
- case DNS_TYPE_A:
- r = dns_packet_append_blob(p, &rr->a.in_addr, sizeof(struct in_addr), NULL);
- break;
-
- case DNS_TYPE_AAAA:
- r = dns_packet_append_blob(p, &rr->aaaa.in6_addr, sizeof(struct in6_addr), NULL);
- break;
-
- case DNS_TYPE_SOA:
- r = dns_packet_append_name(p, rr->soa.mname, true, NULL);
- if (r < 0)
- goto fail;
-
- r = dns_packet_append_name(p, rr->soa.rname, true, NULL);
- if (r < 0)
- goto fail;
-
- r = dns_packet_append_uint32(p, rr->soa.serial, NULL);
- if (r < 0)
- goto fail;
-
- r = dns_packet_append_uint32(p, rr->soa.refresh, NULL);
- if (r < 0)
- goto fail;
-
- r = dns_packet_append_uint32(p, rr->soa.retry, NULL);
- if (r < 0)
- goto fail;
-
- r = dns_packet_append_uint32(p, rr->soa.expire, NULL);
- if (r < 0)
- goto fail;
-
- r = dns_packet_append_uint32(p, rr->soa.minimum, NULL);
- break;
-
- case DNS_TYPE_MX:
- r = dns_packet_append_uint16(p, rr->mx.priority, NULL);
- if (r < 0)
- goto fail;
-
- r = dns_packet_append_name(p, rr->mx.exchange, true, NULL);
- break;
-
- case DNS_TYPE_LOC:
- r = dns_packet_append_uint8(p, rr->loc.version, NULL);
- if (r < 0)
- goto fail;
-
- r = dns_packet_append_uint8(p, rr->loc.size, NULL);
- if (r < 0)
- goto fail;
-
- r = dns_packet_append_uint8(p, rr->loc.horiz_pre, NULL);
- if (r < 0)
- goto fail;
-
- r = dns_packet_append_uint8(p, rr->loc.vert_pre, NULL);
- if (r < 0)
- goto fail;
-
- r = dns_packet_append_uint32(p, rr->loc.latitude, NULL);
- if (r < 0)
- goto fail;
-
- r = dns_packet_append_uint32(p, rr->loc.longitude, NULL);
- if (r < 0)
- goto fail;
-
- r = dns_packet_append_uint32(p, rr->loc.altitude, NULL);
- break;
-
- case DNS_TYPE_SSHFP:
- r = dns_packet_append_uint8(p, rr->sshfp.algorithm, NULL);
- if (r < 0)
- goto fail;
-
- r = dns_packet_append_uint8(p, rr->sshfp.fptype, NULL);
- if (r < 0)
- goto fail;
-
- r = dns_packet_append_blob(p, rr->sshfp.key, rr->sshfp.key_size, NULL);
- break;
-
- case DNS_TYPE_DNSKEY:
- r = dns_packet_append_uint16(p, dnskey_to_flags(rr), NULL);
- if (r < 0)
- goto fail;
-
- r = dns_packet_append_uint8(p, 3u, NULL);
- if (r < 0)
- goto fail;
-
- r = dns_packet_append_uint8(p, rr->dnskey.algorithm, NULL);
- if (r < 0)
- goto fail;
-
- r = dns_packet_append_blob(p, rr->dnskey.key, rr->dnskey.key_size, NULL);
- break;
-
- case DNS_TYPE_RRSIG:
- r = dns_packet_append_uint16(p, rr->rrsig.type_covered, NULL);
- if (r < 0)
- goto fail;
-
- r = dns_packet_append_uint8(p, rr->rrsig.algorithm, NULL);
- if (r < 0)
- goto fail;
-
- r = dns_packet_append_uint8(p, rr->rrsig.labels, NULL);
- if (r < 0)
- goto fail;
-
- r = dns_packet_append_uint32(p, rr->rrsig.original_ttl, NULL);
- if (r < 0)
- goto fail;
-
- r = dns_packet_append_uint32(p, rr->rrsig.expiration, NULL);
- if (r < 0)
- goto fail;
-
- r = dns_packet_append_uint32(p, rr->rrsig.inception, NULL);
- if (r < 0)
- goto fail;
-
- r = dns_packet_append_uint8(p, rr->rrsig.key_tag, NULL);
- if (r < 0)
- goto fail;
-
- r = dns_packet_append_name(p, rr->rrsig.signer, false, NULL);
- if (r < 0)
- goto fail;
-
- r = dns_packet_append_blob(p, rr->rrsig.signature, rr->rrsig.signature_size, NULL);
- break;
-
- case _DNS_TYPE_INVALID: /* unparseable */
- default:
-
- r = dns_packet_append_blob(p, rr->generic.data, rr->generic.size, NULL);
- break;
- }
- if (r < 0)
- goto fail;
-
- /* Let's calculate the actual data size and update the field */
- rdlength = p->size - rdlength_offset - sizeof(uint16_t);
- if (rdlength > 0xFFFF) {
- r = ENOSPC;
- goto fail;
- }
-
- end = p->size;
- p->size = rdlength_offset;
- r = dns_packet_append_uint16(p, rdlength, NULL);
- if (r < 0)
- goto fail;
- p->size = end;
-
- if (start)
- *start = saved_size;
-
- return 0;
-
-fail:
- dns_packet_truncate(p, saved_size);
- return r;
-}
-
-
-int dns_packet_read(DnsPacket *p, size_t sz, const void **ret, size_t *start) {
- assert(p);
-
- if (p->rindex + sz > p->size)
- return -EMSGSIZE;
-
- if (ret)
- *ret = (uint8_t*) DNS_PACKET_DATA(p) + p->rindex;
-
- if (start)
- *start = p->rindex;
-
- p->rindex += sz;
- return 0;
-}
-
-void dns_packet_rewind(DnsPacket *p, size_t idx) {
- assert(p);
- assert(idx <= p->size);
- assert(idx >= DNS_PACKET_HEADER_SIZE);
-
- p->rindex = idx;
-}
-
-int dns_packet_read_blob(DnsPacket *p, void *d, size_t sz, size_t *start) {
- const void *q;
- int r;
-
- assert(p);
- assert(d);
-
- r = dns_packet_read(p, sz, &q, start);
- if (r < 0)
- return r;
-
- memcpy(d, q, sz);
- return 0;
-}
-
-int dns_packet_read_uint8(DnsPacket *p, uint8_t *ret, size_t *start) {
- const void *d;
- int r;
-
- assert(p);
-
- r = dns_packet_read(p, sizeof(uint8_t), &d, start);
- if (r < 0)
- return r;
-
- *ret = ((uint8_t*) d)[0];
- return 0;
-}
-
-int dns_packet_read_uint16(DnsPacket *p, uint16_t *ret, size_t *start) {
- const void *d;
- int r;
-
- assert(p);
-
- r = dns_packet_read(p, sizeof(uint16_t), &d, start);
- if (r < 0)
- return r;
-
- *ret = unaligned_read_be16(d);
-
- return 0;
-}
-
-int dns_packet_read_uint32(DnsPacket *p, uint32_t *ret, size_t *start) {
- const void *d;
- int r;
-
- assert(p);
-
- r = dns_packet_read(p, sizeof(uint32_t), &d, start);
- if (r < 0)
- return r;
-
- *ret = unaligned_read_be32(d);
-
- return 0;
-}
-
-int dns_packet_read_string(DnsPacket *p, char **ret, size_t *start) {
- size_t saved_rindex;
- const void *d;
- char *t;
- uint8_t c;
- int r;
-
- assert(p);
-
- saved_rindex = p->rindex;
-
- r = dns_packet_read_uint8(p, &c, NULL);
- if (r < 0)
- goto fail;
-
- r = dns_packet_read(p, c, &d, NULL);
- if (r < 0)
- goto fail;
-
- if (memchr(d, 0, c)) {
- r = -EBADMSG;
- goto fail;
- }
-
- t = strndup(d, c);
- if (!t) {
- r = -ENOMEM;
- goto fail;
- }
-
- if (!utf8_is_valid(t)) {
- free(t);
- r = -EBADMSG;
- goto fail;
- }
-
- *ret = t;
-
- if (start)
- *start = saved_rindex;
-
- return 0;
-
-fail:
- dns_packet_rewind(p, saved_rindex);
- return r;
-}
-
-int dns_packet_read_name(DnsPacket *p, char **_ret,
- bool allow_compression, size_t *start) {
- size_t saved_rindex, after_rindex = 0, jump_barrier;
- _cleanup_free_ char *ret = NULL;
- size_t n = 0, allocated = 0;
- bool first = true;
- int r;
-
- assert(p);
- assert(_ret);
-
- saved_rindex = p->rindex;
- jump_barrier = p->rindex;
-
- for (;;) {
- uint8_t c, d;
-
- r = dns_packet_read_uint8(p, &c, NULL);
- if (r < 0)
- goto fail;
-
- if (c == 0)
- /* End of name */
- break;
- else if (c <= 63) {
- _cleanup_free_ char *t = NULL;
- const char *label;
-
- /* Literal label */
- r = dns_packet_read(p, c, (const void**) &label, NULL);
- if (r < 0)
- goto fail;
-
- r = dns_label_escape(label, c, &t);
- if (r < 0)
- goto fail;
-
- if (!GREEDY_REALLOC(ret, allocated, n + !first + strlen(t) + 1)) {
- r = -ENOMEM;
- goto fail;
- }
-
- if (!first)
- ret[n++] = '.';
- else
- first = false;
-
- memcpy(ret + n, t, r);
- n += r;
- continue;
- } else if (allow_compression && (c & 0xc0) == 0xc0) {
- uint16_t ptr;
-
- /* Pointer */
- r = dns_packet_read_uint8(p, &d, NULL);
- if (r < 0)
- goto fail;
-
- ptr = (uint16_t) (c & ~0xc0) << 8 | (uint16_t) d;
- if (ptr < DNS_PACKET_HEADER_SIZE || ptr >= jump_barrier) {
- r = -EBADMSG;
- goto fail;
- }
-
- if (after_rindex == 0)
- after_rindex = p->rindex;
-
- /* Jumps are limited to a "prior occurrence" (RFC-1035 4.1.4) */
- jump_barrier = ptr;
- p->rindex = ptr;
- } else {
- r = -EBADMSG;
- goto fail;
- }
- }
-
- if (!GREEDY_REALLOC(ret, allocated, n + 1)) {
- r = -ENOMEM;
- goto fail;
- }
-
- ret[n] = 0;
-
- if (after_rindex != 0)
- p->rindex= after_rindex;
-
- *_ret = ret;
- ret = NULL;
-
- if (start)
- *start = saved_rindex;
-
- return 0;
-
-fail:
- dns_packet_rewind(p, saved_rindex);
- return r;
-}
-
-int dns_packet_read_key(DnsPacket *p, DnsResourceKey **ret, size_t *start) {
- _cleanup_free_ char *name = NULL;
- uint16_t class, type;
- DnsResourceKey *key;
- size_t saved_rindex;
- int r;
-
- assert(p);
- assert(ret);
-
- saved_rindex = p->rindex;
-
- r = dns_packet_read_name(p, &name, true, NULL);
- if (r < 0)
- goto fail;
-
- r = dns_packet_read_uint16(p, &type, NULL);
- if (r < 0)
- goto fail;
-
- r = dns_packet_read_uint16(p, &class, NULL);
- if (r < 0)
- goto fail;
-
- key = dns_resource_key_new_consume(class, type, name);
- if (!key) {
- r = -ENOMEM;
- goto fail;
- }
-
- name = NULL;
- *ret = key;
-
- if (start)
- *start = saved_rindex;
-
- return 0;
-fail:
- dns_packet_rewind(p, saved_rindex);
- return r;
-}
-
-static int dns_packet_read_public_key(DnsPacket *p, size_t length,
- void **dp, size_t *lengthp,
- size_t *start) {
- int r;
- const void *d;
- void *d2;
-
- r = dns_packet_read(p, length, &d, NULL);
- if (r < 0)
- return r;
-
- d2 = memdup(d, length);
- if (!d2)
- return -ENOMEM;
-
- *dp = d2;
- *lengthp = length;
- return 0;
-}
-
-static bool loc_size_ok(uint8_t size) {
- uint8_t m = size >> 4, e = size & 0xF;
-
- return m <= 9 && e <= 9 && (m > 0 || e == 0);
-}
-
-static int dnskey_parse_flags(DnsResourceRecord *rr, uint16_t flags) {
- assert(rr);
-
- if (flags & ~(DNSKEY_FLAG_SEP | DNSKEY_FLAG_ZONE_KEY))
- return -EBADMSG;
-
- rr->dnskey.zone_key_flag = flags & DNSKEY_FLAG_ZONE_KEY;
- rr->dnskey.sep_flag = flags & DNSKEY_FLAG_SEP;
- return 0;
-}
-
-int dns_packet_read_rr(DnsPacket *p, DnsResourceRecord **ret, size_t *start) {
- _cleanup_(dns_resource_record_unrefp) DnsResourceRecord *rr = NULL;
- _cleanup_(dns_resource_key_unrefp) DnsResourceKey *key = NULL;
- size_t saved_rindex, offset;
- uint16_t rdlength;
- const void *d;
- int r;
-
- assert(p);
- assert(ret);
-
- saved_rindex = p->rindex;
-
- r = dns_packet_read_key(p, &key, NULL);
- if (r < 0)
- goto fail;
-
- if (key->class == DNS_CLASS_ANY ||
- key->type == DNS_TYPE_ANY) {
- r = -EBADMSG;
- goto fail;
- }
-
- rr = dns_resource_record_new(key);
- if (!rr) {
- r = -ENOMEM;
- goto fail;
- }
-
- r = dns_packet_read_uint32(p, &rr->ttl, NULL);
- if (r < 0)
- goto fail;
-
- r = dns_packet_read_uint16(p, &rdlength, NULL);
- if (r < 0)
- goto fail;
-
- if (p->rindex + rdlength > p->size) {
- r = -EBADMSG;
- goto fail;
- }
-
- offset = p->rindex;
-
- switch (rr->key->type) {
-
- case DNS_TYPE_SRV:
- r = dns_packet_read_uint16(p, &rr->srv.priority, NULL);
- if (r < 0)
- goto fail;
- r = dns_packet_read_uint16(p, &rr->srv.weight, NULL);
- if (r < 0)
- goto fail;
- r = dns_packet_read_uint16(p, &rr->srv.port, NULL);
- if (r < 0)
- goto fail;
- r = dns_packet_read_name(p, &rr->srv.name, true, NULL);
- break;
-
- case DNS_TYPE_PTR:
- case DNS_TYPE_NS:
- case DNS_TYPE_CNAME:
- case DNS_TYPE_DNAME:
- r = dns_packet_read_name(p, &rr->ptr.name, true, NULL);
- break;
-
- case DNS_TYPE_HINFO:
- r = dns_packet_read_string(p, &rr->hinfo.cpu, NULL);
- if (r < 0)
- goto fail;
-
- r = dns_packet_read_string(p, &rr->hinfo.os, NULL);
- break;
-
- case DNS_TYPE_SPF: /* exactly the same as TXT */
- case DNS_TYPE_TXT:
- if (rdlength <= 0) {
- /* RFC 6763, section 6.1 suggests to treat
- * empty TXT RRs as equivalent to a TXT record
- * with a single empty string. */
-
- r = strv_extend(&rr->txt.strings, "");
- if (r < 0)
- goto fail;
- } else {
- while (p->rindex < offset + rdlength) {
- char *s;
-
- r = dns_packet_read_string(p, &s, NULL);
- if (r < 0)
- goto fail;
-
- r = strv_consume(&rr->txt.strings, s);
- if (r < 0)
- goto fail;
- }
- }
-
- r = 0;
- break;
-
- case DNS_TYPE_A:
- r = dns_packet_read_blob(p, &rr->a.in_addr, sizeof(struct in_addr), NULL);
- break;
-
- case DNS_TYPE_AAAA:
- r = dns_packet_read_blob(p, &rr->aaaa.in6_addr, sizeof(struct in6_addr), NULL);
- break;
-
- case DNS_TYPE_SOA:
- r = dns_packet_read_name(p, &rr->soa.mname, true, NULL);
- if (r < 0)
- goto fail;
-
- r = dns_packet_read_name(p, &rr->soa.rname, true, NULL);
- if (r < 0)
- goto fail;
-
- r = dns_packet_read_uint32(p, &rr->soa.serial, NULL);
- if (r < 0)
- goto fail;
-
- r = dns_packet_read_uint32(p, &rr->soa.refresh, NULL);
- if (r < 0)
- goto fail;
-
- r = dns_packet_read_uint32(p, &rr->soa.retry, NULL);
- if (r < 0)
- goto fail;
-
- r = dns_packet_read_uint32(p, &rr->soa.expire, NULL);
- if (r < 0)
- goto fail;
-
- r = dns_packet_read_uint32(p, &rr->soa.minimum, NULL);
- break;
-
- case DNS_TYPE_MX:
- r = dns_packet_read_uint16(p, &rr->mx.priority, NULL);
- if (r < 0)
- goto fail;
-
- r = dns_packet_read_name(p, &rr->mx.exchange, true, NULL);
- break;
-
- case DNS_TYPE_LOC: {
- uint8_t t;
- size_t pos;
-
- r = dns_packet_read_uint8(p, &t, &pos);
- if (r < 0)
- goto fail;
-
- if (t == 0) {
- rr->loc.version = t;
-
- r = dns_packet_read_uint8(p, &rr->loc.size, NULL);
- if (r < 0)
- goto fail;
-
- if (!loc_size_ok(rr->loc.size)) {
- r = -EBADMSG;
- goto fail;
- }
-
- r = dns_packet_read_uint8(p, &rr->loc.horiz_pre, NULL);
- if (r < 0)
- goto fail;
-
- if (!loc_size_ok(rr->loc.horiz_pre)) {
- r = -EBADMSG;
- goto fail;
- }
-
- r = dns_packet_read_uint8(p, &rr->loc.vert_pre, NULL);
- if (r < 0)
- goto fail;
-
- if (!loc_size_ok(rr->loc.vert_pre)) {
- r = -EBADMSG;
- goto fail;
- }
-
- r = dns_packet_read_uint32(p, &rr->loc.latitude, NULL);
- if (r < 0)
- goto fail;
-
- r = dns_packet_read_uint32(p, &rr->loc.longitude, NULL);
- if (r < 0)
- goto fail;
-
- r = dns_packet_read_uint32(p, &rr->loc.altitude, NULL);
- if (r < 0)
- goto fail;
-
- break;
- } else {
- dns_packet_rewind(p, pos);
- rr->unparseable = true;
- goto unparseable;
- }
- }
-
- case DNS_TYPE_SSHFP:
- r = dns_packet_read_uint8(p, &rr->sshfp.algorithm, NULL);
- if (r < 0)
- goto fail;
-
- r = dns_packet_read_uint8(p, &rr->sshfp.fptype, NULL);
- if (r < 0)
- goto fail;
-
- r = dns_packet_read_public_key(p, rdlength - 2,
- &rr->sshfp.key, &rr->sshfp.key_size,
- NULL);
- break;
-
- case DNS_TYPE_DNSKEY: {
- uint16_t flags;
- uint8_t proto;
-
- r = dns_packet_read_uint16(p, &flags, NULL);
- if (r < 0)
- goto fail;
-
- r = dnskey_parse_flags(rr, flags);
- if (r < 0)
- goto fail;
-
- r = dns_packet_read_uint8(p, &proto, NULL);
- if (r < 0)
- goto fail;
-
- /* protocol is required to be always 3 */
- if (proto != 3) {
- r = -EBADMSG;
- goto fail;
- }
-
- r = dns_packet_read_uint8(p, &rr->dnskey.algorithm, NULL);
- if (r < 0)
- goto fail;
-
- r = dns_packet_read_public_key(p, rdlength - 4,
- &rr->dnskey.key, &rr->dnskey.key_size,
- NULL);
- break;
- }
-
- case DNS_TYPE_RRSIG:
- r = dns_packet_read_uint16(p, &rr->rrsig.type_covered, NULL);
- if (r < 0)
- goto fail;
-
- r = dns_packet_read_uint8(p, &rr->rrsig.algorithm, NULL);
- if (r < 0)
- goto fail;
-
- r = dns_packet_read_uint8(p, &rr->rrsig.labels, NULL);
- if (r < 0)
- goto fail;
-
- r = dns_packet_read_uint32(p, &rr->rrsig.original_ttl, NULL);
- if (r < 0)
- goto fail;
-
- r = dns_packet_read_uint32(p, &rr->rrsig.expiration, NULL);
- if (r < 0)
- goto fail;
-
- r = dns_packet_read_uint32(p, &rr->rrsig.inception, NULL);
- if (r < 0)
- goto fail;
-
- r = dns_packet_read_uint16(p, &rr->rrsig.key_tag, NULL);
- if (r < 0)
- goto fail;
-
- r = dns_packet_read_name(p, &rr->rrsig.signer, false, NULL);
- if (r < 0)
- goto fail;
-
- r = dns_packet_read_public_key(p, offset + rdlength - p->rindex,
- &rr->rrsig.signature, &rr->rrsig.signature_size,
- NULL);
- break;
-
- default:
- unparseable:
- r = dns_packet_read(p, rdlength, &d, NULL);
- if (r < 0)
- goto fail;
-
- rr->generic.data = memdup(d, rdlength);
- if (!rr->generic.data) {
- r = -ENOMEM;
- goto fail;
- }
-
- rr->generic.size = rdlength;
- break;
- }
- if (r < 0)
- goto fail;
- if (p->rindex != offset + rdlength) {
- r = -EBADMSG;
- goto fail;
- }
-
- *ret = rr;
- rr = NULL;
-
- if (start)
- *start = saved_rindex;
-
- return 0;
-fail:
- dns_packet_rewind(p, saved_rindex);
- return r;
-}
-
-int dns_packet_extract(DnsPacket *p) {
- _cleanup_(dns_question_unrefp) DnsQuestion *question = NULL;
- _cleanup_(dns_answer_unrefp) DnsAnswer *answer = NULL;
- size_t saved_rindex;
- unsigned n, i;
- int r;
-
- if (p->extracted)
- return 0;
-
- saved_rindex = p->rindex;
- dns_packet_rewind(p, DNS_PACKET_HEADER_SIZE);
-
- n = DNS_PACKET_QDCOUNT(p);
- if (n > 0) {
- question = dns_question_new(n);
- if (!question) {
- r = -ENOMEM;
- goto finish;
- }
-
- for (i = 0; i < n; i++) {
- _cleanup_(dns_resource_key_unrefp) DnsResourceKey *key = NULL;
-
- r = dns_packet_read_key(p, &key, NULL);
- if (r < 0)
- goto finish;
-
- r = dns_question_add(question, key);
- if (r < 0)
- goto finish;
- }
- }
-
- n = DNS_PACKET_RRCOUNT(p);
- if (n > 0) {
- answer = dns_answer_new(n);
- if (!answer) {
- r = -ENOMEM;
- goto finish;
- }
-
- for (i = 0; i < n; i++) {
- _cleanup_(dns_resource_record_unrefp) DnsResourceRecord *rr = NULL;
-
- r = dns_packet_read_rr(p, &rr, NULL);
- if (r < 0)
- goto finish;
-
- r = dns_answer_add(answer, rr);
- if (r < 0)
- goto finish;
- }
- }
-
- p->question = question;
- question = NULL;
-
- p->answer = answer;
- answer = NULL;
-
- p->extracted = true;
-
- r = 0;
-
-finish:
- p->rindex = saved_rindex;
- return r;
-}
-
-static const char* const dns_rcode_table[_DNS_RCODE_MAX_DEFINED] = {
- [DNS_RCODE_SUCCESS] = "SUCCESS",
- [DNS_RCODE_FORMERR] = "FORMERR",
- [DNS_RCODE_SERVFAIL] = "SERVFAIL",
- [DNS_RCODE_NXDOMAIN] = "NXDOMAIN",
- [DNS_RCODE_NOTIMP] = "NOTIMP",
- [DNS_RCODE_REFUSED] = "REFUSED",
- [DNS_RCODE_YXDOMAIN] = "YXDOMAIN",
- [DNS_RCODE_YXRRSET] = "YRRSET",
- [DNS_RCODE_NXRRSET] = "NXRRSET",
- [DNS_RCODE_NOTAUTH] = "NOTAUTH",
- [DNS_RCODE_NOTZONE] = "NOTZONE",
- [DNS_RCODE_BADVERS] = "BADVERS",
- [DNS_RCODE_BADKEY] = "BADKEY",
- [DNS_RCODE_BADTIME] = "BADTIME",
- [DNS_RCODE_BADMODE] = "BADMODE",
- [DNS_RCODE_BADNAME] = "BADNAME",
- [DNS_RCODE_BADALG] = "BADALG",
- [DNS_RCODE_BADTRUNC] = "BADTRUNC",
-};
-DEFINE_STRING_TABLE_LOOKUP(dns_rcode, int);
-
-static const char* const dns_protocol_table[_DNS_PROTOCOL_MAX] = {
- [DNS_PROTOCOL_DNS] = "dns",
- [DNS_PROTOCOL_MDNS] = "mdns",
- [DNS_PROTOCOL_LLMNR] = "llmnr",
-};
-DEFINE_STRING_TABLE_LOOKUP(dns_protocol, DnsProtocol);
-
-static const char* const dnssec_algorithm_table[_DNSSEC_ALGORITHM_MAX_DEFINED] = {
- [DNSSEC_ALGORITHM_RSAMD5] = "RSAMD5",
- [DNSSEC_ALGORITHM_DH] = "DH",
- [DNSSEC_ALGORITHM_DSA] = "DSA",
- [DNSSEC_ALGORITHM_ECC] = "ECC",
- [DNSSEC_ALGORITHM_RSASHA1] = "RSASHA1",
- [DNSSEC_ALGORITHM_INDIRECT] = "INDIRECT",
- [DNSSEC_ALGORITHM_PRIVATEDNS] = "PRIVATEDNS",
- [DNSSEC_ALGORITHM_PRIVATEOID] = "PRIVATEOID",
-};
-DEFINE_STRING_TABLE_LOOKUP(dnssec_algorithm, int);
diff --git a/src/resolve/resolved-dns-packet.h b/src/resolve/resolved-dns-packet.h
deleted file mode 100644
index c5867386c6..0000000000
--- a/src/resolve/resolved-dns-packet.h
+++ /dev/null
@@ -1,235 +0,0 @@
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
-#pragma once
-
-/***
- This file is part of systemd.
-
- Copyright 2014 Lennart Poettering
-
- systemd is free software; you can redistribute it and/or modify it
- under the terms of the GNU Lesser General Public License as published by
- the Free Software Foundation; either version 2.1 of the License, or
- (at your option) any later version.
-
- systemd is distributed in the hope that it will be useful, but
- WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Lesser General Public License for more details.
-
- You should have received a copy of the GNU Lesser General Public License
- along with systemd; If not, see <http://www.gnu.org/licenses/>.
- ***/
-
-
-#include "macro.h"
-#include "sparse-endian.h"
-#include "hashmap.h"
-#include "in-addr-util.h"
-
-typedef struct DnsPacketHeader DnsPacketHeader;
-typedef struct DnsPacket DnsPacket;
-
-#include "resolved-dns-rr.h"
-#include "resolved-dns-question.h"
-#include "resolved-dns-answer.h"
-#include "resolved-def.h"
-
-typedef enum DnsProtocol {
- DNS_PROTOCOL_DNS,
- DNS_PROTOCOL_MDNS,
- DNS_PROTOCOL_LLMNR,
- _DNS_PROTOCOL_MAX,
- _DNS_PROTOCOL_INVALID = -1
-} DnsProtocol;
-
-struct DnsPacketHeader {
- uint16_t id;
- be16_t flags;
- be16_t qdcount;
- be16_t ancount;
- be16_t nscount;
- be16_t arcount;
-};
-
-#define DNS_PACKET_HEADER_SIZE sizeof(DnsPacketHeader)
-
-/* The various DNS protocols deviate in how large a packet can grow,
- but the TCP transport has a 16bit size field, hence that appears to
- be the absolute maximum. */
-#define DNS_PACKET_SIZE_MAX 0xFFFF
-
-/* RFC 1035 say 512 is the maximum, for classic unicast DNS */
-#define DNS_PACKET_UNICAST_SIZE_MAX 512
-
-#define DNS_PACKET_SIZE_START 512
-
-struct DnsPacket {
- int n_ref;
- DnsProtocol protocol;
- size_t size, allocated, rindex;
- void *_data; /* don't access directly, use DNS_PACKET_DATA()! */
- Hashmap *names; /* For name compression */
-
- /* Parsed data */
- DnsQuestion *question;
- DnsAnswer *answer;
-
- /* Packet reception meta data */
- int ifindex;
- int family, ipproto;
- union in_addr_union sender, destination;
- uint16_t sender_port, destination_port;
- uint32_t ttl;
-
- bool extracted;
-};
-
-static inline uint8_t* DNS_PACKET_DATA(DnsPacket *p) {
- if (_unlikely_(!p))
- return NULL;
-
- if (p->_data)
- return p->_data;
-
- return ((uint8_t*) p) + ALIGN(sizeof(DnsPacket));
-}
-
-#define DNS_PACKET_HEADER(p) ((DnsPacketHeader*) DNS_PACKET_DATA(p))
-#define DNS_PACKET_ID(p) DNS_PACKET_HEADER(p)->id
-#define DNS_PACKET_QR(p) ((be16toh(DNS_PACKET_HEADER(p)->flags) >> 15) & 1)
-#define DNS_PACKET_OPCODE(p) ((be16toh(DNS_PACKET_HEADER(p)->flags) >> 11) & 15)
-#define DNS_PACKET_RCODE(p) (be16toh(DNS_PACKET_HEADER(p)->flags) & 15)
-#define DNS_PACKET_TC(p) ((be16toh(DNS_PACKET_HEADER(p)->flags) >> 9) & 1)
-#define DNS_PACKET_C(p) ((be16toh(DNS_PACKET_HEADER(p)->flags) >> 10) & 1)
-#define DNS_PACKET_T(p) ((be16toh(DNS_PACKET_HEADER(p)->flags) >> 8) & 1)
-#define DNS_PACKET_QDCOUNT(p) be16toh(DNS_PACKET_HEADER(p)->qdcount)
-#define DNS_PACKET_ANCOUNT(p) be16toh(DNS_PACKET_HEADER(p)->ancount)
-#define DNS_PACKET_NSCOUNT(p) be16toh(DNS_PACKET_HEADER(p)->nscount)
-#define DNS_PACKET_ARCOUNT(p) be16toh(DNS_PACKET_HEADER(p)->arcount)
-
-#define DNS_PACKET_MAKE_FLAGS(qr, opcode, aa, tc, rd, ra, ad, cd, rcode) \
- (((uint16_t) !!qr << 15) | \
- ((uint16_t) (opcode & 15) << 11) | \
- ((uint16_t) !!aa << 10) | \
- ((uint16_t) !!tc << 9) | \
- ((uint16_t) !!rd << 8) | \
- ((uint16_t) !!ra << 7) | \
- ((uint16_t) !!ad << 5) | \
- ((uint16_t) !!cd << 4) | \
- ((uint16_t) (rcode & 15)))
-
-static inline unsigned DNS_PACKET_RRCOUNT(DnsPacket *p) {
- return
- (unsigned) DNS_PACKET_ANCOUNT(p) +
- (unsigned) DNS_PACKET_NSCOUNT(p) +
- (unsigned) DNS_PACKET_ARCOUNT(p);
-}
-
-int dns_packet_new(DnsPacket **p, DnsProtocol protocol, size_t mtu);
-int dns_packet_new_query(DnsPacket **p, DnsProtocol protocol, size_t mtu);
-
-DnsPacket *dns_packet_ref(DnsPacket *p);
-DnsPacket *dns_packet_unref(DnsPacket *p);
-
-DEFINE_TRIVIAL_CLEANUP_FUNC(DnsPacket*, dns_packet_unref);
-
-int dns_packet_validate(DnsPacket *p);
-int dns_packet_validate_reply(DnsPacket *p);
-int dns_packet_validate_query(DnsPacket *p);
-
-int dns_packet_append_blob(DnsPacket *p, const void *d, size_t sz, size_t *start);
-int dns_packet_append_uint8(DnsPacket *p, uint8_t v, size_t *start);
-int dns_packet_append_uint16(DnsPacket *p, uint16_t v, size_t *start);
-int dns_packet_append_uint32(DnsPacket *p, uint32_t v, size_t *start);
-int dns_packet_append_string(DnsPacket *p, const char *s, size_t *start);
-int dns_packet_append_label(DnsPacket *p, const char *s, size_t l, size_t *start);
-int dns_packet_append_name(DnsPacket *p, const char *name,
- bool allow_compression, size_t *start);
-int dns_packet_append_key(DnsPacket *p, const DnsResourceKey *key, size_t *start);
-int dns_packet_append_rr(DnsPacket *p, const DnsResourceRecord *rr, size_t *start);
-
-int dns_packet_read(DnsPacket *p, size_t sz, const void **ret, size_t *start);
-int dns_packet_read_blob(DnsPacket *p, void *d, size_t sz, size_t *start);
-int dns_packet_read_uint8(DnsPacket *p, uint8_t *ret, size_t *start);
-int dns_packet_read_uint16(DnsPacket *p, uint16_t *ret, size_t *start);
-int dns_packet_read_uint32(DnsPacket *p, uint32_t *ret, size_t *start);
-int dns_packet_read_string(DnsPacket *p, char **ret, size_t *start);
-int dns_packet_read_name(DnsPacket *p, char **ret,
- bool allow_compression, size_t *start);
-int dns_packet_read_key(DnsPacket *p, DnsResourceKey **ret, size_t *start);
-int dns_packet_read_rr(DnsPacket *p, DnsResourceRecord **ret, size_t *start);
-
-void dns_packet_rewind(DnsPacket *p, size_t idx);
-
-int dns_packet_skip_question(DnsPacket *p);
-int dns_packet_extract(DnsPacket *p);
-
-enum {
- DNS_RCODE_SUCCESS = 0,
- DNS_RCODE_FORMERR = 1,
- DNS_RCODE_SERVFAIL = 2,
- DNS_RCODE_NXDOMAIN = 3,
- DNS_RCODE_NOTIMP = 4,
- DNS_RCODE_REFUSED = 5,
- DNS_RCODE_YXDOMAIN = 6,
- DNS_RCODE_YXRRSET = 7,
- DNS_RCODE_NXRRSET = 8,
- DNS_RCODE_NOTAUTH = 9,
- DNS_RCODE_NOTZONE = 10,
- DNS_RCODE_BADVERS = 16,
- DNS_RCODE_BADSIG = 16, /* duplicate value! */
- DNS_RCODE_BADKEY = 17,
- DNS_RCODE_BADTIME = 18,
- DNS_RCODE_BADMODE = 19,
- DNS_RCODE_BADNAME = 20,
- DNS_RCODE_BADALG = 21,
- DNS_RCODE_BADTRUNC = 22,
- _DNS_RCODE_MAX_DEFINED
-};
-
-const char* dns_rcode_to_string(int i) _const_;
-int dns_rcode_from_string(const char *s) _pure_;
-
-const char* dns_protocol_to_string(DnsProtocol p) _const_;
-DnsProtocol dns_protocol_from_string(const char *s) _pure_;
-
-#define LLMNR_MULTICAST_IPV4_ADDRESS ((struct in_addr) { .s_addr = htobe32(224U << 24 | 252U) })
-#define LLMNR_MULTICAST_IPV6_ADDRESS ((struct in6_addr) { .s6_addr = { 0xFF, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x03 } })
-
-#define DNSKEY_FLAG_ZONE_KEY (1u << 8)
-#define DNSKEY_FLAG_SEP (1u << 0)
-
-static inline uint16_t dnskey_to_flags(const DnsResourceRecord *rr) {
- return (rr->dnskey.zone_key_flag * DNSKEY_FLAG_ZONE_KEY |
- rr->dnskey.sep_flag * DNSKEY_FLAG_SEP);
-}
-
-/* http://tools.ietf.org/html/rfc4034#appendix-A.1 */
-enum {
- DNSSEC_ALGORITHM_RSAMD5 = 1,
- DNSSEC_ALGORITHM_DH,
- DNSSEC_ALGORITHM_DSA,
- DNSSEC_ALGORITHM_ECC,
- DNSSEC_ALGORITHM_RSASHA1,
- DNSSEC_ALGORITHM_INDIRECT = 252,
- DNSSEC_ALGORITHM_PRIVATEDNS,
- DNSSEC_ALGORITHM_PRIVATEOID,
- _DNSSEC_ALGORITHM_MAX_DEFINED
-};
-
-const char* dnssec_algorithm_to_string(int i) _const_;
-int dnssec_algorithm_from_string(const char *s) _pure_;
-
-static inline uint64_t SD_RESOLVED_FLAGS_MAKE(DnsProtocol protocol, int family) {
-
- /* Converts a protocol + family into a flags field as used in queries */
-
- if (protocol == DNS_PROTOCOL_DNS)
- return SD_RESOLVED_DNS;
-
- if (protocol == DNS_PROTOCOL_LLMNR)
- return family == AF_INET6 ? SD_RESOLVED_LLMNR_IPV6 : SD_RESOLVED_LLMNR_IPV4;
-
- return 0;
-}
diff --git a/src/resolve/resolved-dns-query.c b/src/resolve/resolved-dns-query.c
deleted file mode 100644
index d619fae725..0000000000
--- a/src/resolve/resolved-dns-query.c
+++ /dev/null
@@ -1,487 +0,0 @@
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
-/***
- This file is part of systemd.
-
- Copyright 2014 Lennart Poettering
-
- systemd is free software; you can redistribute it and/or modify it
- under the terms of the GNU Lesser General Public License as published by
- the Free Software Foundation; either version 2.1 of the License, or
- (at your option) any later version.
-
- systemd is distributed in the hope that it will be useful, but
- WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Lesser General Public License for more details.
-
- You should have received a copy of the GNU Lesser General Public License
- along with systemd; If not, see <http://www.gnu.org/licenses/>.
-***/
-
-
-#include "resolved-dns-query.h"
-
-/* How long to wait for the query in total */
-#define QUERY_TIMEOUT_USEC (30 * USEC_PER_SEC)
-
-#define CNAME_MAX 8
-#define QUERIES_MAX 2048
-
-static void dns_query_stop(DnsQuery *q) {
- DnsTransaction *t;
-
- assert(q);
-
- q->timeout_event_source = sd_event_source_unref(q->timeout_event_source);
-
- while ((t = set_steal_first(q->transactions))) {
- set_remove(t->queries, q);
- dns_transaction_gc(t);
- }
-}
-
-DnsQuery *dns_query_free(DnsQuery *q) {
- if (!q)
- return NULL;
-
- dns_query_stop(q);
- set_free(q->transactions);
-
- dns_question_unref(q->question);
- dns_answer_unref(q->answer);
-
- sd_bus_message_unref(q->request);
- sd_bus_track_unref(q->bus_track);
-
- if (q->manager) {
- LIST_REMOVE(queries, q->manager->dns_queries, q);
- q->manager->n_dns_queries--;
- }
-
- free(q);
-
- return NULL;
-}
-
-int dns_query_new(Manager *m, DnsQuery **ret, DnsQuestion *question, int ifindex, uint64_t flags) {
- _cleanup_(dns_query_freep) DnsQuery *q = NULL;
- unsigned i;
- int r;
-
- assert(m);
- assert(question);
-
- r = dns_question_is_valid(question);
- if (r < 0)
- return r;
-
- if (m->n_dns_queries >= QUERIES_MAX)
- return -EBUSY;
-
- q = new0(DnsQuery, 1);
- if (!q)
- return -ENOMEM;
-
- q->question = dns_question_ref(question);
- q->ifindex = ifindex;
- q->flags = flags;
-
- for (i = 0; i < question->n_keys; i++) {
- _cleanup_free_ char *p;
-
- r = dns_resource_key_to_string(question->keys[i], &p);
- if (r < 0)
- return r;
-
- log_debug("Looking up RR for %s", p);
- }
-
- LIST_PREPEND(queries, m->dns_queries, q);
- m->n_dns_queries++;
- q->manager = m;
-
- if (ret)
- *ret = q;
- q = NULL;
-
- return 0;
-}
-
-static void dns_query_complete(DnsQuery *q, DnsTransactionState state) {
- assert(q);
- assert(!IN_SET(state, DNS_TRANSACTION_NULL, DNS_TRANSACTION_PENDING));
- assert(IN_SET(q->state, DNS_TRANSACTION_NULL, DNS_TRANSACTION_PENDING));
-
- /* Note that this call might invalidate the query. Callers
- * should hence not attempt to access the query or transaction
- * after calling this function. */
-
- q->state = state;
-
- dns_query_stop(q);
- if (q->complete)
- q->complete(q);
-}
-
-static int on_query_timeout(sd_event_source *s, usec_t usec, void *userdata) {
- DnsQuery *q = userdata;
-
- assert(s);
- assert(q);
-
- dns_query_complete(q, DNS_TRANSACTION_TIMEOUT);
- return 0;
-}
-
-static int dns_query_add_transaction(DnsQuery *q, DnsScope *s, DnsResourceKey *key) {
- _cleanup_(dns_question_unrefp) DnsQuestion *question = NULL;
- DnsTransaction *t;
- int r;
-
- assert(q);
- assert(s);
-
- r = set_ensure_allocated(&q->transactions, NULL);
- if (r < 0)
- return r;
-
- if (key) {
- question = dns_question_new(1);
- if (!question)
- return -ENOMEM;
-
- r = dns_question_add(question, key);
- if (r < 0)
- return r;
- } else
- question = dns_question_ref(q->question);
-
- t = dns_scope_find_transaction(s, question, true);
- if (!t) {
- r = dns_transaction_new(&t, s, question);
- if (r < 0)
- return r;
- }
-
- r = set_ensure_allocated(&t->queries, NULL);
- if (r < 0)
- goto gc;
-
- r = set_put(t->queries, q);
- if (r < 0)
- goto gc;
-
- r = set_put(q->transactions, t);
- if (r < 0) {
- set_remove(t->queries, q);
- goto gc;
- }
-
- return 0;
-
-gc:
- dns_transaction_gc(t);
- return r;
-}
-
-static int dns_query_add_transaction_split(DnsQuery *q, DnsScope *s) {
- int r;
-
- assert(q);
- assert(s);
-
- if (s->protocol == DNS_PROTOCOL_MDNS) {
- r = dns_query_add_transaction(q, s, NULL);
- if (r < 0)
- return r;
- } else {
- unsigned i;
-
- /* On DNS and LLMNR we can only send a single
- * question per datagram, hence issue multiple
- * transactions. */
-
- for (i = 0; i < q->question->n_keys; i++) {
- r = dns_query_add_transaction(q, s, q->question->keys[i]);
- if (r < 0)
- return r;
- }
- }
-
- return 0;
-}
-
-int dns_query_go(DnsQuery *q) {
- DnsScopeMatch found = DNS_SCOPE_NO;
- DnsScope *s, *first = NULL;
- DnsTransaction *t;
- const char *name;
- Iterator i;
- int r;
-
- assert(q);
-
- if (q->state != DNS_TRANSACTION_NULL)
- return 0;
-
- assert(q->question);
- assert(q->question->n_keys > 0);
-
- name = DNS_RESOURCE_KEY_NAME(q->question->keys[0]);
-
- LIST_FOREACH(scopes, s, q->manager->dns_scopes) {
- DnsScopeMatch match;
-
- match = dns_scope_good_domain(s, q->ifindex, q->flags, name);
- if (match < 0)
- return match;
-
- if (match == DNS_SCOPE_NO)
- continue;
-
- found = match;
-
- if (match == DNS_SCOPE_YES) {
- first = s;
- break;
- } else {
- assert(match == DNS_SCOPE_MAYBE);
-
- if (!first)
- first = s;
- }
- }
-
- if (found == DNS_SCOPE_NO)
- return -ESRCH;
-
- r = dns_query_add_transaction_split(q, first);
- if (r < 0)
- goto fail;
-
- LIST_FOREACH(scopes, s, first->scopes_next) {
- DnsScopeMatch match;
-
- match = dns_scope_good_domain(s, q->ifindex, q->flags, name);
- if (match < 0)
- goto fail;
-
- if (match != found)
- continue;
-
- r = dns_query_add_transaction_split(q, s);
- if (r < 0)
- goto fail;
- }
-
- q->answer = dns_answer_unref(q->answer);
- q->answer_ifindex = 0;
- q->answer_rcode = 0;
- q->answer_family = AF_UNSPEC;
- q->answer_protocol = _DNS_PROTOCOL_INVALID;
-
- r = sd_event_add_time(
- q->manager->event,
- &q->timeout_event_source,
- clock_boottime_or_monotonic(),
- now(clock_boottime_or_monotonic()) + QUERY_TIMEOUT_USEC, 0,
- on_query_timeout, q);
- if (r < 0)
- goto fail;
-
- q->state = DNS_TRANSACTION_PENDING;
- q->block_ready++;
-
- /* Start the transactions that are not started yet */
- SET_FOREACH(t, q->transactions, i) {
- if (t->state != DNS_TRANSACTION_NULL)
- continue;
-
- r = dns_transaction_go(t);
- if (r < 0)
- goto fail;
- }
-
- q->block_ready--;
- dns_query_ready(q);
-
- return 1;
-
-fail:
- dns_query_stop(q);
- return r;
-}
-
-void dns_query_ready(DnsQuery *q) {
- DnsTransaction *t;
- DnsTransactionState state = DNS_TRANSACTION_NO_SERVERS;
- _cleanup_(dns_answer_unrefp) DnsAnswer *answer = NULL;
- int rcode = 0;
- DnsScope *scope = NULL;
- bool pending = false;
- Iterator i;
-
- assert(q);
- assert(IN_SET(q->state, DNS_TRANSACTION_NULL, DNS_TRANSACTION_PENDING));
-
- /* Note that this call might invalidate the query. Callers
- * should hence not attempt to access the query or transaction
- * after calling this function, unless the block_ready
- * counter was explicitly bumped before doing so. */
-
- if (q->block_ready > 0)
- return;
-
- SET_FOREACH(t, q->transactions, i) {
-
- /* If we found a successful answer, ignore all answers from other scopes */
- if (state == DNS_TRANSACTION_SUCCESS && t->scope != scope)
- continue;
-
- /* One of the transactions is still going on, let's maybe wait for it */
- if (IN_SET(t->state, DNS_TRANSACTION_PENDING, DNS_TRANSACTION_NULL)) {
- pending = true;
- continue;
- }
-
- /* One of the transactions is successful, let's use
- * it, and copy its data out */
- if (t->state == DNS_TRANSACTION_SUCCESS) {
- DnsAnswer *a;
-
- if (t->received) {
- rcode = DNS_PACKET_RCODE(t->received);
- a = t->received->answer;
- } else {
- rcode = t->cached_rcode;
- a = t->cached;
- }
-
- if (state == DNS_TRANSACTION_SUCCESS) {
- DnsAnswer *merged;
-
- merged = dns_answer_merge(answer, a);
- if (!merged) {
- dns_query_complete(q, DNS_TRANSACTION_RESOURCES);
- return;
- }
-
- dns_answer_unref(answer);
- answer = merged;
- } else {
- dns_answer_unref(answer);
- answer = dns_answer_ref(a);
- }
-
- scope = t->scope;
- state = DNS_TRANSACTION_SUCCESS;
- continue;
- }
-
- /* One of the transactions has failed, let's see
- * whether we find anything better, but if not, return
- * its response data */
- if (state != DNS_TRANSACTION_SUCCESS && t->state == DNS_TRANSACTION_FAILURE) {
- DnsAnswer *a;
-
- if (t->received) {
- rcode = DNS_PACKET_RCODE(t->received);
- a = t->received->answer;
- } else {
- rcode = t->cached_rcode;
- a = t->cached;
- }
-
- dns_answer_unref(answer);
- answer = dns_answer_ref(a);
-
- scope = t->scope;
- state = DNS_TRANSACTION_FAILURE;
- continue;
- }
-
- if (state == DNS_TRANSACTION_NO_SERVERS && t->state != DNS_TRANSACTION_NO_SERVERS)
- state = t->state;
- }
-
- if (pending) {
-
- /* If so far we weren't successful, and there's
- * something still pending, then wait for it */
- if (state != DNS_TRANSACTION_SUCCESS)
- return;
-
- /* If we already were successful, then only wait for
- * other transactions on the same scope to finish. */
- SET_FOREACH(t, q->transactions, i) {
- if (t->scope == scope && IN_SET(t->state, DNS_TRANSACTION_PENDING, DNS_TRANSACTION_NULL))
- return;
- }
- }
-
- if (IN_SET(state, DNS_TRANSACTION_SUCCESS, DNS_TRANSACTION_FAILURE)) {
- q->answer = dns_answer_ref(answer);
- q->answer_rcode = rcode;
- q->answer_ifindex = (scope && scope->link) ? scope->link->ifindex : 0;
- q->answer_protocol = scope ? scope->protocol : _DNS_PROTOCOL_INVALID;
- q->answer_family = scope ? scope->family : AF_UNSPEC;
- }
-
- dns_query_complete(q, state);
-}
-
-int dns_query_cname_redirect(DnsQuery *q, const char *name) {
- _cleanup_(dns_question_unrefp) DnsQuestion *nq = NULL;
- int r;
-
- assert(q);
-
- if (q->n_cname_redirects > CNAME_MAX)
- return -ELOOP;
-
- r = dns_question_cname_redirect(q->question, name, &nq);
- if (r < 0)
- return r;
-
- dns_question_unref(q->question);
- q->question = nq;
- nq = NULL;
-
- q->n_cname_redirects++;
-
- dns_query_stop(q);
- q->state = DNS_TRANSACTION_NULL;
-
- return 0;
-}
-
-static int on_bus_track(sd_bus_track *t, void *userdata) {
- DnsQuery *q = userdata;
-
- assert(t);
- assert(q);
-
- log_debug("Client of active query vanished, aborting query.");
- dns_query_complete(q, DNS_TRANSACTION_ABORTED);
- return 0;
-}
-
-int dns_query_bus_track(DnsQuery *q, sd_bus *bus, sd_bus_message *m) {
- int r;
-
- assert(q);
- assert(m);
-
- if (!q->bus_track) {
- r = sd_bus_track_new(bus, &q->bus_track, on_bus_track, q);
- if (r < 0)
- return r;
- }
-
- r = sd_bus_track_add_sender(q->bus_track, m);
- if (r < 0)
- return r;
-
- return 0;
-}
diff --git a/src/resolve/resolved-dns-query.h b/src/resolve/resolved-dns-query.h
deleted file mode 100644
index 788992e679..0000000000
--- a/src/resolve/resolved-dns-query.h
+++ /dev/null
@@ -1,80 +0,0 @@
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
-#pragma once
-
-/***
- This file is part of systemd.
-
- Copyright 2014 Lennart Poettering
-
- systemd is free software; you can redistribute it and/or modify it
- under the terms of the GNU Lesser General Public License as published by
- the Free Software Foundation; either version 2.1 of the License, or
- (at your option) any later version.
-
- systemd is distributed in the hope that it will be useful, but
- WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Lesser General Public License for more details.
-
- You should have received a copy of the GNU Lesser General Public License
- along with systemd; If not, see <http://www.gnu.org/licenses/>.
-***/
-
-
-#include "sd-bus.h"
-#include "set.h"
-
-typedef struct DnsQuery DnsQuery;
-
-#include "resolved-dns-question.h"
-#include "resolved-dns-answer.h"
-#include "resolved-dns-stream.h"
-
-struct DnsQuery {
- Manager *manager;
- DnsQuestion *question;
-
- uint64_t flags;
- int ifindex;
-
- DnsTransactionState state;
- unsigned n_cname_redirects;
-
- sd_event_source *timeout_event_source;
-
- /* Discovered data */
- DnsAnswer *answer;
- int answer_ifindex;
- int answer_family;
- DnsProtocol answer_protocol;
- int answer_rcode;
-
- /* Bus client information */
- sd_bus_message *request;
- int request_family;
- const char *request_hostname;
- union in_addr_union request_address;
-
- /* Completion callback */
- void (*complete)(DnsQuery* q);
- unsigned block_ready;
-
- Set *transactions;
-
- sd_bus_track *bus_track;
-
- LIST_FIELDS(DnsQuery, queries);
-};
-
-int dns_query_new(Manager *m, DnsQuery **q, DnsQuestion *question, int family, uint64_t flags);
-DnsQuery *dns_query_free(DnsQuery *q);
-
-int dns_query_go(DnsQuery *q);
-void dns_query_ready(DnsQuery *q);
-
-int dns_query_cname_redirect(DnsQuery *q, const char *name);
-
-int dns_query_bus_track(DnsQuery *q, sd_bus *bus, sd_bus_message *m);
-
-DEFINE_TRIVIAL_CLEANUP_FUNC(DnsQuery*, dns_query_free);
diff --git a/src/resolve/resolved-dns-question.c b/src/resolve/resolved-dns-question.c
deleted file mode 100644
index 45bcbbf23a..0000000000
--- a/src/resolve/resolved-dns-question.c
+++ /dev/null
@@ -1,274 +0,0 @@
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
-/***
- This file is part of systemd.
-
- Copyright 2014 Lennart Poettering
-
- systemd is free software; you can redistribute it and/or modify it
- under the terms of the GNU Lesser General Public License as published by
- the Free Software Foundation; either version 2.1 of the License, or
- (at your option) any later version.
-
- systemd is distributed in the hope that it will be useful, but
- WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Lesser General Public License for more details.
-
- You should have received a copy of the GNU Lesser General Public License
- along with systemd; If not, see <http://www.gnu.org/licenses/>.
-***/
-
-#include "resolved-dns-question.h"
-#include "resolved-dns-domain.h"
-
-DnsQuestion *dns_question_new(unsigned n) {
- DnsQuestion *q;
-
- assert(n > 0);
-
- q = malloc0(offsetof(DnsQuestion, keys) + sizeof(DnsResourceKey*) * n);
- if (!q)
- return NULL;
-
- q->n_ref = 1;
- q->n_allocated = n;
-
- return q;
-}
-
-DnsQuestion *dns_question_ref(DnsQuestion *q) {
- if (!q)
- return NULL;
-
- assert(q->n_ref > 0);
- q->n_ref++;
- return q;
-}
-
-DnsQuestion *dns_question_unref(DnsQuestion *q) {
- if (!q)
- return NULL;
-
- assert(q->n_ref > 0);
-
- if (q->n_ref == 1) {
- unsigned i;
-
- for (i = 0; i < q->n_keys; i++)
- dns_resource_key_unref(q->keys[i]);
- free(q);
- } else
- q->n_ref--;
-
- return NULL;
-}
-
-int dns_question_add(DnsQuestion *q, DnsResourceKey *key) {
- unsigned i;
- int r;
-
- assert(q);
- assert(key);
-
- for (i = 0; i < q->n_keys; i++) {
- r = dns_resource_key_equal(q->keys[i], key);
- if (r < 0)
- return r;
- if (r > 0)
- return 0;
- }
-
- if (q->n_keys >= q->n_allocated)
- return -ENOSPC;
-
- q->keys[q->n_keys++] = dns_resource_key_ref(key);
- return 0;
-}
-
-int dns_question_matches_rr(DnsQuestion *q, DnsResourceRecord *rr) {
- unsigned i;
- int r;
-
- assert(q);
- assert(rr);
-
- for (i = 0; i < q->n_keys; i++) {
- r = dns_resource_key_match_rr(q->keys[i], rr);
- if (r != 0)
- return r;
- }
-
- return 0;
-}
-
-int dns_question_matches_cname(DnsQuestion *q, DnsResourceRecord *rr) {
- unsigned i;
- int r;
-
- assert(q);
- assert(rr);
-
- for (i = 0; i < q->n_keys; i++) {
- r = dns_resource_key_match_cname(q->keys[i], rr);
- if (r != 0)
- return r;
- }
-
- return 0;
-}
-
-int dns_question_is_valid(DnsQuestion *q) {
- const char *name;
- unsigned i;
- int r;
-
- assert(q);
-
- if (q->n_keys <= 0)
- return 0;
-
- if (q->n_keys > 65535)
- return 0;
-
- name = DNS_RESOURCE_KEY_NAME(q->keys[0]);
- if (!name)
- return 0;
-
- /* Check that all keys in this question bear the same name */
- for (i = 1; i < q->n_keys; i++) {
- assert(q->keys[i]);
-
- r = dns_name_equal(DNS_RESOURCE_KEY_NAME(q->keys[i]), name);
- if (r <= 0)
- return r;
- }
-
- return 1;
-}
-
-int dns_question_is_superset(DnsQuestion *q, DnsQuestion *other) {
- unsigned j;
- int r;
-
- assert(q);
- assert(other);
-
- /* Checks if all keys in "other" are also contained in "q" */
-
- for (j = 0; j < other->n_keys; j++) {
- DnsResourceKey *b = other->keys[j];
- bool found = false;
- unsigned i;
-
- for (i = 0; i < q->n_keys; i++) {
- DnsResourceKey *a = q->keys[i];
-
- r = dns_name_equal(DNS_RESOURCE_KEY_NAME(a), DNS_RESOURCE_KEY_NAME(b));
- if (r < 0)
- return r;
-
- if (r == 0)
- continue;
-
- if (a->class != b->class && a->class != DNS_CLASS_ANY)
- continue;
-
- if (a->type != b->type && a->type != DNS_TYPE_ANY)
- continue;
-
- found = true;
- break;
- }
-
- if (!found)
- return 0;
- }
-
- return 1;
-}
-
-int dns_question_cname_redirect(DnsQuestion *q, const char *name, DnsQuestion **ret) {
- _cleanup_(dns_question_unrefp) DnsQuestion *n = NULL;
- bool same = true;
- unsigned i;
- int r;
-
- assert(q);
- assert(name);
- assert(ret);
-
- for (i = 0; i < q->n_keys; i++) {
- r = dns_name_equal(DNS_RESOURCE_KEY_NAME(q->keys[i]), name);
- if (r < 0)
- return r;
-
- if (r == 0) {
- same = false;
- break;
- }
- }
-
- if (same) {
- /* Shortcut, the names are already right */
- *ret = dns_question_ref(q);
- return 0;
- }
-
- n = dns_question_new(q->n_keys);
- if (!n)
- return -ENOMEM;
-
- /* Create a new question, and patch in the new name */
- for (i = 0; i < q->n_keys; i++) {
- _cleanup_(dns_resource_key_unrefp) DnsResourceKey *k = NULL;
-
- k = dns_resource_key_new(q->keys[i]->class, q->keys[i]->type, name);
- if (!k)
- return -ENOMEM;
-
- r = dns_question_add(n, k);
- if (r < 0)
- return r;
- }
-
- *ret = n;
- n = NULL;
-
- return 1;
-}
-
-int dns_question_endswith(DnsQuestion *q, const char *suffix) {
- unsigned i;
-
- assert(q);
- assert(suffix);
-
- for (i = 0; i < q->n_keys; i++) {
- int k;
-
- k = dns_name_endswith(DNS_RESOURCE_KEY_NAME(q->keys[i]), suffix);
- if (k <= 0)
- return k;
- }
-
- return 1;
-}
-
-int dns_question_extract_reverse_address(DnsQuestion *q, int *family, union in_addr_union *address) {
- unsigned i;
-
- assert(q);
- assert(family);
- assert(address);
-
- for (i = 0; i < q->n_keys; i++) {
- int k;
-
- k = dns_name_address(DNS_RESOURCE_KEY_NAME(q->keys[i]), family, address);
- if (k != 0)
- return k;
- }
-
- return 0;
-}
diff --git a/src/resolve/resolved-dns-question.h b/src/resolve/resolved-dns-question.h
deleted file mode 100644
index 4ba2fe9f0e..0000000000
--- a/src/resolve/resolved-dns-question.h
+++ /dev/null
@@ -1,52 +0,0 @@
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
-#pragma once
-
-/***
- This file is part of systemd.
-
- Copyright 2014 Lennart Poettering
-
- systemd is free software; you can redistribute it and/or modify it
- under the terms of the GNU Lesser General Public License as published by
- the Free Software Foundation; either version 2.1 of the License, or
- (at your option) any later version.
-
- systemd is distributed in the hope that it will be useful, but
- WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Lesser General Public License for more details.
-
- You should have received a copy of the GNU Lesser General Public License
- along with systemd; If not, see <http://www.gnu.org/licenses/>.
-***/
-
-typedef struct DnsQuestion DnsQuestion;
-
-#include "resolved-dns-rr.h"
-
-/* A simple array of resources keys */
-
-struct DnsQuestion {
- unsigned n_ref;
- unsigned n_keys, n_allocated;
- DnsResourceKey* keys[0];
-};
-
-DnsQuestion *dns_question_new(unsigned n);
-DnsQuestion *dns_question_ref(DnsQuestion *q);
-DnsQuestion *dns_question_unref(DnsQuestion *q);
-
-int dns_question_add(DnsQuestion *q, DnsResourceKey *key);
-
-int dns_question_matches_rr(DnsQuestion *q, DnsResourceRecord *rr);
-int dns_question_matches_cname(DnsQuestion *q, DnsResourceRecord *rr);
-int dns_question_is_valid(DnsQuestion *q);
-int dns_question_is_superset(DnsQuestion *q, DnsQuestion *other);
-
-int dns_question_cname_redirect(DnsQuestion *q, const char *name, DnsQuestion **ret);
-
-int dns_question_endswith(DnsQuestion *q, const char *suffix);
-int dns_question_extract_reverse_address(DnsQuestion *q, int *family, union in_addr_union *address);
-
-DEFINE_TRIVIAL_CLEANUP_FUNC(DnsQuestion*, dns_question_unref);
diff --git a/src/resolve/resolved-dns-rr.c b/src/resolve/resolved-dns-rr.c
deleted file mode 100644
index 78d9e4a412..0000000000
--- a/src/resolve/resolved-dns-rr.c
+++ /dev/null
@@ -1,698 +0,0 @@
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
-/***
- This file is part of systemd.
-
- Copyright 2014 Lennart Poettering
-
- systemd is free software; you can redistribute it and/or modify it
- under the terms of the GNU Lesser General Public License as published by
- the Free Software Foundation; either version 2.1 of the License, or
- (at your option) any later version.
-
- systemd is distributed in the hope that it will be useful, but
- WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Lesser General Public License for more details.
-
- You should have received a copy of the GNU Lesser General Public License
- along with systemd; If not, see <http://www.gnu.org/licenses/>.
-***/
-
-#include <math.h>
-
-#include "strv.h"
-
-#include "resolved-dns-domain.h"
-#include "resolved-dns-rr.h"
-#include "resolved-dns-packet.h"
-#include "dns-type.h"
-
-DnsResourceKey* dns_resource_key_new(uint16_t class, uint16_t type, const char *name) {
- DnsResourceKey *k;
- size_t l;
-
- assert(name);
-
- l = strlen(name);
- k = malloc0(sizeof(DnsResourceKey) + l + 1);
- if (!k)
- return NULL;
-
- k->n_ref = 1;
- k->class = class;
- k->type = type;
-
- strcpy((char*) k + sizeof(DnsResourceKey), name);
-
- return k;
-}
-
-DnsResourceKey* dns_resource_key_new_consume(uint16_t class, uint16_t type, char *name) {
- DnsResourceKey *k;
-
- assert(name);
-
- k = new0(DnsResourceKey, 1);
- if (!k)
- return NULL;
-
- k->n_ref = 1;
- k->class = class;
- k->type = type;
- k->_name = name;
-
- return k;
-}
-
-DnsResourceKey* dns_resource_key_ref(DnsResourceKey *k) {
-
- if (!k)
- return NULL;
-
- assert(k->n_ref > 0);
- k->n_ref++;
-
- return k;
-}
-
-DnsResourceKey* dns_resource_key_unref(DnsResourceKey *k) {
- if (!k)
- return NULL;
-
- assert(k->n_ref > 0);
-
- if (k->n_ref == 1) {
- free(k->_name);
- free(k);
- } else
- k->n_ref--;
-
- return NULL;
-}
-
-int dns_resource_key_equal(const DnsResourceKey *a, const DnsResourceKey *b) {
- int r;
-
- r = dns_name_equal(DNS_RESOURCE_KEY_NAME(a), DNS_RESOURCE_KEY_NAME(b));
- if (r <= 0)
- return r;
-
- if (a->class != b->class)
- return 0;
-
- if (a->type != b->type)
- return 0;
-
- return 1;
-}
-
-int dns_resource_key_match_rr(const DnsResourceKey *key, const DnsResourceRecord *rr) {
- assert(key);
- assert(rr);
-
- if (rr->key->class != key->class && key->class != DNS_CLASS_ANY)
- return 0;
-
- if (rr->key->type != key->type && key->type != DNS_TYPE_ANY)
- return 0;
-
- return dns_name_equal(DNS_RESOURCE_KEY_NAME(rr->key), DNS_RESOURCE_KEY_NAME(key));
-}
-
-int dns_resource_key_match_cname(const DnsResourceKey *key, const DnsResourceRecord *rr) {
- assert(key);
- assert(rr);
-
- if (rr->key->class != key->class && key->class != DNS_CLASS_ANY)
- return 0;
-
- if (rr->key->type != DNS_TYPE_CNAME)
- return 0;
-
- return dns_name_equal(DNS_RESOURCE_KEY_NAME(rr->key), DNS_RESOURCE_KEY_NAME(key));
-}
-
-static unsigned long dns_resource_key_hash_func(const void *i, const uint8_t hash_key[HASH_KEY_SIZE]) {
- const DnsResourceKey *k = i;
- unsigned long ul;
-
- ul = dns_name_hash_func(DNS_RESOURCE_KEY_NAME(k), hash_key);
- ul = ul * hash_key[0] + ul + k->class;
- ul = ul * hash_key[1] + ul + k->type;
-
- return ul;
-}
-
-static int dns_resource_key_compare_func(const void *a, const void *b) {
- const DnsResourceKey *x = a, *y = b;
- int ret;
-
- ret = dns_name_compare_func(DNS_RESOURCE_KEY_NAME(x), DNS_RESOURCE_KEY_NAME(y));
- if (ret != 0)
- return ret;
-
- if (x->type < y->type)
- return -1;
- if (x->type > y->type)
- return 1;
-
- if (x->class < y->class)
- return -1;
- if (x->class > y->class)
- return 1;
-
- return 0;
-}
-
-const struct hash_ops dns_resource_key_hash_ops = {
- .hash = dns_resource_key_hash_func,
- .compare = dns_resource_key_compare_func
-};
-
-int dns_resource_key_to_string(const DnsResourceKey *key, char **ret) {
- char cbuf[DECIMAL_STR_MAX(uint16_t)], tbuf[DECIMAL_STR_MAX(uint16_t)];
- const char *c, *t;
- char *s;
-
- c = dns_class_to_string(key->class);
- if (!c) {
- sprintf(cbuf, "%i", key->class);
- c = cbuf;
- }
-
- t = dns_type_to_string(key->type);
- if (!t){
- sprintf(tbuf, "%i", key->type);
- t = tbuf;
- }
-
- if (asprintf(&s, "%s %s %-5s", DNS_RESOURCE_KEY_NAME(key), c, t) < 0)
- return -ENOMEM;
-
- *ret = s;
- return 0;
-}
-
-DnsResourceRecord* dns_resource_record_new(DnsResourceKey *key) {
- DnsResourceRecord *rr;
-
- rr = new0(DnsResourceRecord, 1);
- if (!rr)
- return NULL;
-
- rr->n_ref = 1;
- rr->key = dns_resource_key_ref(key);
-
- return rr;
-}
-
-DnsResourceRecord* dns_resource_record_new_full(uint16_t class, uint16_t type, const char *name) {
- _cleanup_(dns_resource_key_unrefp) DnsResourceKey *key = NULL;
-
- key = dns_resource_key_new(class, type, name);
- if (!key)
- return NULL;
-
- return dns_resource_record_new(key);
-}
-
-DnsResourceRecord* dns_resource_record_ref(DnsResourceRecord *rr) {
- if (!rr)
- return NULL;
-
- assert(rr->n_ref > 0);
- rr->n_ref++;
-
- return rr;
-}
-
-DnsResourceRecord* dns_resource_record_unref(DnsResourceRecord *rr) {
- if (!rr)
- return NULL;
-
- assert(rr->n_ref > 0);
-
- if (rr->n_ref > 1) {
- rr->n_ref--;
- return NULL;
- }
-
- if (rr->key) {
- switch(rr->key->type) {
-
- case DNS_TYPE_SRV:
- free(rr->srv.name);
- break;
-
- case DNS_TYPE_PTR:
- case DNS_TYPE_NS:
- case DNS_TYPE_CNAME:
- case DNS_TYPE_DNAME:
- free(rr->ptr.name);
- break;
-
- case DNS_TYPE_HINFO:
- free(rr->hinfo.cpu);
- free(rr->hinfo.os);
- break;
-
- case DNS_TYPE_TXT:
- case DNS_TYPE_SPF:
- strv_free(rr->txt.strings);
- break;
-
- case DNS_TYPE_SOA:
- free(rr->soa.mname);
- free(rr->soa.rname);
- break;
-
- case DNS_TYPE_MX:
- free(rr->mx.exchange);
- break;
-
- case DNS_TYPE_SSHFP:
- free(rr->sshfp.key);
- break;
-
- case DNS_TYPE_DNSKEY:
- free(rr->dnskey.key);
- break;
-
- case DNS_TYPE_RRSIG:
- free(rr->rrsig.signer);
- free(rr->rrsig.signature);
- break;
-
- case DNS_TYPE_LOC:
- case DNS_TYPE_A:
- case DNS_TYPE_AAAA:
- break;
-
- default:
- free(rr->generic.data);
- }
-
- dns_resource_key_unref(rr->key);
- }
-
- free(rr);
-
- return NULL;
-}
-
-int dns_resource_record_new_reverse(DnsResourceRecord **ret, int family, const union in_addr_union *address, const char *hostname) {
- _cleanup_(dns_resource_key_unrefp) DnsResourceKey *key = NULL;
- _cleanup_(dns_resource_record_unrefp) DnsResourceRecord *rr = NULL;
- _cleanup_free_ char *ptr = NULL;
- int r;
-
- assert(ret);
- assert(address);
- assert(hostname);
-
- r = dns_name_reverse(family, address, &ptr);
- if (r < 0)
- return r;
-
- key = dns_resource_key_new_consume(DNS_CLASS_IN, DNS_TYPE_PTR, ptr);
- if (!key)
- return -ENOMEM;
-
- ptr = NULL;
-
- rr = dns_resource_record_new(key);
- if (!rr)
- return -ENOMEM;
-
- rr->ptr.name = strdup(hostname);
- if (!rr->ptr.name)
- return -ENOMEM;
-
- *ret = rr;
- rr = NULL;
-
- return 0;
-}
-
-int dns_resource_record_equal(const DnsResourceRecord *a, const DnsResourceRecord *b) {
- int r;
-
- assert(a);
- assert(b);
-
- r = dns_resource_key_equal(a->key, b->key);
- if (r <= 0)
- return r;
-
- if (a->unparseable != b->unparseable)
- return 0;
-
- switch (a->unparseable ? _DNS_TYPE_INVALID : a->key->type) {
-
- case DNS_TYPE_SRV:
- r = dns_name_equal(a->srv.name, b->srv.name);
- if (r <= 0)
- return r;
-
- return a->srv.priority == b->srv.priority &&
- a->srv.weight == b->srv.weight &&
- a->srv.port == b->srv.port;
-
- case DNS_TYPE_PTR:
- case DNS_TYPE_NS:
- case DNS_TYPE_CNAME:
- case DNS_TYPE_DNAME:
- return dns_name_equal(a->ptr.name, b->ptr.name);
-
- case DNS_TYPE_HINFO:
- return strcaseeq(a->hinfo.cpu, b->hinfo.cpu) &&
- strcaseeq(a->hinfo.os, b->hinfo.os);
-
- case DNS_TYPE_SPF: /* exactly the same as TXT */
- case DNS_TYPE_TXT:
- return strv_equal(a->txt.strings, b->txt.strings);
-
- case DNS_TYPE_A:
- return memcmp(&a->a.in_addr, &b->a.in_addr, sizeof(struct in_addr)) == 0;
-
- case DNS_TYPE_AAAA:
- return memcmp(&a->aaaa.in6_addr, &b->aaaa.in6_addr, sizeof(struct in6_addr)) == 0;
-
- case DNS_TYPE_SOA:
- r = dns_name_equal(a->soa.mname, b->soa.mname);
- if (r <= 0)
- return r;
- r = dns_name_equal(a->soa.rname, b->soa.rname);
- if (r <= 0)
- return r;
-
- return a->soa.serial == b->soa.serial &&
- a->soa.refresh == b->soa.refresh &&
- a->soa.retry == b->soa.retry &&
- a->soa.expire == b->soa.expire &&
- a->soa.minimum == b->soa.minimum;
-
- case DNS_TYPE_MX:
- if (a->mx.priority != b->mx.priority)
- return 0;
-
- return dns_name_equal(a->mx.exchange, b->mx.exchange);
-
- case DNS_TYPE_LOC:
- assert(a->loc.version == b->loc.version);
-
- return a->loc.size == b->loc.size &&
- a->loc.horiz_pre == b->loc.horiz_pre &&
- a->loc.vert_pre == b->loc.vert_pre &&
- a->loc.latitude == b->loc.latitude &&
- a->loc.longitude == b->loc.longitude &&
- a->loc.altitude == b->loc.altitude;
-
- case DNS_TYPE_SSHFP:
- return a->sshfp.algorithm == b->sshfp.algorithm &&
- a->sshfp.fptype == b->sshfp.fptype &&
- a->sshfp.key_size == b->sshfp.key_size &&
- memcmp(a->sshfp.key, b->sshfp.key, a->sshfp.key_size) == 0;
-
- case DNS_TYPE_DNSKEY:
- return a->dnskey.zone_key_flag == b->dnskey.zone_key_flag &&
- a->dnskey.sep_flag == b->dnskey.sep_flag &&
- a->dnskey.algorithm == b->dnskey.algorithm &&
- a->dnskey.key_size == b->dnskey.key_size &&
- memcmp(a->dnskey.key, b->dnskey.key, a->dnskey.key_size) == 0;
-
- case DNS_TYPE_RRSIG:
- /* do the fast comparisons first */
- if (a->rrsig.type_covered != b->rrsig.type_covered ||
- a->rrsig.algorithm != b->rrsig.algorithm ||
- a->rrsig.labels != b->rrsig.labels ||
- a->rrsig.original_ttl != b->rrsig.original_ttl ||
- a->rrsig.expiration != b->rrsig.expiration ||
- a->rrsig.inception != b->rrsig.inception ||
- a->rrsig.key_tag != b->rrsig.key_tag ||
- a->rrsig.signature_size != b->rrsig.signature_size ||
- memcmp(a->rrsig.signature, b->rrsig.signature, a->rrsig.signature_size) != 0)
- return false;
-
- return dns_name_equal(a->rrsig.signer, b->rrsig.signer);
-
- default:
- return a->generic.size == b->generic.size &&
- memcmp(a->generic.data, b->generic.data, a->generic.size) == 0;
- }
-}
-
-static char* format_location(uint32_t latitude, uint32_t longitude, uint32_t altitude,
- uint8_t size, uint8_t horiz_pre, uint8_t vert_pre) {
- char *s;
- char NS = latitude >= 1U<<31 ? 'N' : 'S';
- char EW = longitude >= 1U<<31 ? 'E' : 'W';
-
- int lat = latitude >= 1U<<31 ? (int) (latitude - (1U<<31)) : (int) ((1U<<31) - latitude);
- int lon = longitude >= 1U<<31 ? (int) (longitude - (1U<<31)) : (int) ((1U<<31) - longitude);
- double alt = altitude >= 10000000u ? altitude - 10000000u : -(double)(10000000u - altitude);
- double siz = (size >> 4) * exp10((double) (size & 0xF));
- double hor = (horiz_pre >> 4) * exp10((double) (horiz_pre & 0xF));
- double ver = (vert_pre >> 4) * exp10((double) (vert_pre & 0xF));
-
- if (asprintf(&s, "%d %d %.3f %c %d %d %.3f %c %.2fm %.2fm %.2fm %.2fm",
- (lat / 60000 / 60),
- (lat / 60000) % 60,
- (lat % 60000) / 1000.,
- NS,
- (lon / 60000 / 60),
- (lon / 60000) % 60,
- (lon % 60000) / 1000.,
- EW,
- alt / 100.,
- siz / 100.,
- hor / 100.,
- ver / 100.) < 0)
- return NULL;
-
- return s;
-}
-
-int dns_resource_record_to_string(const DnsResourceRecord *rr, char **ret) {
- _cleanup_free_ char *k = NULL, *t = NULL;
- char *s;
- int r;
-
- assert(rr);
-
- r = dns_resource_key_to_string(rr->key, &k);
- if (r < 0)
- return r;
-
- switch (rr->unparseable ? _DNS_TYPE_INVALID : rr->key->type) {
-
- case DNS_TYPE_SRV:
- r = asprintf(&s, "%s %u %u %u %s",
- k,
- rr->srv.priority,
- rr->srv.weight,
- rr->srv.port,
- strna(rr->srv.name));
- if (r < 0)
- return -ENOMEM;
- break;
-
- case DNS_TYPE_PTR:
- case DNS_TYPE_NS:
- case DNS_TYPE_CNAME:
- case DNS_TYPE_DNAME:
- s = strjoin(k, " ", rr->ptr.name, NULL);
- if (!s)
- return -ENOMEM;
-
- break;
-
- case DNS_TYPE_HINFO:
- s = strjoin(k, " ", rr->hinfo.cpu, " ", rr->hinfo.os, NULL);
- if (!s)
- return -ENOMEM;
- break;
-
- case DNS_TYPE_SPF: /* exactly the same as TXT */
- case DNS_TYPE_TXT:
- t = strv_join_quoted(rr->txt.strings);
- if (!t)
- return -ENOMEM;
-
- s = strjoin(k, " ", t, NULL);
- if (!s)
- return -ENOMEM;
-
- break;
-
- case DNS_TYPE_A: {
- _cleanup_free_ char *x = NULL;
-
- r = in_addr_to_string(AF_INET, (const union in_addr_union*) &rr->a.in_addr, &x);
- if (r < 0)
- return r;
-
- s = strjoin(k, " ", x, NULL);
- if (!s)
- return -ENOMEM;
- break;
- }
-
- case DNS_TYPE_AAAA:
- r = in_addr_to_string(AF_INET6, (const union in_addr_union*) &rr->aaaa.in6_addr, &t);
- if (r < 0)
- return r;
-
- s = strjoin(k, " ", t, NULL);
- if (!s)
- return -ENOMEM;
- break;
-
- case DNS_TYPE_SOA:
- r = asprintf(&s, "%s %s %s %u %u %u %u %u",
- k,
- strna(rr->soa.mname),
- strna(rr->soa.rname),
- rr->soa.serial,
- rr->soa.refresh,
- rr->soa.retry,
- rr->soa.expire,
- rr->soa.minimum);
- if (r < 0)
- return -ENOMEM;
- break;
-
- case DNS_TYPE_MX:
- r = asprintf(&s, "%s %u %s",
- k,
- rr->mx.priority,
- rr->mx.exchange);
- if (r < 0)
- return -ENOMEM;
- break;
-
- case DNS_TYPE_LOC:
- assert(rr->loc.version == 0);
-
- t = format_location(rr->loc.latitude,
- rr->loc.longitude,
- rr->loc.altitude,
- rr->loc.size,
- rr->loc.horiz_pre,
- rr->loc.vert_pre);
- if (!t)
- return -ENOMEM;
-
- s = strjoin(k, " ", t, NULL);
- if (!s)
- return -ENOMEM;
- break;
-
- case DNS_TYPE_SSHFP:
- t = hexmem(rr->sshfp.key, rr->sshfp.key_size);
- if (!t)
- return -ENOMEM;
-
- r = asprintf(&s, "%s %u %u %s",
- k,
- rr->sshfp.algorithm,
- rr->sshfp.fptype,
- t);
- if (r < 0)
- return -ENOMEM;
- break;
-
- case DNS_TYPE_DNSKEY: {
- const char *alg;
-
- alg = dnssec_algorithm_to_string(rr->dnskey.algorithm);
-
- t = hexmem(rr->dnskey.key, rr->dnskey.key_size);
- if (!t)
- return -ENOMEM;
-
- r = asprintf(&s, "%s %u 3 %.*s%.*u %s",
- k,
- dnskey_to_flags(rr),
- alg ? -1 : 0, alg,
- alg ? 0 : 1, alg ? 0u : (unsigned) rr->dnskey.algorithm,
- t);
- if (r < 0)
- return -ENOMEM;
- break;
- }
-
- case DNS_TYPE_RRSIG: {
- const char *type, *alg;
-
- type = dns_type_to_string(rr->rrsig.type_covered);
- alg = dnssec_algorithm_to_string(rr->rrsig.algorithm);
-
- t = hexmem(rr->rrsig.signature, rr->rrsig.signature_size);
- if (!t)
- return -ENOMEM;
-
- /* TYPE?? follows
- * http://tools.ietf.org/html/rfc3597#section-5 */
-
- r = asprintf(&s, "%s %s%.*u %.*s%.*u %u %u %u %u %u %s %s",
- k,
- type ?: "TYPE",
- type ? 0 : 1, type ? 0u : (unsigned) rr->rrsig.type_covered,
- alg ? -1 : 0, alg,
- alg ? 0 : 1, alg ? 0u : (unsigned) rr->rrsig.algorithm,
- rr->rrsig.labels,
- rr->rrsig.original_ttl,
- rr->rrsig.expiration,
- rr->rrsig.inception,
- rr->rrsig.key_tag,
- rr->rrsig.signer,
- t);
- if (r < 0)
- return -ENOMEM;
- break;
- }
-
- default:
- t = hexmem(rr->generic.data, rr->generic.size);
- if (!t)
- return -ENOMEM;
-
- s = strjoin(k, " ", t, NULL);
- if (!s)
- return -ENOMEM;
- break;
- }
-
- *ret = s;
- return 0;
-}
-
-const char *dns_class_to_string(uint16_t class) {
-
- switch (class) {
-
- case DNS_CLASS_IN:
- return "IN";
-
- case DNS_CLASS_ANY:
- return "ANY";
- }
-
- return NULL;
-}
-
-int dns_class_from_string(const char *s, uint16_t *class) {
- assert(s);
- assert(class);
-
- if (strcaseeq(s, "IN"))
- *class = DNS_CLASS_IN;
- else if (strcaseeq(s, "ANY"))
- *class = DNS_TYPE_ANY;
- else
- return -EINVAL;
-
- return 0;
-}
diff --git a/src/resolve/resolved-dns-rr.h b/src/resolve/resolved-dns-rr.h
deleted file mode 100644
index 26796c842b..0000000000
--- a/src/resolve/resolved-dns-rr.h
+++ /dev/null
@@ -1,175 +0,0 @@
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
-#pragma once
-
-/***
- This file is part of systemd.
-
- Copyright 2014 Lennart Poettering
-
- systemd is free software; you can redistribute it and/or modify it
- under the terms of the GNU Lesser General Public License as published by
- the Free Software Foundation; either version 2.1 of the License, or
- (at your option) any later version.
-
- systemd is distributed in the hope that it will be useful, but
- WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Lesser General Public License for more details.
-
- You should have received a copy of the GNU Lesser General Public License
- along with systemd; If not, see <http://www.gnu.org/licenses/>.
- ***/
-
-#include <netinet/in.h>
-
-#include "hashmap.h"
-#include "in-addr-util.h"
-#include "dns-type.h"
-
-typedef struct DnsResourceKey DnsResourceKey;
-typedef struct DnsResourceRecord DnsResourceRecord;
-
-/* DNS record classes, see RFC 1035 */
-enum {
- DNS_CLASS_IN = 0x01,
- DNS_CLASS_ANY = 0xFF,
- _DNS_CLASS_MAX,
- _DNS_CLASS_INVALID = -1
-};
-
-struct DnsResourceKey {
- unsigned n_ref;
- uint16_t class, type;
- char *_name; /* don't access directy, use DNS_RESOURCE_KEY_NAME()! */
-};
-
-struct DnsResourceRecord {
- unsigned n_ref;
- DnsResourceKey *key;
- uint32_t ttl;
- bool unparseable;
- union {
- struct {
- void *data;
- uint16_t size;
- } generic;
-
- struct {
- uint16_t priority;
- uint16_t weight;
- uint16_t port;
- char *name;
- } srv;
-
- struct {
- char *name;
- } ptr, ns, cname, dname;
-
- struct {
- char *cpu;
- char *os;
- } hinfo;
-
- struct {
- char **strings;
- } txt, spf;
-
- struct {
- struct in_addr in_addr;
- } a;
-
- struct {
- struct in6_addr in6_addr;
- } aaaa;
-
- struct {
- char *mname;
- char *rname;
- uint32_t serial;
- uint32_t refresh;
- uint32_t retry;
- uint32_t expire;
- uint32_t minimum;
- } soa;
-
- struct {
- uint16_t priority;
- char *exchange;
- } mx;
-
- struct {
- uint8_t version;
- uint8_t size;
- uint8_t horiz_pre;
- uint8_t vert_pre;
- uint32_t latitude;
- uint32_t longitude;
- uint32_t altitude;
- } loc;
-
- struct {
- uint8_t algorithm;
- uint8_t fptype;
- void *key;
- size_t key_size;
- } sshfp;
-
- /* http://tools.ietf.org/html/rfc4034#section-2.1 */
- struct {
- bool zone_key_flag:1;
- bool sep_flag:1;
- uint8_t algorithm;
- void* key;
- size_t key_size;
- } dnskey;
-
- /* http://tools.ietf.org/html/rfc4034#section-3.1 */
- struct {
- uint16_t type_covered;
- uint8_t algorithm;
- uint8_t labels;
- uint32_t original_ttl;
- uint32_t expiration;
- uint32_t inception;
- uint16_t key_tag;
- char *signer;
- void *signature;
- size_t signature_size;
- } rrsig;
- };
-};
-
-static inline const char* DNS_RESOURCE_KEY_NAME(const DnsResourceKey *key) {
- if (_unlikely_(!key))
- return NULL;
-
- if (key->_name)
- return key->_name;
-
- return (char*) key + sizeof(DnsResourceKey);
-}
-
-DnsResourceKey* dns_resource_key_new(uint16_t class, uint16_t type, const char *name);
-DnsResourceKey* dns_resource_key_new_consume(uint16_t class, uint16_t type, char *name);
-DnsResourceKey* dns_resource_key_ref(DnsResourceKey *key);
-DnsResourceKey* dns_resource_key_unref(DnsResourceKey *key);
-int dns_resource_key_equal(const DnsResourceKey *a, const DnsResourceKey *b);
-int dns_resource_key_match_rr(const DnsResourceKey *key, const DnsResourceRecord *rr);
-int dns_resource_key_match_cname(const DnsResourceKey *key, const DnsResourceRecord *rr);
-int dns_resource_key_to_string(const DnsResourceKey *key, char **ret);
-DEFINE_TRIVIAL_CLEANUP_FUNC(DnsResourceKey*, dns_resource_key_unref);
-
-DnsResourceRecord* dns_resource_record_new(DnsResourceKey *key);
-DnsResourceRecord* dns_resource_record_new_full(uint16_t class, uint16_t type, const char *name);
-DnsResourceRecord* dns_resource_record_ref(DnsResourceRecord *rr);
-DnsResourceRecord* dns_resource_record_unref(DnsResourceRecord *rr);
-int dns_resource_record_new_reverse(DnsResourceRecord **ret, int family, const union in_addr_union *address, const char *name);
-int dns_resource_record_equal(const DnsResourceRecord *a, const DnsResourceRecord *b);
-int dns_resource_record_to_string(const DnsResourceRecord *rr, char **ret);
-DEFINE_TRIVIAL_CLEANUP_FUNC(DnsResourceRecord*, dns_resource_record_unref);
-
-const char *dns_class_to_string(uint16_t type);
-int dns_class_from_string(const char *name, uint16_t *class);
-
-extern const struct hash_ops dns_resource_key_hash_ops;
diff --git a/src/resolve/resolved-dns-scope.c b/src/resolve/resolved-dns-scope.c
deleted file mode 100644
index ba116de6f5..0000000000
--- a/src/resolve/resolved-dns-scope.c
+++ /dev/null
@@ -1,794 +0,0 @@
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
-/***
- This file is part of systemd.
-
- Copyright 2014 Lennart Poettering
-
- systemd is free software; you can redistribute it and/or modify it
- under the terms of the GNU Lesser General Public License as published by
- the Free Software Foundation; either version 2.1 of the License, or
- (at your option) any later version.
-
- systemd is distributed in the hope that it will be useful, but
- WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Lesser General Public License for more details.
-
- You should have received a copy of the GNU Lesser General Public License
- along with systemd; If not, see <http://www.gnu.org/licenses/>.
-***/
-
-#include <netinet/tcp.h>
-
-#include "missing.h"
-#include "strv.h"
-#include "socket-util.h"
-#include "af-list.h"
-#include "resolved-dns-domain.h"
-#include "resolved-dns-scope.h"
-
-#define MULTICAST_RATELIMIT_INTERVAL_USEC (1*USEC_PER_SEC)
-#define MULTICAST_RATELIMIT_BURST 1000
-
-int dns_scope_new(Manager *m, DnsScope **ret, Link *l, DnsProtocol protocol, int family) {
- DnsScope *s;
-
- assert(m);
- assert(ret);
-
- s = new0(DnsScope, 1);
- if (!s)
- return -ENOMEM;
-
- s->manager = m;
- s->link = l;
- s->protocol = protocol;
- s->family = family;
-
- LIST_PREPEND(scopes, m->dns_scopes, s);
-
- dns_scope_llmnr_membership(s, true);
-
- 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));
-
- /* Enforce ratelimiting for the multicast protocols */
- RATELIMIT_INIT(s->ratelimit, MULTICAST_RATELIMIT_INTERVAL_USEC, MULTICAST_RATELIMIT_BURST);
-
- *ret = s;
- return 0;
-}
-
-DnsScope* dns_scope_free(DnsScope *s) {
- DnsTransaction *t;
- DnsResourceRecord *rr;
-
- if (!s)
- return NULL;
-
- 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));
-
- dns_scope_llmnr_membership(s, false);
-
- while ((t = s->transactions)) {
-
- /* Abort the transaction, but make sure it is not
- * freed while we still look at it */
-
- t->block_gc++;
- dns_transaction_complete(t, DNS_TRANSACTION_ABORTED);
- t->block_gc--;
-
- dns_transaction_free(t);
- }
-
- while ((rr = ordered_hashmap_steal_first(s->conflict_queue)))
- dns_resource_record_unref(rr);
-
- ordered_hashmap_free(s->conflict_queue);
- sd_event_source_unref(s->conflict_event_source);
-
- dns_cache_flush(&s->cache);
- dns_zone_flush(&s->zone);
-
- LIST_REMOVE(scopes, s->manager->dns_scopes, s);
- strv_free(s->domains);
- free(s);
-
- return NULL;
-}
-
-DnsServer *dns_scope_get_dns_server(DnsScope *s) {
- assert(s);
-
- if (s->protocol != DNS_PROTOCOL_DNS)
- return NULL;
-
- if (s->link)
- return link_get_dns_server(s->link);
- else
- return manager_get_dns_server(s->manager);
-}
-
-void dns_scope_next_dns_server(DnsScope *s) {
- assert(s);
-
- if (s->protocol != DNS_PROTOCOL_DNS)
- return;
-
- if (s->link)
- link_next_dns_server(s->link);
- else
- manager_next_dns_server(s->manager);
-}
-
-int dns_scope_emit(DnsScope *s, DnsPacket *p) {
- union in_addr_union addr;
- int ifindex = 0, r;
- int family;
- uint16_t port;
- uint32_t mtu;
- int fd;
-
- assert(s);
- assert(p);
- assert(p->protocol == s->protocol);
-
- if (s->link) {
- mtu = s->link->mtu;
- ifindex = s->link->ifindex;
- } else
- mtu = manager_find_mtu(s->manager);
-
- if (s->protocol == DNS_PROTOCOL_DNS) {
- DnsServer *srv;
-
- if (DNS_PACKET_QDCOUNT(p) > 1)
- return -EOPNOTSUPP;
-
- srv = dns_scope_get_dns_server(s);
- if (!srv)
- return -ESRCH;
-
- family = srv->family;
- addr = srv->address;
- port = 53;
-
- if (p->size > DNS_PACKET_UNICAST_SIZE_MAX)
- return -EMSGSIZE;
-
- if (p->size > mtu)
- return -EMSGSIZE;
-
- if (family == AF_INET)
- fd = manager_dns_ipv4_fd(s->manager);
- else if (family == AF_INET6)
- fd = manager_dns_ipv6_fd(s->manager);
- else
- return -EAFNOSUPPORT;
- if (fd < 0)
- return fd;
-
- } else if (s->protocol == DNS_PROTOCOL_LLMNR) {
-
- if (DNS_PACKET_QDCOUNT(p) > 1)
- return -EOPNOTSUPP;
-
- if (!ratelimit_test(&s->ratelimit))
- return -EBUSY;
-
- family = s->family;
- port = 5355;
-
- if (family == AF_INET) {
- addr.in = LLMNR_MULTICAST_IPV4_ADDRESS;
- fd = manager_llmnr_ipv4_udp_fd(s->manager);
- } else if (family == AF_INET6) {
- addr.in6 = LLMNR_MULTICAST_IPV6_ADDRESS;
- fd = manager_llmnr_ipv6_udp_fd(s->manager);
- } else
- return -EAFNOSUPPORT;
- if (fd < 0)
- return fd;
- } else
- return -EAFNOSUPPORT;
-
- r = manager_send(s->manager, fd, ifindex, family, &addr, port, p);
- if (r < 0)
- return r;
-
- return 1;
-}
-
-int dns_scope_tcp_socket(DnsScope *s, int family, const union in_addr_union *address, uint16_t port) {
- _cleanup_close_ int fd = -1;
- union sockaddr_union sa = {};
- socklen_t salen;
- static const int one = 1;
- int ret, r;
-
- assert(s);
- assert((family == AF_UNSPEC) == !address);
-
- if (family == AF_UNSPEC) {
- DnsServer *srv;
-
- srv = dns_scope_get_dns_server(s);
- if (!srv)
- return -ESRCH;
-
- sa.sa.sa_family = srv->family;
- if (srv->family == AF_INET) {
- sa.in.sin_port = htobe16(port);
- sa.in.sin_addr = srv->address.in;
- salen = sizeof(sa.in);
- } else if (srv->family == AF_INET6) {
- sa.in6.sin6_port = htobe16(port);
- sa.in6.sin6_addr = srv->address.in6;
- sa.in6.sin6_scope_id = s->link ? s->link->ifindex : 0;
- salen = sizeof(sa.in6);
- } else
- return -EAFNOSUPPORT;
- } else {
- sa.sa.sa_family = family;
-
- if (family == AF_INET) {
- sa.in.sin_port = htobe16(port);
- sa.in.sin_addr = address->in;
- salen = sizeof(sa.in);
- } else if (family == AF_INET6) {
- sa.in6.sin6_port = htobe16(port);
- sa.in6.sin6_addr = address->in6;
- sa.in6.sin6_scope_id = s->link ? s->link->ifindex : 0;
- salen = sizeof(sa.in6);
- } else
- return -EAFNOSUPPORT;
- }
-
- fd = socket(sa.sa.sa_family, SOCK_STREAM|SOCK_CLOEXEC|SOCK_NONBLOCK, 0);
- if (fd < 0)
- return -errno;
-
- r = setsockopt(fd, IPPROTO_TCP, TCP_NODELAY, &one, sizeof(one));
- if (r < 0)
- return -errno;
-
- if (s->link) {
- uint32_t ifindex = htobe32(s->link->ifindex);
-
- if (sa.sa.sa_family == AF_INET) {
- r = setsockopt(fd, IPPROTO_IP, IP_UNICAST_IF, &ifindex, sizeof(ifindex));
- if (r < 0)
- return -errno;
- } else if (sa.sa.sa_family == AF_INET6) {
- r = setsockopt(fd, IPPROTO_IPV6, IPV6_UNICAST_IF, &ifindex, sizeof(ifindex));
- if (r < 0)
- return -errno;
- }
- }
-
- if (s->protocol == DNS_PROTOCOL_LLMNR) {
- /* RFC 4795, section 2.5 requires the TTL to be set to 1 */
-
- if (sa.sa.sa_family == AF_INET) {
- r = setsockopt(fd, IPPROTO_IP, IP_TTL, &one, sizeof(one));
- if (r < 0)
- return -errno;
- } else if (sa.sa.sa_family == AF_INET6) {
- r = setsockopt(fd, IPPROTO_IPV6, IPV6_UNICAST_HOPS, &one, sizeof(one));
- if (r < 0)
- return -errno;
- }
- }
-
- r = connect(fd, &sa.sa, salen);
- if (r < 0 && errno != EINPROGRESS)
- return -errno;
-
- ret = fd;
- fd = -1;
-
- return ret;
-}
-
-DnsScopeMatch dns_scope_good_domain(DnsScope *s, int ifindex, uint64_t flags, const char *domain) {
- char **i;
-
- assert(s);
- assert(domain);
-
- if (ifindex != 0 && (!s->link || s->link->ifindex != ifindex))
- return DNS_SCOPE_NO;
-
- if ((SD_RESOLVED_FLAGS_MAKE(s->protocol, s->family) & flags) == 0)
- return DNS_SCOPE_NO;
-
- STRV_FOREACH(i, s->domains)
- if (dns_name_endswith(domain, *i) > 0)
- return DNS_SCOPE_YES;
-
- if (dns_name_root(domain) != 0)
- return DNS_SCOPE_NO;
-
- if (is_localhost(domain))
- return DNS_SCOPE_NO;
-
- if (s->protocol == DNS_PROTOCOL_DNS) {
- if (dns_name_endswith(domain, "254.169.in-addr.arpa") == 0 &&
- dns_name_endswith(domain, "0.8.e.f.ip6.arpa") == 0 &&
- dns_name_single_label(domain) == 0)
- return DNS_SCOPE_MAYBE;
-
- return DNS_SCOPE_NO;
- }
-
- if (s->protocol == DNS_PROTOCOL_MDNS) {
- if (dns_name_endswith(domain, "254.169.in-addr.arpa") > 0 ||
- dns_name_endswith(domain, "0.8.e.f.ip6.arpa") > 0 ||
- (dns_name_endswith(domain, "local") > 0 && dns_name_equal(domain, "local") == 0))
- return DNS_SCOPE_MAYBE;
-
- return DNS_SCOPE_NO;
- }
-
- if (s->protocol == DNS_PROTOCOL_LLMNR) {
- if (dns_name_endswith(domain, "in-addr.arpa") > 0 ||
- dns_name_endswith(domain, "ip6.arpa") > 0 ||
- (dns_name_single_label(domain) > 0 &&
- dns_name_equal(domain, "gateway") <= 0)) /* don't resolve "gateway" with LLMNR, let nss-myhostname handle this */
- return DNS_SCOPE_MAYBE;
-
- return DNS_SCOPE_NO;
- }
-
- assert_not_reached("Unknown scope protocol");
-}
-
-int dns_scope_good_key(DnsScope *s, DnsResourceKey *key) {
- assert(s);
- assert(key);
-
- if (s->protocol == DNS_PROTOCOL_DNS)
- return true;
-
- /* On mDNS and LLMNR, send A and AAAA queries only on the
- * respective scopes */
-
- if (s->family == AF_INET && key->class == DNS_CLASS_IN && key->type == DNS_TYPE_AAAA)
- return false;
-
- if (s->family == AF_INET6 && key->class == DNS_CLASS_IN && key->type == DNS_TYPE_A)
- return false;
-
- return true;
-}
-
-int dns_scope_llmnr_membership(DnsScope *s, bool b) {
- int fd;
-
- assert(s);
-
- if (s->protocol != DNS_PROTOCOL_LLMNR)
- return 0;
-
- assert(s->link);
-
- if (s->family == AF_INET) {
- struct ip_mreqn mreqn = {
- .imr_multiaddr = LLMNR_MULTICAST_IPV4_ADDRESS,
- .imr_ifindex = s->link->ifindex,
- };
-
- fd = manager_llmnr_ipv4_udp_fd(s->manager);
- if (fd < 0)
- return fd;
-
- /* Always first try to drop membership before we add
- * one. This is necessary on some devices, such as
- * veth. */
- if (b)
- (void) setsockopt(fd, IPPROTO_IP, IP_DROP_MEMBERSHIP, &mreqn, sizeof(mreqn));
-
- if (setsockopt(fd, IPPROTO_IP, b ? IP_ADD_MEMBERSHIP : IP_DROP_MEMBERSHIP, &mreqn, sizeof(mreqn)) < 0)
- return -errno;
-
- } else if (s->family == AF_INET6) {
- struct ipv6_mreq mreq = {
- .ipv6mr_multiaddr = LLMNR_MULTICAST_IPV6_ADDRESS,
- .ipv6mr_interface = s->link->ifindex,
- };
-
- fd = manager_llmnr_ipv6_udp_fd(s->manager);
- if (fd < 0)
- return fd;
-
- if (b)
- (void) setsockopt(fd, IPPROTO_IPV6, IPV6_DROP_MEMBERSHIP, &mreq, sizeof(mreq));
-
- if (setsockopt(fd, IPPROTO_IPV6, b ? IPV6_ADD_MEMBERSHIP : IPV6_DROP_MEMBERSHIP, &mreq, sizeof(mreq)) < 0)
- return -errno;
- } else
- return -EAFNOSUPPORT;
-
- return 0;
-}
-
-int dns_scope_good_dns_server(DnsScope *s, int family, const union in_addr_union *address) {
- assert(s);
- assert(address);
-
- if (s->protocol != DNS_PROTOCOL_DNS)
- return 1;
-
- if (s->link)
- return !!link_find_dns_server(s->link, family, address);
- else
- return !!manager_find_dns_server(s->manager, family, address);
-}
-
-static int dns_scope_make_reply_packet(
- DnsScope *s,
- uint16_t id,
- int rcode,
- DnsQuestion *q,
- DnsAnswer *answer,
- DnsAnswer *soa,
- bool tentative,
- DnsPacket **ret) {
-
- _cleanup_(dns_packet_unrefp) DnsPacket *p = NULL;
- unsigned i;
- int r;
-
- assert(s);
- assert(ret);
-
- if ((!q || q->n_keys <= 0)
- && (!answer || answer->n_rrs <= 0)
- && (!soa || soa->n_rrs <= 0))
- return -EINVAL;
-
- r = dns_packet_new(&p, s->protocol, 0);
- if (r < 0)
- return r;
-
- DNS_PACKET_HEADER(p)->id = id;
- DNS_PACKET_HEADER(p)->flags = htobe16(DNS_PACKET_MAKE_FLAGS(
- 1 /* qr */,
- 0 /* opcode */,
- 0 /* c */,
- 0 /* tc */,
- tentative,
- 0 /* (ra) */,
- 0 /* (ad) */,
- 0 /* (cd) */,
- rcode));
-
- if (q) {
- for (i = 0; i < q->n_keys; i++) {
- r = dns_packet_append_key(p, q->keys[i], NULL);
- if (r < 0)
- return r;
- }
-
- DNS_PACKET_HEADER(p)->qdcount = htobe16(q->n_keys);
- }
-
- if (answer) {
- for (i = 0; i < answer->n_rrs; i++) {
- r = dns_packet_append_rr(p, answer->rrs[i], NULL);
- if (r < 0)
- return r;
- }
-
- DNS_PACKET_HEADER(p)->ancount = htobe16(answer->n_rrs);
- }
-
- if (soa) {
- for (i = 0; i < soa->n_rrs; i++) {
- r = dns_packet_append_rr(p, soa->rrs[i], NULL);
- if (r < 0)
- return r;
- }
-
- DNS_PACKET_HEADER(p)->arcount = htobe16(soa->n_rrs);
- }
-
- *ret = p;
- p = NULL;
-
- return 0;
-}
-
-static void dns_scope_verify_conflicts(DnsScope *s, DnsPacket *p) {
- unsigned n;
-
- assert(s);
- assert(p);
-
- if (p->question)
- for (n = 0; n < p->question->n_keys; n++)
- dns_zone_verify_conflicts(&s->zone, p->question->keys[n]);
- if (p->answer)
- for (n = 0; n < p->answer->n_rrs; n++)
- dns_zone_verify_conflicts(&s->zone, p->answer->rrs[n]->key);
-}
-
-void dns_scope_process_query(DnsScope *s, DnsStream *stream, DnsPacket *p) {
- _cleanup_(dns_packet_unrefp) DnsPacket *reply = NULL;
- _cleanup_(dns_answer_unrefp) DnsAnswer *answer = NULL, *soa = NULL;
- bool tentative = false;
- int r, fd;
-
- assert(s);
- assert(p);
-
- if (p->protocol != DNS_PROTOCOL_LLMNR)
- return;
-
- if (p->ipproto == IPPROTO_UDP) {
- /* Don't accept UDP queries directed to anything but
- * the LLMNR multicast addresses. See RFC 4795,
- * section 2.5. */
-
- if (p->family == AF_INET && !in_addr_equal(AF_INET, &p->destination, (union in_addr_union*) &LLMNR_MULTICAST_IPV4_ADDRESS))
- return;
-
- if (p->family == AF_INET6 && !in_addr_equal(AF_INET6, &p->destination, (union in_addr_union*) &LLMNR_MULTICAST_IPV6_ADDRESS))
- return;
- }
-
- r = dns_packet_extract(p);
- if (r < 0) {
- log_debug_errno(r, "Failed to extract resources from incoming packet: %m");
- return;
- }
-
- if (DNS_PACKET_C(p)) {
- /* Somebody notified us about a possible conflict */
- dns_scope_verify_conflicts(s, p);
- return;
- }
-
- r = dns_zone_lookup(&s->zone, p->question, &answer, &soa, &tentative);
- if (r < 0) {
- log_debug_errno(r, "Failed to lookup key: %m");
- return;
- }
- if (r == 0)
- return;
-
- if (answer)
- dns_answer_order_by_scope(answer, in_addr_is_link_local(p->family, &p->sender) > 0);
-
- r = dns_scope_make_reply_packet(s, DNS_PACKET_ID(p), DNS_RCODE_SUCCESS, p->question, answer, soa, tentative, &reply);
- if (r < 0) {
- log_debug_errno(r, "Failed to build reply packet: %m");
- return;
- }
-
- if (stream)
- r = dns_stream_write_packet(stream, reply);
- else {
- if (!ratelimit_test(&s->ratelimit))
- return;
-
- if (p->family == AF_INET)
- fd = manager_llmnr_ipv4_udp_fd(s->manager);
- else if (p->family == AF_INET6)
- fd = manager_llmnr_ipv6_udp_fd(s->manager);
- else {
- log_debug("Unknown protocol");
- return;
- }
- if (fd < 0) {
- log_debug_errno(fd, "Failed to get reply socket: %m");
- return;
- }
-
- /* Note that we always immediately reply to all LLMNR
- * requests, and do not wait any time, since we
- * verified uniqueness for all records. Also see RFC
- * 4795, Section 2.7 */
-
- r = manager_send(s->manager, fd, p->ifindex, p->family, &p->sender, p->sender_port, reply);
- }
-
- if (r < 0) {
- log_debug_errno(r, "Failed to send reply packet: %m");
- return;
- }
-}
-
-DnsTransaction *dns_scope_find_transaction(DnsScope *scope, DnsQuestion *question, bool cache_ok) {
- DnsTransaction *t;
-
- assert(scope);
- assert(question);
-
- /* Try to find an ongoing transaction that is a equal or a
- * superset of the specified question */
-
- LIST_FOREACH(transactions_by_scope, t, scope->transactions) {
-
- /* Refuse reusing transactions that completed based on
- * cached data instead of a real packet, if that's
- * requested. */
- if (!cache_ok &&
- IN_SET(t->state, DNS_TRANSACTION_SUCCESS, DNS_TRANSACTION_FAILURE) &&
- !t->received)
- continue;
-
- if (dns_question_is_superset(t->question, question) > 0)
- return t;
- }
-
- return NULL;
-}
-
-static int dns_scope_make_conflict_packet(
- DnsScope *s,
- DnsResourceRecord *rr,
- DnsPacket **ret) {
-
- _cleanup_(dns_packet_unrefp) DnsPacket *p = NULL;
- int r;
-
- assert(s);
- assert(rr);
- assert(ret);
-
- r = dns_packet_new(&p, s->protocol, 0);
- if (r < 0)
- return r;
-
- DNS_PACKET_HEADER(p)->flags = htobe16(DNS_PACKET_MAKE_FLAGS(
- 0 /* qr */,
- 0 /* opcode */,
- 1 /* conflict */,
- 0 /* tc */,
- 0 /* t */,
- 0 /* (ra) */,
- 0 /* (ad) */,
- 0 /* (cd) */,
- 0));
- random_bytes(&DNS_PACKET_HEADER(p)->id, sizeof(uint16_t));
- DNS_PACKET_HEADER(p)->qdcount = htobe16(1);
- DNS_PACKET_HEADER(p)->arcount = htobe16(1);
-
- r = dns_packet_append_key(p, rr->key, NULL);
- if (r < 0)
- return r;
-
- r = dns_packet_append_rr(p, rr, NULL);
- if (r < 0)
- return r;
-
- *ret = p;
- p = NULL;
-
- return 0;
-}
-
-static 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, 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_C(p) != 0)
- return;
-
- if (DNS_PACKET_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->rrs[i]);
- 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->rrs[i], p->family, &p->sender);
- if (r <= 0)
- continue;
-
- dns_scope_notify_conflict(scope, p->answer->rrs[i]);
- }
-}
diff --git a/src/resolve/resolved-dns-scope.h b/src/resolve/resolved-dns-scope.h
deleted file mode 100644
index cfbde1343f..0000000000
--- a/src/resolve/resolved-dns-scope.h
+++ /dev/null
@@ -1,85 +0,0 @@
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
-#pragma once
-
-/***
- This file is part of systemd.
-
- Copyright 2014 Lennart Poettering
-
- systemd is free software; you can redistribute it and/or modify it
- under the terms of the GNU Lesser General Public License as published by
- the Free Software Foundation; either version 2.1 of the License, or
- (at your option) any later version.
-
- systemd is distributed in the hope that it will be useful, but
- WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Lesser General Public License for more details.
-
- You should have received a copy of the GNU Lesser General Public License
- along with systemd; If not, see <http://www.gnu.org/licenses/>.
-***/
-
-#include "list.h"
-
-typedef struct DnsScope DnsScope;
-
-#include "resolved-dns-server.h"
-#include "resolved-dns-packet.h"
-#include "resolved-dns-cache.h"
-#include "resolved-dns-zone.h"
-#include "resolved-link.h"
-
-typedef enum DnsScopeMatch {
- DNS_SCOPE_NO,
- DNS_SCOPE_MAYBE,
- DNS_SCOPE_YES,
- _DNS_SCOPE_MATCH_MAX,
- _DNS_SCOPE_INVALID = -1
-} DnsScopeMatch;
-
-struct DnsScope {
- Manager *manager;
-
- DnsProtocol protocol;
- int family;
-
- Link *link;
-
- char **domains;
-
- DnsCache cache;
- DnsZone zone;
-
- OrderedHashmap *conflict_queue;
- sd_event_source *conflict_event_source;
-
- RateLimit ratelimit;
-
- LIST_HEAD(DnsTransaction, transactions);
-
- LIST_FIELDS(DnsScope, scopes);
-};
-
-int dns_scope_new(Manager *m, DnsScope **ret, Link *l, DnsProtocol p, int family);
-DnsScope* dns_scope_free(DnsScope *s);
-
-int dns_scope_emit(DnsScope *s, DnsPacket *p);
-int dns_scope_tcp_socket(DnsScope *s, int family, const union in_addr_union *address, uint16_t port);
-
-DnsScopeMatch dns_scope_good_domain(DnsScope *s, int ifindex, uint64_t flags, const char *domain);
-int dns_scope_good_key(DnsScope *s, DnsResourceKey *key);
-int dns_scope_good_dns_server(DnsScope *s, int family, const union in_addr_union *address);
-
-DnsServer *dns_scope_get_dns_server(DnsScope *s);
-void dns_scope_next_dns_server(DnsScope *s);
-
-int dns_scope_llmnr_membership(DnsScope *s, bool b);
-
-void dns_scope_process_query(DnsScope *s, DnsStream *stream, DnsPacket *p);
-
-DnsTransaction *dns_scope_find_transaction(DnsScope *scope, DnsQuestion *question, bool cache_ok);
-
-int dns_scope_notify_conflict(DnsScope *scope, DnsResourceRecord *rr);
-void dns_scope_check_conflicts(DnsScope *scope, DnsPacket *p);
diff --git a/src/resolve/resolved-dns-server.c b/src/resolve/resolved-dns-server.c
deleted file mode 100644
index caf06fe450..0000000000
--- a/src/resolve/resolved-dns-server.c
+++ /dev/null
@@ -1,127 +0,0 @@
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
-/***
- This file is part of systemd.
-
- Copyright 2014 Lennart Poettering
-
- systemd is free software; you can redistribute it and/or modify it
- under the terms of the GNU Lesser General Public License as published by
- the Free Software Foundation; either version 2.1 of the License, or
- (at your option) any later version.
-
- systemd is distributed in the hope that it will be useful, but
- WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Lesser General Public License for more details.
-
- You should have received a copy of the GNU Lesser General Public License
- along with systemd; If not, see <http://www.gnu.org/licenses/>.
-***/
-
-#include "siphash24.h"
-
-#include "resolved-dns-server.h"
-
-int dns_server_new(
- Manager *m,
- DnsServer **ret,
- DnsServerType type,
- Link *l,
- int family,
- const union in_addr_union *in_addr) {
-
- DnsServer *s, *tail;
-
- assert(m);
- assert((type == DNS_SERVER_LINK) == !!l);
- assert(in_addr);
-
- s = new0(DnsServer, 1);
- if (!s)
- return -ENOMEM;
-
- s->type = type;
- s->family = family;
- s->address = *in_addr;
-
- if (type == DNS_SERVER_LINK) {
- LIST_FIND_TAIL(servers, l->dns_servers, tail);
- LIST_INSERT_AFTER(servers, l->dns_servers, tail, s);
- s->link = l;
- } else if (type == DNS_SERVER_SYSTEM) {
- LIST_FIND_TAIL(servers, m->dns_servers, tail);
- LIST_INSERT_AFTER(servers, m->dns_servers, tail, s);
- } else if (type == DNS_SERVER_FALLBACK) {
- LIST_FIND_TAIL(servers, m->fallback_dns_servers, tail);
- LIST_INSERT_AFTER(servers, m->fallback_dns_servers, tail, s);
- } else
- assert_not_reached("Unknown server type");
-
- s->manager = m;
-
- /* A new DNS server that isn't fallback is added and the one
- * we used so far was a fallback one? Then let's try to pick
- * the new one */
- if (type != DNS_SERVER_FALLBACK &&
- m->current_dns_server &&
- m->current_dns_server->type == DNS_SERVER_FALLBACK)
- manager_set_dns_server(m, NULL);
-
- if (ret)
- *ret = s;
-
- return 0;
-}
-
-DnsServer* dns_server_free(DnsServer *s) {
- if (!s)
- return NULL;
-
- if (s->manager) {
- if (s->type == DNS_SERVER_LINK)
- LIST_REMOVE(servers, s->link->dns_servers, s);
- else if (s->type == DNS_SERVER_SYSTEM)
- LIST_REMOVE(servers, s->manager->dns_servers, s);
- else if (s->type == DNS_SERVER_FALLBACK)
- LIST_REMOVE(servers, s->manager->fallback_dns_servers, s);
- else
- assert_not_reached("Unknown server type");
-
- if (s->manager->current_dns_server == s)
- manager_set_dns_server(s->manager, NULL);
- }
-
- if (s->link && s->link->current_dns_server == s)
- link_set_dns_server(s->link, NULL);
-
- free(s);
-
- return NULL;
-}
-
-static unsigned long dns_server_hash_func(const void *p, const uint8_t hash_key[HASH_KEY_SIZE]) {
- const DnsServer *s = p;
- uint64_t u;
-
- siphash24((uint8_t*) &u, &s->address, FAMILY_ADDRESS_SIZE(s->family), hash_key);
- u = u * hash_key[0] + u + s->family;
-
- return u;
-}
-
-static int dns_server_compare_func(const void *a, const void *b) {
- const DnsServer *x = a, *y = b;
-
- if (x->family < y->family)
- return -1;
- if (x->family > y->family)
- return 1;
-
- return memcmp(&x->address, &y->address, FAMILY_ADDRESS_SIZE(x->family));
-}
-
-const struct hash_ops dns_server_hash_ops = {
- .hash = dns_server_hash_func,
- .compare = dns_server_compare_func
-};
diff --git a/src/resolve/resolved-dns-server.h b/src/resolve/resolved-dns-server.h
deleted file mode 100644
index 70ff35b08f..0000000000
--- a/src/resolve/resolved-dns-server.h
+++ /dev/null
@@ -1,62 +0,0 @@
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
-#pragma once
-
-/***
- This file is part of systemd.
-
- Copyright 2014 Lennart Poettering
-
- systemd is free software; you can redistribute it and/or modify it
- under the terms of the GNU Lesser General Public License as published by
- the Free Software Foundation; either version 2.1 of the License, or
- (at your option) any later version.
-
- systemd is distributed in the hope that it will be useful, but
- WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Lesser General Public License for more details.
-
- You should have received a copy of the GNU Lesser General Public License
- along with systemd; If not, see <http://www.gnu.org/licenses/>.
-***/
-
-#include "in-addr-util.h"
-
-typedef struct DnsServer DnsServer;
-typedef enum DnsServerSource DnsServerSource;
-
-typedef enum DnsServerType {
- DNS_SERVER_SYSTEM,
- DNS_SERVER_FALLBACK,
- DNS_SERVER_LINK,
-} DnsServerType;
-
-#include "resolved-link.h"
-
-struct DnsServer {
- Manager *manager;
-
- DnsServerType type;
-
- Link *link;
-
- int family;
- union in_addr_union address;
-
- bool marked:1;
-
- LIST_FIELDS(DnsServer, servers);
-};
-
-int dns_server_new(
- Manager *m,
- DnsServer **s,
- DnsServerType type,
- Link *l,
- int family,
- const union in_addr_union *address);
-
-DnsServer* dns_server_free(DnsServer *s);
-
-extern const struct hash_ops dns_server_hash_ops;
diff --git a/src/resolve/resolved-dns-stream.c b/src/resolve/resolved-dns-stream.c
deleted file mode 100644
index 4c0b557bad..0000000000
--- a/src/resolve/resolved-dns-stream.c
+++ /dev/null
@@ -1,402 +0,0 @@
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
-/***
- This file is part of systemd.
-
- Copyright 2014 Lennart Poettering
-
- systemd is free software; you can redistribute it and/or modify it
- under the terms of the GNU Lesser General Public License as published by
- the Free Software Foundation; either version 2.1 of the License, or
- (at your option) any later version.
-
- systemd is distributed in the hope that it will be useful, but
- WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Lesser General Public License for more details.
-
- You should have received a copy of the GNU Lesser General Public License
- along with systemd; If not, see <http://www.gnu.org/licenses/>.
-***/
-
-#include <netinet/tcp.h>
-
-#include "missing.h"
-#include "resolved-dns-stream.h"
-
-#define DNS_STREAM_TIMEOUT_USEC (10 * USEC_PER_SEC)
-#define DNS_STREAMS_MAX 128
-
-static void dns_stream_stop(DnsStream *s) {
- assert(s);
-
- s->io_event_source = sd_event_source_unref(s->io_event_source);
- s->timeout_event_source = sd_event_source_unref(s->timeout_event_source);
- s->fd = safe_close(s->fd);
-}
-
-static int dns_stream_update_io(DnsStream *s) {
- int f = 0;
-
- assert(s);
-
- if (s->write_packet && s->n_written < sizeof(s->write_size) + s->write_packet->size)
- f |= EPOLLOUT;
- if (!s->read_packet || s->n_read < sizeof(s->read_size) + s->read_packet->size)
- f |= EPOLLIN;
-
- return sd_event_source_set_io_events(s->io_event_source, f);
-}
-
-static int dns_stream_complete(DnsStream *s, int error) {
- assert(s);
-
- dns_stream_stop(s);
-
- if (s->complete)
- s->complete(s, error);
- else
- dns_stream_free(s);
-
- return 0;
-}
-
-static int dns_stream_identify(DnsStream *s) {
- union {
- struct cmsghdr header; /* For alignment */
- uint8_t buffer[CMSG_SPACE(MAXSIZE(struct in_pktinfo, struct in6_pktinfo))
- + EXTRA_CMSG_SPACE /* kernel appears to require extra space */];
- } control;
- struct msghdr mh = {};
- struct cmsghdr *cmsg;
- socklen_t sl;
- int r;
-
- assert(s);
-
- if (s->identified)
- return 0;
-
- /* Query the local side */
- s->local_salen = sizeof(s->local);
- r = getsockname(s->fd, &s->local.sa, &s->local_salen);
- if (r < 0)
- return -errno;
- if (s->local.sa.sa_family == AF_INET6 && s->ifindex <= 0)
- s->ifindex = s->local.in6.sin6_scope_id;
-
- /* Query the remote side */
- s->peer_salen = sizeof(s->peer);
- r = getpeername(s->fd, &s->peer.sa, &s->peer_salen);
- if (r < 0)
- return -errno;
- if (s->peer.sa.sa_family == AF_INET6 && s->ifindex <= 0)
- s->ifindex = s->peer.in6.sin6_scope_id;
-
- /* Check consistency */
- assert(s->peer.sa.sa_family == s->local.sa.sa_family);
- assert(IN_SET(s->peer.sa.sa_family, AF_INET, AF_INET6));
-
- /* Query connection meta information */
- sl = sizeof(control);
- if (s->peer.sa.sa_family == AF_INET) {
- r = getsockopt(s->fd, IPPROTO_IP, IP_PKTOPTIONS, &control, &sl);
- if (r < 0)
- return -errno;
- } else if (s->peer.sa.sa_family == AF_INET6) {
-
- r = getsockopt(s->fd, IPPROTO_IPV6, IPV6_2292PKTOPTIONS, &control, &sl);
- if (r < 0)
- return -errno;
- } else
- return -EAFNOSUPPORT;
-
- mh.msg_control = &control;
- mh.msg_controllen = sl;
- for (cmsg = CMSG_FIRSTHDR(&mh); cmsg; cmsg = CMSG_NXTHDR(&mh, cmsg)) {
-
- if (cmsg->cmsg_level == IPPROTO_IPV6) {
- assert(s->peer.sa.sa_family == AF_INET6);
-
- switch (cmsg->cmsg_type) {
-
- case IPV6_PKTINFO: {
- struct in6_pktinfo *i = (struct in6_pktinfo*) CMSG_DATA(cmsg);
-
- if (s->ifindex <= 0)
- s->ifindex = i->ipi6_ifindex;
- break;
- }
-
- case IPV6_HOPLIMIT:
- s->ttl = *(int *) CMSG_DATA(cmsg);
- break;
- }
-
- } else if (cmsg->cmsg_level == IPPROTO_IP) {
- assert(s->peer.sa.sa_family == AF_INET);
-
- switch (cmsg->cmsg_type) {
-
- case IP_PKTINFO: {
- struct in_pktinfo *i = (struct in_pktinfo*) CMSG_DATA(cmsg);
-
- if (s->ifindex <= 0)
- s->ifindex = i->ipi_ifindex;
- break;
- }
-
- case IP_TTL:
- s->ttl = *(int *) CMSG_DATA(cmsg);
- break;
- }
- }
- }
-
- /* The Linux kernel sets the interface index to the loopback
- * device if the connection came from the local host since it
- * avoids the routing table in such a case. Let's unset the
- * interface index in such a case. */
- if (s->ifindex == LOOPBACK_IFINDEX)
- s->ifindex = 0;
-
- /* If we don't know the interface index still, we look for the
- * first local interface with a matching address. Yuck! */
- if (s->ifindex <= 0)
- s->ifindex = manager_find_ifindex(s->manager, s->local.sa.sa_family, s->local.sa.sa_family == AF_INET ? (union in_addr_union*) &s->local.in.sin_addr : (union in_addr_union*) &s->local.in6.sin6_addr);
-
- if (s->protocol == DNS_PROTOCOL_LLMNR && s->ifindex > 0) {
- uint32_t ifindex = htobe32(s->ifindex);
-
- /* Make sure all packets for this connection are sent on the same interface */
- if (s->local.sa.sa_family == AF_INET) {
- r = setsockopt(s->fd, IPPROTO_IP, IP_UNICAST_IF, &ifindex, sizeof(ifindex));
- if (r < 0)
- log_debug_errno(errno, "Failed to invoke IP_UNICAST_IF: %m");
- } else if (s->local.sa.sa_family == AF_INET6) {
- r = setsockopt(s->fd, IPPROTO_IPV6, IPV6_UNICAST_IF, &ifindex, sizeof(ifindex));
- if (r < 0)
- log_debug_errno(errno, "Failed to invoke IPV6_UNICAST_IF: %m");
- }
- }
-
- s->identified = true;
-
- return 0;
-}
-
-static int on_stream_timeout(sd_event_source *es, usec_t usec, void *userdata) {
- DnsStream *s = userdata;
-
- assert(s);
-
- return dns_stream_complete(s, ETIMEDOUT);
-}
-
-static int on_stream_io(sd_event_source *es, int fd, uint32_t revents, void *userdata) {
- DnsStream *s = userdata;
- int r;
-
- assert(s);
-
- r = dns_stream_identify(s);
- if (r < 0)
- return dns_stream_complete(s, -r);
-
- if ((revents & EPOLLOUT) &&
- s->write_packet &&
- s->n_written < sizeof(s->write_size) + s->write_packet->size) {
-
- struct iovec iov[2];
- ssize_t ss;
-
- iov[0].iov_base = &s->write_size;
- iov[0].iov_len = sizeof(s->write_size);
- iov[1].iov_base = DNS_PACKET_DATA(s->write_packet);
- iov[1].iov_len = s->write_packet->size;
-
- IOVEC_INCREMENT(iov, 2, s->n_written);
-
- ss = writev(fd, iov, 2);
- if (ss < 0) {
- if (errno != EINTR && errno != EAGAIN)
- return dns_stream_complete(s, errno);
- } else
- s->n_written += ss;
-
- /* Are we done? If so, disable the event source for EPOLLOUT */
- if (s->n_written >= sizeof(s->write_size) + s->write_packet->size) {
- r = dns_stream_update_io(s);
- if (r < 0)
- return dns_stream_complete(s, -r);
- }
- }
-
- if ((revents & (EPOLLIN|EPOLLHUP|EPOLLRDHUP)) &&
- (!s->read_packet ||
- s->n_read < sizeof(s->read_size) + s->read_packet->size)) {
-
- if (s->n_read < sizeof(s->read_size)) {
- ssize_t ss;
-
- ss = read(fd, (uint8_t*) &s->read_size + s->n_read, sizeof(s->read_size) - s->n_read);
- if (ss < 0) {
- if (errno != EINTR && errno != EAGAIN)
- return dns_stream_complete(s, errno);
- } else if (ss == 0)
- return dns_stream_complete(s, ECONNRESET);
- else
- s->n_read += ss;
- }
-
- if (s->n_read >= sizeof(s->read_size)) {
-
- if (be16toh(s->read_size) < DNS_PACKET_HEADER_SIZE)
- return dns_stream_complete(s, EBADMSG);
-
- if (s->n_read < sizeof(s->read_size) + be16toh(s->read_size)) {
- ssize_t ss;
-
- if (!s->read_packet) {
- r = dns_packet_new(&s->read_packet, s->protocol, be16toh(s->read_size));
- if (r < 0)
- return dns_stream_complete(s, -r);
-
- s->read_packet->size = be16toh(s->read_size);
- s->read_packet->ipproto = IPPROTO_TCP;
- s->read_packet->family = s->peer.sa.sa_family;
- s->read_packet->ttl = s->ttl;
- s->read_packet->ifindex = s->ifindex;
-
- if (s->read_packet->family == AF_INET) {
- s->read_packet->sender.in = s->peer.in.sin_addr;
- s->read_packet->sender_port = be16toh(s->peer.in.sin_port);
- s->read_packet->destination.in = s->local.in.sin_addr;
- s->read_packet->destination_port = be16toh(s->local.in.sin_port);
- } else {
- assert(s->read_packet->family == AF_INET6);
- s->read_packet->sender.in6 = s->peer.in6.sin6_addr;
- s->read_packet->sender_port = be16toh(s->peer.in6.sin6_port);
- s->read_packet->destination.in6 = s->local.in6.sin6_addr;
- s->read_packet->destination_port = be16toh(s->local.in6.sin6_port);
-
- if (s->read_packet->ifindex == 0)
- s->read_packet->ifindex = s->peer.in6.sin6_scope_id;
- if (s->read_packet->ifindex == 0)
- s->read_packet->ifindex = s->local.in6.sin6_scope_id;
- }
- }
-
- ss = read(fd,
- (uint8_t*) DNS_PACKET_DATA(s->read_packet) + s->n_read - sizeof(s->read_size),
- sizeof(s->read_size) + be16toh(s->read_size) - s->n_read);
- if (ss < 0) {
- if (errno != EINTR && errno != EAGAIN)
- return dns_stream_complete(s, errno);
- } else if (ss == 0)
- return dns_stream_complete(s, ECONNRESET);
- else
- s->n_read += ss;
- }
-
- /* Are we done? If so, disable the event source for EPOLLIN */
- if (s->n_read >= sizeof(s->read_size) + be16toh(s->read_size)) {
- r = dns_stream_update_io(s);
- if (r < 0)
- return dns_stream_complete(s, -r);
-
- /* If there's a packet handler
- * installed, call that. Note that
- * this is optional... */
- if (s->on_packet)
- return s->on_packet(s);
- }
- }
- }
-
- if ((s->write_packet && s->n_written >= sizeof(s->write_size) + s->write_packet->size) &&
- (s->read_packet && s->n_read >= sizeof(s->read_size) + s->read_packet->size))
- return dns_stream_complete(s, 0);
-
- return 0;
-}
-
-DnsStream *dns_stream_free(DnsStream *s) {
- if (!s)
- return NULL;
-
- dns_stream_stop(s);
-
- if (s->manager) {
- LIST_REMOVE(streams, s->manager->dns_streams, s);
- s->manager->n_dns_streams--;
- }
-
- dns_packet_unref(s->write_packet);
- dns_packet_unref(s->read_packet);
-
- free(s);
-
- return 0;
-}
-
-DEFINE_TRIVIAL_CLEANUP_FUNC(DnsStream*, dns_stream_free);
-
-int dns_stream_new(Manager *m, DnsStream **ret, DnsProtocol protocol, int fd) {
- static const int one = 1;
- _cleanup_(dns_stream_freep) DnsStream *s = NULL;
- int r;
-
- assert(m);
- assert(fd >= 0);
-
- if (m->n_dns_streams > DNS_STREAMS_MAX)
- return -EBUSY;
-
- s = new0(DnsStream, 1);
- if (!s)
- return -ENOMEM;
-
- s->fd = -1;
- s->protocol = protocol;
-
- r = setsockopt(fd, IPPROTO_TCP, TCP_NODELAY, &one, sizeof(one));
- if (r < 0)
- return -errno;
-
- r = sd_event_add_io(m->event, &s->io_event_source, fd, EPOLLIN, on_stream_io, s);
- if (r < 0)
- return r;
-
- r = sd_event_add_time(
- m->event,
- &s->timeout_event_source,
- clock_boottime_or_monotonic(),
- now(clock_boottime_or_monotonic()) + DNS_STREAM_TIMEOUT_USEC, 0,
- on_stream_timeout, s);
- if (r < 0)
- return r;
-
- LIST_PREPEND(streams, m->dns_streams, s);
- s->manager = m;
- s->fd = fd;
- m->n_dns_streams++;
-
- *ret = s;
- s = NULL;
-
- return 0;
-}
-
-int dns_stream_write_packet(DnsStream *s, DnsPacket *p) {
- assert(s);
-
- if (s->write_packet)
- return -EBUSY;
-
- s->write_packet = dns_packet_ref(p);
- s->write_size = htobe16(p->size);
- s->n_written = 0;
-
- return dns_stream_update_io(s);
-}
diff --git a/src/resolve/resolved-dns-stream.h b/src/resolve/resolved-dns-stream.h
deleted file mode 100644
index fb81e9f1ac..0000000000
--- a/src/resolve/resolved-dns-stream.h
+++ /dev/null
@@ -1,63 +0,0 @@
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
-#pragma once
-
-/***
- This file is part of systemd.
-
- Copyright 2014 Lennart Poettering
-
- systemd is free software; you can redistribute it and/or modify it
- under the terms of the GNU Lesser General Public License as published by
- the Free Software Foundation; either version 2.1 of the License, or
- (at your option) any later version.
-
- systemd is distributed in the hope that it will be useful, but
- WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Lesser General Public License for more details.
-
- You should have received a copy of the GNU Lesser General Public License
- along with systemd; If not, see <http://www.gnu.org/licenses/>.
-***/
-
-#include "socket-util.h"
-
-typedef struct DnsStream DnsStream;
-
-#include "resolved-dns-packet.h"
-#include "resolved-dns-transaction.h"
-
-struct DnsStream {
- Manager *manager;
-
- DnsProtocol protocol;
-
- int fd;
- union sockaddr_union peer;
- socklen_t peer_salen;
- union sockaddr_union local;
- socklen_t local_salen;
- int ifindex;
- uint32_t ttl;
- bool identified;
-
- sd_event_source *io_event_source;
- sd_event_source *timeout_event_source;
-
- be16_t write_size, read_size;
- DnsPacket *write_packet, *read_packet;
- size_t n_written, n_read;
-
- int (*on_packet)(DnsStream *s);
- int (*complete)(DnsStream *s, int error);
-
- DnsTransaction *transaction;
-
- LIST_FIELDS(DnsStream, streams);
-};
-
-int dns_stream_new(Manager *m, DnsStream **s, DnsProtocol protocol, int fd);
-DnsStream *dns_stream_free(DnsStream *s);
-
-int dns_stream_write_packet(DnsStream *s, DnsPacket *p);
diff --git a/src/resolve/resolved-dns-transaction.c b/src/resolve/resolved-dns-transaction.c
deleted file mode 100644
index bc1a90db1b..0000000000
--- a/src/resolve/resolved-dns-transaction.c
+++ /dev/null
@@ -1,619 +0,0 @@
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
-/***
- This file is part of systemd.
-
- Copyright 2014 Lennart Poettering
-
- systemd is free software; you can redistribute it and/or modify it
- under the terms of the GNU Lesser General Public License as published by
- the Free Software Foundation; either version 2.1 of the License, or
- (at your option) any later version.
-
- systemd is distributed in the hope that it will be useful, but
- WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Lesser General Public License for more details.
-
- You should have received a copy of the GNU Lesser General Public License
- along with systemd; If not, see <http://www.gnu.org/licenses/>.
-***/
-
-#include "af-list.h"
-
-#include "resolved-dns-transaction.h"
-
-DnsTransaction* dns_transaction_free(DnsTransaction *t) {
- DnsQuery *q;
- DnsZoneItem *i;
-
- if (!t)
- return NULL;
-
- sd_event_source_unref(t->timeout_event_source);
-
- dns_question_unref(t->question);
- dns_packet_unref(t->sent);
- dns_packet_unref(t->received);
- dns_answer_unref(t->cached);
-
- dns_stream_free(t->stream);
-
- if (t->scope) {
- LIST_REMOVE(transactions_by_scope, t->scope->transactions, t);
-
- if (t->id != 0)
- hashmap_remove(t->scope->manager->dns_transactions, UINT_TO_PTR(t->id));
- }
-
- while ((q = set_steal_first(t->queries)))
- set_remove(q->transactions, t);
- set_free(t->queries);
-
- while ((i = set_steal_first(t->zone_items)))
- i->probe_transaction = NULL;
- set_free(t->zone_items);
-
- free(t);
- return NULL;
-}
-
-DEFINE_TRIVIAL_CLEANUP_FUNC(DnsTransaction*, dns_transaction_free);
-
-void dns_transaction_gc(DnsTransaction *t) {
- assert(t);
-
- if (t->block_gc > 0)
- return;
-
- if (set_isempty(t->queries) && set_isempty(t->zone_items))
- dns_transaction_free(t);
-}
-
-int dns_transaction_new(DnsTransaction **ret, DnsScope *s, DnsQuestion *q) {
- _cleanup_(dns_transaction_freep) DnsTransaction *t = NULL;
- int r;
-
- assert(ret);
- assert(s);
- assert(q);
-
- r = hashmap_ensure_allocated(&s->manager->dns_transactions, NULL);
- if (r < 0)
- return r;
-
- t = new0(DnsTransaction, 1);
- if (!t)
- return -ENOMEM;
-
- t->question = dns_question_ref(q);
-
- do
- random_bytes(&t->id, sizeof(t->id));
- while (t->id == 0 ||
- hashmap_get(s->manager->dns_transactions, UINT_TO_PTR(t->id)));
-
- r = hashmap_put(s->manager->dns_transactions, UINT_TO_PTR(t->id), t);
- if (r < 0) {
- t->id = 0;
- return r;
- }
-
- LIST_PREPEND(transactions_by_scope, s->transactions, t);
- t->scope = s;
-
- if (ret)
- *ret = t;
-
- t = NULL;
-
- return 0;
-}
-
-static void dns_transaction_stop(DnsTransaction *t) {
- assert(t);
-
- t->timeout_event_source = sd_event_source_unref(t->timeout_event_source);
- t->stream = dns_stream_free(t->stream);
-}
-
-static void dns_transaction_tentative(DnsTransaction *t, DnsPacket *p) {
- _cleanup_free_ char *pretty = NULL;
- DnsZoneItem *z;
-
- assert(t);
- assert(p);
-
- if (manager_our_packet(t->scope->manager, p) != 0)
- return;
-
- in_addr_to_string(p->family, &p->sender, &pretty);
-
- log_debug("Transaction on scope %s on %s/%s got tentative packet from %s",
- dns_protocol_to_string(t->scope->protocol),
- t->scope->link ? t->scope->link->name : "*",
- t->scope->family == AF_UNSPEC ? "*" : af_to_name(t->scope->family),
- pretty);
-
- /* RFC 4795, Section 4.1 says that the peer with the
- * lexicographically smaller IP address loses */
- if (memcmp(&p->sender, &p->destination, FAMILY_ADDRESS_SIZE(p->family)) >= 0) {
- log_debug("Peer has lexicographically larger IP address and thus lost in the conflict.");
- return;
- }
-
- log_debug("We have the lexicographically larger IP address and thus lost in the conflict.");
-
- t->block_gc++;
- while ((z = set_first(t->zone_items))) {
- /* First, make sure the zone item drops the reference
- * to us */
- dns_zone_item_probe_stop(z);
-
- /* Secondly, report this as conflict, so that we might
- * look for a different hostname */
- dns_zone_item_conflict(z);
- }
- t->block_gc--;
-
- dns_transaction_gc(t);
-}
-
-void dns_transaction_complete(DnsTransaction *t, DnsTransactionState state) {
- DnsQuery *q;
- DnsZoneItem *z;
- Iterator i;
-
- assert(t);
- assert(!IN_SET(state, DNS_TRANSACTION_NULL, DNS_TRANSACTION_PENDING));
-
- if (!IN_SET(t->state, DNS_TRANSACTION_NULL, DNS_TRANSACTION_PENDING))
- return;
-
- /* Note that this call might invalidate the query. Callers
- * should hence not attempt to access the query or transaction
- * after calling this function. */
-
- log_debug("Transaction on scope %s on %s/%s now complete with <%s>",
- dns_protocol_to_string(t->scope->protocol),
- t->scope->link ? t->scope->link->name : "*",
- t->scope->family == AF_UNSPEC ? "*" : af_to_name(t->scope->family),
- dns_transaction_state_to_string(state));
-
- t->state = state;
-
- dns_transaction_stop(t);
-
- /* Notify all queries that are interested, but make sure the
- * transaction isn't freed while we are still looking at it */
- t->block_gc++;
- SET_FOREACH(q, t->queries, i)
- dns_query_ready(q);
- SET_FOREACH(z, t->zone_items, i)
- dns_zone_item_ready(z);
- t->block_gc--;
-
- dns_transaction_gc(t);
-}
-
-static int on_stream_complete(DnsStream *s, int error) {
- _cleanup_(dns_packet_unrefp) DnsPacket *p = NULL;
- DnsTransaction *t;
-
- assert(s);
- assert(s->transaction);
-
- /* Copy the data we care about out of the stream before we
- * destroy it. */
- t = s->transaction;
- p = dns_packet_ref(s->read_packet);
-
- t->stream = dns_stream_free(t->stream);
-
- if (error != 0) {
- dns_transaction_complete(t, DNS_TRANSACTION_RESOURCES);
- return 0;
- }
-
- if (dns_packet_validate_reply(p) <= 0) {
- log_debug("Invalid LLMNR TCP packet.");
- dns_transaction_complete(t, DNS_TRANSACTION_INVALID_REPLY);
- return 0;
- }
-
- dns_scope_check_conflicts(t->scope, p);
-
- t->block_gc++;
- dns_transaction_process_reply(t, p);
- t->block_gc--;
-
- /* If the response wasn't useful, then complete the transition now */
- if (t->state == DNS_TRANSACTION_PENDING)
- dns_transaction_complete(t, DNS_TRANSACTION_INVALID_REPLY);
-
- return 0;
-}
-
-static int dns_transaction_open_tcp(DnsTransaction *t) {
- _cleanup_close_ int fd = -1;
- int r;
-
- assert(t);
-
- if (t->stream)
- return 0;
-
- if (t->scope->protocol == DNS_PROTOCOL_DNS)
- fd = dns_scope_tcp_socket(t->scope, AF_UNSPEC, NULL, 53);
- else if (t->scope->protocol == DNS_PROTOCOL_LLMNR) {
-
- /* When we already received a query to this (but it was truncated), send to its sender address */
- if (t->received)
- fd = dns_scope_tcp_socket(t->scope, t->received->family, &t->received->sender, t->received->sender_port);
- else {
- union in_addr_union address;
- int family = AF_UNSPEC;
-
- /* Otherwise, try to talk to the owner of a
- * the IP address, in case this is a reverse
- * PTR lookup */
- r = dns_question_extract_reverse_address(t->question, &family, &address);
- if (r < 0)
- return r;
- if (r == 0)
- return -EINVAL;
-
- fd = dns_scope_tcp_socket(t->scope, family, &address, 5355);
- }
- } else
- return -EAFNOSUPPORT;
-
- if (fd < 0)
- return fd;
-
- r = dns_stream_new(t->scope->manager, &t->stream, t->scope->protocol, fd);
- if (r < 0)
- return r;
-
- fd = -1;
-
- r = dns_stream_write_packet(t->stream, t->sent);
- if (r < 0) {
- t->stream = dns_stream_free(t->stream);
- return r;
- }
-
- t->received = dns_packet_unref(t->received);
- t->stream->complete = on_stream_complete;
- t->stream->transaction = t;
-
- /* The interface index is difficult to determine if we are
- * connecting to the local host, hence fill this in right away
- * instead of determining it from the socket */
- if (t->scope->link)
- t->stream->ifindex = t->scope->link->ifindex;
-
- return 0;
-}
-
-void dns_transaction_process_reply(DnsTransaction *t, DnsPacket *p) {
- int r;
-
- assert(t);
- assert(p);
- assert(t->state == DNS_TRANSACTION_PENDING);
-
- /* Note that this call might invalidate the query. Callers
- * should hence not attempt to access the query or transaction
- * after calling this function. */
-
- if (t->scope->protocol == DNS_PROTOCOL_LLMNR) {
- assert(t->scope->link);
-
- /* For LLMNR we will not accept any packets from other
- * interfaces */
-
- if (p->ifindex != t->scope->link->ifindex)
- return;
-
- if (p->family != t->scope->family)
- return;
-
- /* Tentative packets are not full responses but still
- * useful for identifying uniqueness conflicts during
- * probing. */
- if (DNS_PACKET_T(p)) {
- dns_transaction_tentative(t, p);
- return;
- }
- }
-
- if (t->scope->protocol == DNS_PROTOCOL_DNS) {
-
- /* For DNS we are fine with accepting packets on any
- * interface, but the source IP address must be one of
- * a valid DNS server */
-
- if (!dns_scope_good_dns_server(t->scope, p->family, &p->sender))
- return;
-
- if (p->sender_port != 53)
- return;
- }
-
- if (t->received != p) {
- dns_packet_unref(t->received);
- t->received = dns_packet_ref(p);
- }
-
- if (p->ipproto == IPPROTO_TCP) {
- if (DNS_PACKET_TC(p)) {
- /* Truncated via TCP? Somebody must be fucking with us */
- dns_transaction_complete(t, DNS_TRANSACTION_INVALID_REPLY);
- return;
- }
-
- if (DNS_PACKET_ID(p) != t->id) {
- /* Not the reply to our query? Somebody must be fucking with us */
- dns_transaction_complete(t, DNS_TRANSACTION_INVALID_REPLY);
- return;
- }
- }
-
- if (DNS_PACKET_TC(p)) {
- /* Response was truncated, let's try again with good old TCP */
- r = dns_transaction_open_tcp(t);
- if (r == -ESRCH) {
- /* No servers found? Damn! */
- dns_transaction_complete(t, DNS_TRANSACTION_NO_SERVERS);
- return;
- }
- if (r < 0) {
- /* On LLMNR, if we cannot connect to the host,
- * we immediately give up */
- if (t->scope->protocol == DNS_PROTOCOL_LLMNR) {
- dns_transaction_complete(t, DNS_TRANSACTION_RESOURCES);
- return;
- }
-
- /* On DNS, couldn't send? Try immediately again, with a new server */
- dns_scope_next_dns_server(t->scope);
-
- r = dns_transaction_go(t);
- if (r < 0) {
- dns_transaction_complete(t, DNS_TRANSACTION_RESOURCES);
- return;
- }
-
- return;
- }
- }
-
- /* Parse and update the cache */
- r = dns_packet_extract(p);
- if (r < 0) {
- dns_transaction_complete(t, DNS_TRANSACTION_INVALID_REPLY);
- return;
- }
-
- /* According to RFC 4795, section 2.9. only the RRs from the answer section shall be cached */
- dns_cache_put(&t->scope->cache, p->question, DNS_PACKET_RCODE(p), p->answer, DNS_PACKET_ANCOUNT(p), 0, p->family, &p->sender);
-
- if (DNS_PACKET_RCODE(p) == DNS_RCODE_SUCCESS)
- dns_transaction_complete(t, DNS_TRANSACTION_SUCCESS);
- else
- dns_transaction_complete(t, DNS_TRANSACTION_FAILURE);
-}
-
-static int on_transaction_timeout(sd_event_source *s, usec_t usec, void *userdata) {
- DnsTransaction *t = userdata;
- int r;
-
- assert(s);
- assert(t);
-
- /* Timeout reached? Try again, with a new server */
- dns_scope_next_dns_server(t->scope);
-
- r = dns_transaction_go(t);
- if (r < 0)
- dns_transaction_complete(t, DNS_TRANSACTION_RESOURCES);
-
- return 0;
-}
-
-static int dns_transaction_make_packet(DnsTransaction *t) {
- _cleanup_(dns_packet_unrefp) DnsPacket *p = NULL;
- unsigned n, added = 0;
- int r;
-
- assert(t);
-
- if (t->sent)
- return 0;
-
- r = dns_packet_new_query(&p, t->scope->protocol, 0);
- if (r < 0)
- return r;
-
- for (n = 0; n < t->question->n_keys; n++) {
- r = dns_scope_good_key(t->scope, t->question->keys[n]);
- if (r < 0)
- return r;
- if (r == 0)
- continue;
-
- r = dns_packet_append_key(p, t->question->keys[n], NULL);
- if (r < 0)
- return r;
-
- added++;
- }
-
- if (added <= 0)
- return -EDOM;
-
- DNS_PACKET_HEADER(p)->qdcount = htobe16(added);
- DNS_PACKET_HEADER(p)->id = t->id;
-
- t->sent = p;
- p = NULL;
-
- return 0;
-}
-
-int dns_transaction_go(DnsTransaction *t) {
- bool had_stream;
- int r;
-
- assert(t);
-
- had_stream = !!t->stream;
-
- dns_transaction_stop(t);
-
- log_debug("Excercising transaction on scope %s on %s/%s",
- dns_protocol_to_string(t->scope->protocol),
- t->scope->link ? t->scope->link->name : "*",
- t->scope->family == AF_UNSPEC ? "*" : af_to_name(t->scope->family));
-
- if (t->n_attempts >= TRANSACTION_ATTEMPTS_MAX(t->scope->protocol)) {
- dns_transaction_complete(t, DNS_TRANSACTION_ATTEMPTS_MAX_REACHED);
- return 0;
- }
-
- if (t->scope->protocol == DNS_PROTOCOL_LLMNR && had_stream) {
- /* If we already tried via a stream, then we don't
- * retry on LLMNR. See RFC 4795, Section 2.7. */
- dns_transaction_complete(t, DNS_TRANSACTION_ATTEMPTS_MAX_REACHED);
- return 0;
- }
-
- t->n_attempts++;
- t->received = dns_packet_unref(t->received);
- t->cached = dns_answer_unref(t->cached);
- t->cached_rcode = 0;
-
- /* Check the cache, but only if this transaction is not used
- * for probing or verifying a zone item. */
- if (set_isempty(t->zone_items)) {
-
- /* Before trying the cache, let's make sure we figured out a
- * server to use. Should this cause a change of server this
- * might flush the cache. */
- dns_scope_get_dns_server(t->scope);
-
- /* Let's then prune all outdated entries */
- dns_cache_prune(&t->scope->cache);
-
- r = dns_cache_lookup(&t->scope->cache, t->question, &t->cached_rcode, &t->cached);
- if (r < 0)
- return r;
- if (r > 0) {
- log_debug("Cache hit!");
- if (t->cached_rcode == DNS_RCODE_SUCCESS)
- dns_transaction_complete(t, DNS_TRANSACTION_SUCCESS);
- else
- dns_transaction_complete(t, DNS_TRANSACTION_FAILURE);
- return 0;
- }
- }
-
- if (t->scope->protocol == DNS_PROTOCOL_LLMNR && !t->initial_jitter) {
- usec_t jitter;
-
- /* RFC 4795 Section 2.7 suggests all queries should be
- * delayed by a random time from 0 to JITTER_INTERVAL. */
-
- t->initial_jitter = true;
-
- random_bytes(&jitter, sizeof(jitter));
- jitter %= LLMNR_JITTER_INTERVAL_USEC;
-
- r = sd_event_add_time(
- t->scope->manager->event,
- &t->timeout_event_source,
- clock_boottime_or_monotonic(),
- now(clock_boottime_or_monotonic()) + jitter,
- LLMNR_JITTER_INTERVAL_USEC,
- on_transaction_timeout, t);
- if (r < 0)
- return r;
-
- t->n_attempts = 0;
- t->state = DNS_TRANSACTION_PENDING;
-
- log_debug("Delaying LLMNR transaction for " USEC_FMT "us.", jitter);
- return 0;
- }
-
- log_debug("Cache miss!");
-
- /* Otherwise, we need to ask the network */
- r = dns_transaction_make_packet(t);
- if (r == -EDOM) {
- /* Not the right request to make on this network?
- * (i.e. an A request made on IPv6 or an AAAA request
- * made on IPv4, on LLMNR or mDNS.) */
- dns_transaction_complete(t, DNS_TRANSACTION_NO_SERVERS);
- return 0;
- }
- if (r < 0)
- return r;
-
- if (t->scope->protocol == DNS_PROTOCOL_LLMNR &&
- (dns_question_endswith(t->question, "in-addr.arpa") > 0 ||
- dns_question_endswith(t->question, "ip6.arpa") > 0)) {
-
- /* RFC 4795, Section 2.4. says reverse lookups shall
- * always be made via TCP on LLMNR */
- r = dns_transaction_open_tcp(t);
- } else {
- /* Try via UDP, and if that fails due to large size try via TCP */
- r = dns_scope_emit(t->scope, t->sent);
- if (r == -EMSGSIZE)
- r = dns_transaction_open_tcp(t);
- }
- if (r == -ESRCH) {
- /* No servers to send this to? */
- dns_transaction_complete(t, DNS_TRANSACTION_NO_SERVERS);
- return 0;
- }
- if (r < 0) {
- if (t->scope->protocol != DNS_PROTOCOL_DNS) {
- dns_transaction_complete(t, DNS_TRANSACTION_RESOURCES);
- return 0;
- }
-
- /* Couldn't send? Try immediately again, with a new server */
- dns_scope_next_dns_server(t->scope);
-
- return dns_transaction_go(t);
- }
-
- r = sd_event_add_time(
- t->scope->manager->event,
- &t->timeout_event_source,
- clock_boottime_or_monotonic(),
- now(clock_boottime_or_monotonic()) + TRANSACTION_TIMEOUT_USEC(t->scope->protocol), 0,
- on_transaction_timeout, t);
- if (r < 0)
- return r;
-
- t->state = DNS_TRANSACTION_PENDING;
- return 1;
-}
-
-static const char* const dns_transaction_state_table[_DNS_TRANSACTION_STATE_MAX] = {
- [DNS_TRANSACTION_NULL] = "null",
- [DNS_TRANSACTION_PENDING] = "pending",
- [DNS_TRANSACTION_FAILURE] = "failure",
- [DNS_TRANSACTION_SUCCESS] = "success",
- [DNS_TRANSACTION_NO_SERVERS] = "no-servers",
- [DNS_TRANSACTION_TIMEOUT] = "timeout",
- [DNS_TRANSACTION_ATTEMPTS_MAX_REACHED] = "attempts-max-reached",
- [DNS_TRANSACTION_INVALID_REPLY] = "invalid-reply",
- [DNS_TRANSACTION_RESOURCES] = "resources",
- [DNS_TRANSACTION_ABORTED] = "aborted",
-};
-DEFINE_STRING_TABLE_LOOKUP(dns_transaction_state, DnsTransactionState);
diff --git a/src/resolve/resolved-dns-transaction.h b/src/resolve/resolved-dns-transaction.h
deleted file mode 100644
index f6d539d315..0000000000
--- a/src/resolve/resolved-dns-transaction.h
+++ /dev/null
@@ -1,108 +0,0 @@
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
-#pragma once
-
-/***
- This file is part of systemd.
-
- Copyright 2014 Lennart Poettering
-
- systemd is free software; you can redistribute it and/or modify it
- under the terms of the GNU Lesser General Public License as published by
- the Free Software Foundation; either version 2.1 of the License, or
- (at your option) any later version.
-
- systemd is distributed in the hope that it will be useful, but
- WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Lesser General Public License for more details.
-
- You should have received a copy of the GNU Lesser General Public License
- along with systemd; If not, see <http://www.gnu.org/licenses/>.
-***/
-
-typedef struct DnsTransaction DnsTransaction;
-typedef enum DnsTransactionState DnsTransactionState;
-
-enum DnsTransactionState {
- DNS_TRANSACTION_NULL,
- DNS_TRANSACTION_PENDING,
- DNS_TRANSACTION_FAILURE,
- DNS_TRANSACTION_SUCCESS,
- DNS_TRANSACTION_NO_SERVERS,
- DNS_TRANSACTION_TIMEOUT,
- DNS_TRANSACTION_ATTEMPTS_MAX_REACHED,
- DNS_TRANSACTION_INVALID_REPLY,
- DNS_TRANSACTION_RESOURCES,
- DNS_TRANSACTION_ABORTED,
- _DNS_TRANSACTION_STATE_MAX,
- _DNS_TRANSACTION_STATE_INVALID = -1
-};
-
-#include "resolved-dns-scope.h"
-#include "resolved-dns-packet.h"
-#include "resolved-dns-question.h"
-#include "resolved-dns-answer.h"
-
-struct DnsTransaction {
- DnsScope *scope;
-
- DnsQuestion *question;
-
- DnsTransactionState state;
- uint16_t id;
-
- bool initial_jitter;
-
- DnsPacket *sent, *received;
- DnsAnswer *cached;
- int cached_rcode;
-
- sd_event_source *timeout_event_source;
- unsigned n_attempts;
-
- /* TCP connection logic, if we need it */
- DnsStream *stream;
-
- /* Queries this transaction is referenced by and that shall be
- * notified about this specific transaction completing. */
- Set *queries;
-
- /* Zone items this transaction is referenced by and that shall
- * be notified about completion. */
- Set *zone_items;
-
- unsigned block_gc;
-
- LIST_FIELDS(DnsTransaction, transactions_by_scope);
-};
-
-int dns_transaction_new(DnsTransaction **ret, DnsScope *s, DnsQuestion *q);
-DnsTransaction* dns_transaction_free(DnsTransaction *t);
-
-void dns_transaction_gc(DnsTransaction *t);
-int dns_transaction_go(DnsTransaction *t);
-
-void dns_transaction_process_reply(DnsTransaction *t, DnsPacket *p);
-void dns_transaction_complete(DnsTransaction *t, DnsTransactionState state);
-
-const char* dns_transaction_state_to_string(DnsTransactionState p) _const_;
-DnsTransactionState dns_transaction_state_from_string(const char *s) _pure_;
-
-/* After how much time to repeat classic DNS requests */
-#define DNS_TRANSACTION_TIMEOUT_USEC (5 * USEC_PER_SEC)
-
-/* After how much time to repeat LLMNR requests, see RFC 4795 Section 7 */
-#define LLMNR_TRANSACTION_TIMEOUT_USEC (1 * USEC_PER_SEC)
-
-/* LLMNR Jitter interval, see RFC 4795 Section 7 */
-#define LLMNR_JITTER_INTERVAL_USEC (100 * USEC_PER_MSEC)
-
-/* Maximum attempts to send DNS requests, across all DNS servers */
-#define DNS_TRANSACTION_ATTEMPTS_MAX 8
-
-/* Maximum attempts to send LLMNR requests, see RFC 4795 Section 2.7 */
-#define LLMNR_TRANSACTION_ATTEMPTS_MAX 3
-
-#define TRANSACTION_TIMEOUT_USEC(p) (p == DNS_PROTOCOL_LLMNR ? LLMNR_TRANSACTION_TIMEOUT_USEC : DNS_TRANSACTION_TIMEOUT_USEC)
-#define TRANSACTION_ATTEMPTS_MAX(p) (p == DNS_PROTOCOL_LLMNR ? LLMNR_TRANSACTION_ATTEMPTS_MAX : DNS_TRANSACTION_ATTEMPTS_MAX)
diff --git a/src/resolve/resolved-dns-zone.c b/src/resolve/resolved-dns-zone.c
deleted file mode 100644
index a4c9b7d7af..0000000000
--- a/src/resolve/resolved-dns-zone.c
+++ /dev/null
@@ -1,648 +0,0 @@
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
-/***
- This file is part of systemd.
-
- Copyright 2014 Lennart Poettering
-
- systemd is free software; you can redistribute it and/or modify it
- under the terms of the GNU Lesser General Public License as published by
- the Free Software Foundation; either version 2.1 of the License, or
- (at your option) any later version.
-
- systemd is distributed in the hope that it will be useful, but
- WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Lesser General Public License for more details.
-
- You should have received a copy of the GNU Lesser General Public License
- along with systemd; If not, see <http://www.gnu.org/licenses/>.
-***/
-
-#include "list.h"
-
-#include "resolved-dns-zone.h"
-#include "resolved-dns-domain.h"
-#include "resolved-dns-packet.h"
-
-/* Never allow more than 1K entries */
-#define ZONE_MAX 1024
-
-void dns_zone_item_probe_stop(DnsZoneItem *i) {
- DnsTransaction *t;
- assert(i);
-
- if (!i->probe_transaction)
- return;
-
- t = i->probe_transaction;
- i->probe_transaction = NULL;
-
- set_remove(t->zone_items, i);
- dns_transaction_gc(t);
-}
-
-static void dns_zone_item_free(DnsZoneItem *i) {
- if (!i)
- return;
-
- dns_zone_item_probe_stop(i);
- dns_resource_record_unref(i->rr);
-
- free(i);
-}
-
-DEFINE_TRIVIAL_CLEANUP_FUNC(DnsZoneItem*, dns_zone_item_free);
-
-static void dns_zone_item_remove_and_free(DnsZone *z, DnsZoneItem *i) {
- DnsZoneItem *first;
-
- assert(z);
-
- if (!i)
- return;
-
- first = hashmap_get(z->by_key, i->rr->key);
- LIST_REMOVE(by_key, first, i);
- if (first)
- assert_se(hashmap_replace(z->by_key, first->rr->key, first) >= 0);
- else
- hashmap_remove(z->by_key, i->rr->key);
-
- first = hashmap_get(z->by_name, DNS_RESOURCE_KEY_NAME(i->rr->key));
- LIST_REMOVE(by_name, first, i);
- if (first)
- assert_se(hashmap_replace(z->by_name, DNS_RESOURCE_KEY_NAME(first->rr->key), first) >= 0);
- else
- hashmap_remove(z->by_name, DNS_RESOURCE_KEY_NAME(i->rr->key));
-
- dns_zone_item_free(i);
-}
-
-void dns_zone_flush(DnsZone *z) {
- DnsZoneItem *i;
-
- assert(z);
-
- while ((i = hashmap_first(z->by_key)))
- dns_zone_item_remove_and_free(z, i);
-
- assert(hashmap_size(z->by_key) == 0);
- assert(hashmap_size(z->by_name) == 0);
-
- hashmap_free(z->by_key);
- z->by_key = NULL;
-
- hashmap_free(z->by_name);
- z->by_name = NULL;
-}
-
-static DnsZoneItem* dns_zone_get(DnsZone *z, DnsResourceRecord *rr) {
- DnsZoneItem *i;
-
- assert(z);
- assert(rr);
-
- LIST_FOREACH(by_key, i, hashmap_get(z->by_key, rr->key))
- if (dns_resource_record_equal(i->rr, rr) > 0)
- return i;
-
- return NULL;
-}
-
-void dns_zone_remove_rr(DnsZone *z, DnsResourceRecord *rr) {
- DnsZoneItem *i;
-
- assert(z);
- assert(rr);
-
- i = dns_zone_get(z, rr);
- if (i)
- dns_zone_item_remove_and_free(z, i);
-}
-
-static int dns_zone_init(DnsZone *z) {
- int r;
-
- assert(z);
-
- r = hashmap_ensure_allocated(&z->by_key, &dns_resource_key_hash_ops);
- if (r < 0)
- return r;
-
- r = hashmap_ensure_allocated(&z->by_name, &dns_name_hash_ops);
- if (r < 0)
- return r;
-
- return 0;
-}
-
-static int dns_zone_link_item(DnsZone *z, DnsZoneItem *i) {
- DnsZoneItem *first;
- int r;
-
- first = hashmap_get(z->by_key, i->rr->key);
- if (first) {
- LIST_PREPEND(by_key, first, i);
- assert_se(hashmap_replace(z->by_key, first->rr->key, first) >= 0);
- } else {
- r = hashmap_put(z->by_key, i->rr->key, i);
- if (r < 0)
- return r;
- }
-
- first = hashmap_get(z->by_name, DNS_RESOURCE_KEY_NAME(i->rr->key));
- if (first) {
- LIST_PREPEND(by_name, first, i);
- assert_se(hashmap_replace(z->by_name, DNS_RESOURCE_KEY_NAME(first->rr->key), first) >= 0);
- } else {
- r = hashmap_put(z->by_name, DNS_RESOURCE_KEY_NAME(i->rr->key), i);
- if (r < 0)
- return r;
- }
-
- return 0;
-}
-
-static int dns_zone_item_probe_start(DnsZoneItem *i) {
- _cleanup_(dns_resource_key_unrefp) DnsResourceKey *key = NULL;
- _cleanup_(dns_question_unrefp) DnsQuestion *question = NULL;
- DnsTransaction *t;
- int r;
-
- assert(i);
-
- if (i->probe_transaction)
- return 0;
-
- key = dns_resource_key_new(i->rr->key->class, DNS_TYPE_ANY, DNS_RESOURCE_KEY_NAME(i->rr->key));
- if (!key)
- return -ENOMEM;
-
- question = dns_question_new(1);
- if (!question)
- return -ENOMEM;
-
- r = dns_question_add(question, key);
- if (r < 0)
- return r;
-
- t = dns_scope_find_transaction(i->scope, question, false);
- if (!t) {
- r = dns_transaction_new(&t, i->scope, question);
- if (r < 0)
- return r;
- }
-
- r = set_ensure_allocated(&t->zone_items, NULL);
- if (r < 0)
- goto gc;
-
- r = set_put(t->zone_items, i);
- if (r < 0)
- goto gc;
-
- i->probe_transaction = t;
-
- if (t->state == DNS_TRANSACTION_NULL) {
-
- i->block_ready++;
- r = dns_transaction_go(t);
- i->block_ready--;
-
- if (r < 0) {
- dns_zone_item_probe_stop(i);
- return r;
- }
- }
-
- dns_zone_item_ready(i);
-
- return 0;
-
-gc:
- dns_transaction_gc(t);
- return r;
-}
-
-int dns_zone_put(DnsZone *z, DnsScope *s, DnsResourceRecord *rr, bool probe) {
- _cleanup_(dns_zone_item_freep) DnsZoneItem *i = NULL;
- DnsZoneItem *existing;
- int r;
-
- assert(z);
- assert(s);
- assert(rr);
-
- if (rr->key->class == DNS_CLASS_ANY)
- return -EINVAL;
- if (rr->key->type == DNS_TYPE_ANY)
- return -EINVAL;
-
- existing = dns_zone_get(z, rr);
- if (existing)
- return 0;
-
- r = dns_zone_init(z);
- if (r < 0)
- return r;
-
- i = new0(DnsZoneItem, 1);
- if (!i)
- return -ENOMEM;
-
- i->scope = s;
- i->rr = dns_resource_record_ref(rr);
- i->probing_enabled = probe;
-
- r = dns_zone_link_item(z, i);
- if (r < 0)
- return r;
-
- if (probe) {
- DnsZoneItem *first, *j;
- bool established = false;
-
- /* Check if there's already an RR with the same name
- * established. If so, it has been probed already, and
- * we don't ned to probe again. */
-
- LIST_FIND_HEAD(by_name, i, first);
- LIST_FOREACH(by_name, j, first) {
- if (i == j)
- continue;
-
- if (j->state == DNS_ZONE_ITEM_ESTABLISHED)
- established = true;
- }
-
- if (established)
- i->state = DNS_ZONE_ITEM_ESTABLISHED;
- else {
- i->state = DNS_ZONE_ITEM_PROBING;
-
- r = dns_zone_item_probe_start(i);
- if (r < 0) {
- dns_zone_item_remove_and_free(z, i);
- i = NULL;
- return r;
- }
- }
- } else
- i->state = DNS_ZONE_ITEM_ESTABLISHED;
-
- i = NULL;
- return 0;
-}
-
-int dns_zone_lookup(DnsZone *z, DnsQuestion *q, DnsAnswer **ret_answer, DnsAnswer **ret_soa, bool *ret_tentative) {
- _cleanup_(dns_answer_unrefp) DnsAnswer *answer = NULL, *soa = NULL;
- unsigned i, n_answer = 0, n_soa = 0;
- bool tentative = true;
- int r;
-
- assert(z);
- assert(q);
- assert(ret_answer);
- assert(ret_soa);
-
- if (q->n_keys <= 0) {
- *ret_answer = NULL;
- *ret_soa = NULL;
-
- if (ret_tentative)
- *ret_tentative = false;
-
- return 0;
- }
-
- /* First iteration, count what we have */
- for (i = 0; i < q->n_keys; i++) {
- DnsZoneItem *j, *first;
-
- if (q->keys[i]->type == DNS_TYPE_ANY ||
- q->keys[i]->class == DNS_CLASS_ANY) {
- bool found = false, added = false;
- int k;
-
- /* If this is a generic match, then we have to
- * go through the list by the name and look
- * for everything manually */
-
- first = hashmap_get(z->by_name, DNS_RESOURCE_KEY_NAME(q->keys[i]));
- LIST_FOREACH(by_name, j, first) {
- if (!IN_SET(j->state, DNS_ZONE_ITEM_PROBING, DNS_ZONE_ITEM_ESTABLISHED, DNS_ZONE_ITEM_VERIFYING))
- continue;
-
- found = true;
-
- k = dns_resource_key_match_rr(q->keys[i], j->rr);
- if (k < 0)
- return k;
- if (k > 0) {
- n_answer++;
- added = true;
- }
-
- }
-
- if (found && !added)
- n_soa++;
-
- } else {
- bool found = false;
-
- /* If this is a specific match, then look for
- * the right key immediately */
-
- first = hashmap_get(z->by_key, q->keys[i]);
- LIST_FOREACH(by_key, j, first) {
- if (!IN_SET(j->state, DNS_ZONE_ITEM_PROBING, DNS_ZONE_ITEM_ESTABLISHED, DNS_ZONE_ITEM_VERIFYING))
- continue;
-
- found = true;
- n_answer++;
- }
-
- if (!found) {
- first = hashmap_get(z->by_name, DNS_RESOURCE_KEY_NAME(q->keys[i]));
- LIST_FOREACH(by_name, j, first) {
- if (!IN_SET(j->state, DNS_ZONE_ITEM_PROBING, DNS_ZONE_ITEM_ESTABLISHED, DNS_ZONE_ITEM_VERIFYING))
- continue;
-
- n_soa++;
- break;
- }
- }
- }
- }
-
- if (n_answer <= 0 && n_soa <= 0) {
- *ret_answer = NULL;
- *ret_soa = NULL;
-
- if (ret_tentative)
- *ret_tentative = false;
-
- return 0;
- }
-
- if (n_answer > 0) {
- answer = dns_answer_new(n_answer);
- if (!answer)
- return -ENOMEM;
- }
-
- if (n_soa > 0) {
- soa = dns_answer_new(n_soa);
- if (!soa)
- return -ENOMEM;
- }
-
- /* Second iteration, actually add the RRs to the answers */
- for (i = 0; i < q->n_keys; i++) {
- DnsZoneItem *j, *first;
-
- if (q->keys[i]->type == DNS_TYPE_ANY ||
- q->keys[i]->class == DNS_CLASS_ANY) {
- bool found = false, added = false;
- int k;
-
- first = hashmap_get(z->by_name, DNS_RESOURCE_KEY_NAME(q->keys[i]));
- LIST_FOREACH(by_name, j, first) {
- if (!IN_SET(j->state, DNS_ZONE_ITEM_PROBING, DNS_ZONE_ITEM_ESTABLISHED, DNS_ZONE_ITEM_VERIFYING))
- continue;
-
- found = true;
-
- if (j->state != DNS_ZONE_ITEM_PROBING)
- tentative = false;
-
- k = dns_resource_key_match_rr(q->keys[i], j->rr);
- if (k < 0)
- return k;
- if (k > 0) {
- r = dns_answer_add(answer, j->rr);
- if (r < 0)
- return r;
-
- added = true;
- }
- }
-
- if (found && !added) {
- r = dns_answer_add_soa(soa, DNS_RESOURCE_KEY_NAME(q->keys[i]), LLMNR_DEFAULT_TTL);
- if (r < 0)
- return r;
- }
- } else {
- bool found = false;
-
- first = hashmap_get(z->by_key, q->keys[i]);
- LIST_FOREACH(by_key, j, first) {
- if (!IN_SET(j->state, DNS_ZONE_ITEM_PROBING, DNS_ZONE_ITEM_ESTABLISHED, DNS_ZONE_ITEM_VERIFYING))
- continue;
-
- found = true;
-
- if (j->state != DNS_ZONE_ITEM_PROBING)
- tentative = false;
-
- r = dns_answer_add(answer, j->rr);
- if (r < 0)
- return r;
- }
-
- if (!found) {
- bool add_soa = false;
-
- first = hashmap_get(z->by_name, DNS_RESOURCE_KEY_NAME(q->keys[i]));
- LIST_FOREACH(by_name, j, first) {
- if (!IN_SET(j->state, DNS_ZONE_ITEM_PROBING, DNS_ZONE_ITEM_ESTABLISHED, DNS_ZONE_ITEM_VERIFYING))
- continue;
-
- if (j->state != DNS_ZONE_ITEM_PROBING)
- tentative = false;
-
- add_soa = true;
- }
-
- if (add_soa) {
- r = dns_answer_add_soa(soa, DNS_RESOURCE_KEY_NAME(q->keys[i]), LLMNR_DEFAULT_TTL);
- if (r < 0)
- return r;
- }
- }
- }
- }
-
- *ret_answer = answer;
- answer = NULL;
-
- *ret_soa = soa;
- soa = NULL;
-
- if (ret_tentative)
- *ret_tentative = tentative;
-
- return 1;
-}
-
-void dns_zone_item_conflict(DnsZoneItem *i) {
- _cleanup_free_ char *pretty = NULL;
-
- assert(i);
-
- if (!IN_SET(i->state, DNS_ZONE_ITEM_PROBING, DNS_ZONE_ITEM_VERIFYING, DNS_ZONE_ITEM_ESTABLISHED))
- return;
-
- dns_resource_record_to_string(i->rr, &pretty);
- log_info("Detected conflict on %s", strna(pretty));
-
- dns_zone_item_probe_stop(i);
-
- /* Withdraw the conflict item */
- i->state = DNS_ZONE_ITEM_WITHDRAWN;
-
- /* Maybe change the hostname */
- if (dns_name_equal(i->scope->manager->hostname, DNS_RESOURCE_KEY_NAME(i->rr->key)) > 0)
- manager_next_hostname(i->scope->manager);
-}
-
-void dns_zone_item_ready(DnsZoneItem *i) {
- _cleanup_free_ char *pretty = NULL;
-
- assert(i);
- assert(i->probe_transaction);
-
- if (i->block_ready > 0)
- return;
-
- if (IN_SET(i->probe_transaction->state, DNS_TRANSACTION_NULL, DNS_TRANSACTION_PENDING))
- return;
-
- if (i->probe_transaction->state == DNS_TRANSACTION_SUCCESS) {
- bool we_lost = false;
-
- /* The probe got a successful reply. If we so far
- * weren't established we just give up. If we already
- * were established, and the peer has the
- * lexicographically larger IP address we continue
- * and defend it. */
-
- if (!IN_SET(i->state, DNS_ZONE_ITEM_ESTABLISHED, DNS_ZONE_ITEM_VERIFYING)) {
- log_debug("Got a successful probe for not yet established RR, we lost.");
- we_lost = true;
- } else {
- assert(i->probe_transaction->received);
- we_lost = memcmp(&i->probe_transaction->received->sender, &i->probe_transaction->received->destination, FAMILY_ADDRESS_SIZE(i->probe_transaction->received->family)) < 0;
- if (we_lost)
- log_debug("Got a successful probe reply for an established RR, and we have a lexicographically larger IP address and thus lost.");
- }
-
- if (we_lost) {
- dns_zone_item_conflict(i);
- return;
- }
-
- log_debug("Got a successful probe reply, but peer has lexicographically lower IP address and thus lost.");
- }
-
- dns_resource_record_to_string(i->rr, &pretty);
- log_debug("Record %s successfully probed.", strna(pretty));
-
- dns_zone_item_probe_stop(i);
- i->state = DNS_ZONE_ITEM_ESTABLISHED;
-}
-
-static int dns_zone_item_verify(DnsZoneItem *i) {
- _cleanup_free_ char *pretty = NULL;
- int r;
-
- assert(i);
-
- if (i->state != DNS_ZONE_ITEM_ESTABLISHED)
- return 0;
-
- dns_resource_record_to_string(i->rr, &pretty);
- log_debug("Verifying RR %s", strna(pretty));
-
- i->state = DNS_ZONE_ITEM_VERIFYING;
- r = dns_zone_item_probe_start(i);
- if (r < 0) {
- log_error_errno(r, "Failed to start probing for verifying RR: %m");
- i->state = DNS_ZONE_ITEM_ESTABLISHED;
- return r;
- }
-
- return 0;
-}
-
-int dns_zone_check_conflicts(DnsZone *zone, DnsResourceRecord *rr) {
- DnsZoneItem *i, *first;
- int c = 0;
-
- assert(zone);
- assert(rr);
-
- /* This checks whether a response RR we received from somebody
- * else is one that we actually thought was uniquely ours. If
- * so, we'll verify our RRs. */
-
- /* No conflict if we don't have the name at all. */
- first = hashmap_get(zone->by_name, DNS_RESOURCE_KEY_NAME(rr->key));
- if (!first)
- return 0;
-
- /* No conflict if we have the exact same RR */
- if (dns_zone_get(zone, rr))
- return 0;
-
- /* OK, somebody else has RRs for the same name. Yuck! Let's
- * start probing again */
-
- LIST_FOREACH(by_name, i, first) {
- if (dns_resource_record_equal(i->rr, rr))
- continue;
-
- dns_zone_item_verify(i);
- c++;
- }
-
- return c;
-}
-
-int dns_zone_verify_conflicts(DnsZone *zone, DnsResourceKey *key) {
- DnsZoneItem *i, *first;
- int c = 0;
-
- assert(zone);
-
- /* Somebody else notified us about a possible conflict. Let's
- * verify if that's true. */
-
- first = hashmap_get(zone->by_name, DNS_RESOURCE_KEY_NAME(key));
- if (!first)
- return 0;
-
- LIST_FOREACH(by_name, i, first) {
- dns_zone_item_verify(i);
- c++;
- }
-
- return c;
-}
-
-void dns_zone_verify_all(DnsZone *zone) {
- DnsZoneItem *i;
- Iterator iterator;
-
- assert(zone);
-
- HASHMAP_FOREACH(i, zone->by_key, iterator) {
- DnsZoneItem *j;
-
- LIST_FOREACH(by_key, j, i)
- dns_zone_item_verify(j);
- }
-}
diff --git a/src/resolve/resolved-dns-zone.h b/src/resolve/resolved-dns-zone.h
deleted file mode 100644
index 71851265c6..0000000000
--- a/src/resolve/resolved-dns-zone.h
+++ /dev/null
@@ -1,80 +0,0 @@
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
-#pragma once
-
-/***
- This file is part of systemd.
-
- Copyright 2014 Lennart Poettering
-
- systemd is free software; you can redistribute it and/or modify it
- under the terms of the GNU Lesser General Public License as published by
- the Free Software Foundation; either version 2.1 of the License, or
- (at your option) any later version.
-
- systemd is distributed in the hope that it will be useful, but
- WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Lesser General Public License for more details.
-
- You should have received a copy of the GNU Lesser General Public License
- along with systemd; If not, see <http://www.gnu.org/licenses/>.
-***/
-
-#include "hashmap.h"
-
-typedef struct DnsZone {
- Hashmap *by_key;
- Hashmap *by_name;
-} DnsZone;
-
-typedef struct DnsZoneItem DnsZoneItem;
-typedef enum DnsZoneItemState DnsZoneItemState;
-
-#include "resolved-dns-rr.h"
-#include "resolved-dns-question.h"
-#include "resolved-dns-answer.h"
-#include "resolved-dns-transaction.h"
-
-/* RFC 4795 Section 2.8. suggests a TTL of 30s by default */
-#define LLMNR_DEFAULT_TTL (30)
-
-enum DnsZoneItemState {
- DNS_ZONE_ITEM_PROBING,
- DNS_ZONE_ITEM_ESTABLISHED,
- DNS_ZONE_ITEM_VERIFYING,
- DNS_ZONE_ITEM_WITHDRAWN,
-};
-
-struct DnsZoneItem {
- DnsScope *scope;
- DnsResourceRecord *rr;
-
- DnsZoneItemState state;
-
- unsigned block_ready;
-
- bool probing_enabled;
-
- LIST_FIELDS(DnsZoneItem, by_key);
- LIST_FIELDS(DnsZoneItem, by_name);
-
- DnsTransaction *probe_transaction;
-};
-
-void dns_zone_flush(DnsZone *z);
-
-int dns_zone_put(DnsZone *z, DnsScope *s, DnsResourceRecord *rr, bool probe);
-void dns_zone_remove_rr(DnsZone *z, DnsResourceRecord *rr);
-
-int dns_zone_lookup(DnsZone *z, DnsQuestion *q, DnsAnswer **answer, DnsAnswer **soa, bool *tentative);
-
-void dns_zone_item_conflict(DnsZoneItem *i);
-void dns_zone_item_ready(DnsZoneItem *i);
-
-int dns_zone_check_conflicts(DnsZone *zone, DnsResourceRecord *rr);
-int dns_zone_verify_conflicts(DnsZone *zone, DnsResourceKey *key);
-
-void dns_zone_verify_all(DnsZone *zone);
-
-void dns_zone_item_probe_stop(DnsZoneItem *i);
diff --git a/src/resolve/resolved-gperf.gperf b/src/resolve/resolved-gperf.gperf
deleted file mode 100644
index 8e78fbf06a..0000000000
--- a/src/resolve/resolved-gperf.gperf
+++ /dev/null
@@ -1,19 +0,0 @@
-%{
-#include <stddef.h>
-#include "conf-parser.h"
-#include "resolved-conf.h"
-%}
-struct ConfigPerfItem;
-%null_strings
-%language=ANSI-C
-%define slot-name section_and_lvalue
-%define hash-function-name resolved_gperf_hash
-%define lookup-function-name resolved_gperf_lookup
-%readonly-tables
-%omit-struct-type
-%struct-type
-%includes
-%%
-Resolve.DNS, config_parse_dnsv, DNS_SERVER_SYSTEM, 0
-Resolve.FallbackDNS, config_parse_dnsv, DNS_SERVER_FALLBACK, 0
-Resolve.LLMNR, config_parse_support, 0, offsetof(Manager, llmnr_support)
diff --git a/src/resolve/resolved-link.c b/src/resolve/resolved-link.c
deleted file mode 100644
index f94e4bb6f0..0000000000
--- a/src/resolve/resolved-link.c
+++ /dev/null
@@ -1,552 +0,0 @@
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
-/***
- This file is part of systemd.
-
- Copyright 2014 Lennart Poettering
-
- systemd is free software; you can redistribute it and/or modify it
- under the terms of the GNU Lesser General Public License as published by
- the Free Software Foundation; either version 2.1 of the License, or
- (at your option) any later version.
-
- systemd is distributed in the hope that it will be useful, but
- WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Lesser General Public License for more details.
-
- You should have received a copy of the GNU Lesser General Public License
- along with systemd; If not, see <http://www.gnu.org/licenses/>.
-***/
-
-#include <net/if.h>
-
-#include "sd-network.h"
-#include "strv.h"
-#include "missing.h"
-#include "resolved-link.h"
-
-int link_new(Manager *m, Link **ret, int ifindex) {
- _cleanup_(link_freep) Link *l = NULL;
- int r;
-
- assert(m);
- assert(ifindex > 0);
-
- r = hashmap_ensure_allocated(&m->links, NULL);
- if (r < 0)
- return r;
-
- l = new0(Link, 1);
- if (!l)
- return -ENOMEM;
-
- l->ifindex = ifindex;
- l->llmnr_support = SUPPORT_YES;
-
- r = hashmap_put(m->links, INT_TO_PTR(ifindex), l);
- if (r < 0)
- return r;
-
- l->manager = m;
-
- if (ret)
- *ret = l;
- l = NULL;
-
- return 0;
-}
-
-Link *link_free(Link *l) {
-
- if (!l)
- return NULL;
-
- while (l->addresses)
- link_address_free(l->addresses);
-
- if (l->manager)
- hashmap_remove(l->manager->links, INT_TO_PTR(l->ifindex));
-
- dns_scope_free(l->unicast_scope);
- dns_scope_free(l->llmnr_ipv4_scope);
- dns_scope_free(l->llmnr_ipv6_scope);
-
- while (l->dns_servers)
- dns_server_free(l->dns_servers);
-
- free(l);
- return NULL;
-}
-
-static void link_allocate_scopes(Link *l) {
- int r;
-
- assert(l);
-
- if (l->dns_servers) {
- if (!l->unicast_scope) {
- r = dns_scope_new(l->manager, &l->unicast_scope, l, DNS_PROTOCOL_DNS, AF_UNSPEC);
- if (r < 0)
- log_warning_errno(r, "Failed to allocate DNS scope: %m");
- }
- } else
- l->unicast_scope = dns_scope_free(l->unicast_scope);
-
- if (link_relevant(l, AF_INET) &&
- l->llmnr_support != SUPPORT_NO &&
- l->manager->llmnr_support != SUPPORT_NO) {
- if (!l->llmnr_ipv4_scope) {
- r = dns_scope_new(l->manager, &l->llmnr_ipv4_scope, l, DNS_PROTOCOL_LLMNR, AF_INET);
- if (r < 0)
- log_warning_errno(r, "Failed to allocate LLMNR IPv4 scope: %m");
- }
- } else
- l->llmnr_ipv4_scope = dns_scope_free(l->llmnr_ipv4_scope);
-
- if (link_relevant(l, AF_INET6) &&
- l->llmnr_support != SUPPORT_NO &&
- l->manager->llmnr_support != SUPPORT_NO &&
- socket_ipv6_is_supported()) {
- if (!l->llmnr_ipv6_scope) {
- r = dns_scope_new(l->manager, &l->llmnr_ipv6_scope, l, DNS_PROTOCOL_LLMNR, AF_INET6);
- if (r < 0)
- log_warning_errno(r, "Failed to allocate LLMNR IPv6 scope: %m");
- }
- } else
- l->llmnr_ipv6_scope = dns_scope_free(l->llmnr_ipv6_scope);
-}
-
-void link_add_rrs(Link *l, bool force_remove) {
- LinkAddress *a;
-
- LIST_FOREACH(addresses, a, l->addresses)
- link_address_add_rrs(a, force_remove);
-}
-
-int link_update_rtnl(Link *l, sd_rtnl_message *m) {
- const char *n = NULL;
- int r;
-
- assert(l);
- assert(m);
-
- r = sd_rtnl_message_link_get_flags(m, &l->flags);
- if (r < 0)
- return r;
-
- sd_rtnl_message_read_u32(m, IFLA_MTU, &l->mtu);
-
- if (sd_rtnl_message_read_string(m, IFLA_IFNAME, &n) >= 0) {
- strncpy(l->name, n, sizeof(l->name)-1);
- char_array_0(l->name);
- }
-
- link_allocate_scopes(l);
- link_add_rrs(l, false);
-
- return 0;
-}
-
-static int link_update_dns_servers(Link *l) {
- _cleanup_strv_free_ char **nameservers = NULL;
- char **nameserver;
- DnsServer *s, *nx;
- int r;
-
- assert(l);
-
- r = sd_network_link_get_dns(l->ifindex, &nameservers);
- if (r < 0)
- goto clear;
-
- LIST_FOREACH(servers, s, l->dns_servers)
- s->marked = true;
-
- STRV_FOREACH(nameserver, nameservers) {
- union in_addr_union a;
- int family;
-
- r = in_addr_from_string_auto(*nameserver, &family, &a);
- if (r < 0)
- goto clear;
-
- s = link_find_dns_server(l, family, &a);
- if (s)
- s->marked = false;
- else {
- r = dns_server_new(l->manager, NULL, DNS_SERVER_LINK, l, family, &a);
- if (r < 0)
- goto clear;
- }
- }
-
- LIST_FOREACH_SAFE(servers, s, nx, l->dns_servers)
- if (s->marked)
- dns_server_free(s);
-
- return 0;
-
-clear:
- while (l->dns_servers)
- dns_server_free(l->dns_servers);
-
- return r;
-}
-
-static int link_update_llmnr_support(Link *l) {
- _cleanup_free_ char *b = NULL;
- int r;
-
- assert(l);
-
- r = sd_network_link_get_llmnr(l->ifindex, &b);
- if (r < 0)
- goto clear;
-
- r = parse_boolean(b);
- if (r < 0) {
- if (streq(b, "resolve"))
- l->llmnr_support = SUPPORT_RESOLVE;
- else
- goto clear;
-
- } else if (r > 0)
- l->llmnr_support = SUPPORT_YES;
- else
- l->llmnr_support = SUPPORT_NO;
-
- return 0;
-
-clear:
- l->llmnr_support = SUPPORT_YES;
- return r;
-}
-
-static int link_update_domains(Link *l) {
- int r;
-
- if (!l->unicast_scope)
- return 0;
-
- strv_free(l->unicast_scope->domains);
- l->unicast_scope->domains = NULL;
-
- r = sd_network_link_get_domains(l->ifindex,
- &l->unicast_scope->domains);
- if (r < 0)
- return r;
-
- return 0;
-}
-
-int link_update_monitor(Link *l) {
- assert(l);
-
- link_update_dns_servers(l);
- link_update_llmnr_support(l);
- link_allocate_scopes(l);
- link_update_domains(l);
- link_add_rrs(l, false);
-
- return 0;
-}
-
-bool link_relevant(Link *l, int family) {
- _cleanup_free_ char *state = NULL;
- LinkAddress *a;
-
- assert(l);
-
- /* A link is relevant if it isn't a loopback or pointopoint
- * device, has a link beat, can do multicast and has at least
- * one relevant IP address */
-
- if (l->flags & (IFF_LOOPBACK|IFF_POINTOPOINT|IFF_DORMANT))
- return false;
-
- if ((l->flags & (IFF_UP|IFF_LOWER_UP|IFF_MULTICAST)) != (IFF_UP|IFF_LOWER_UP|IFF_MULTICAST))
- return false;
-
- sd_network_link_get_operational_state(l->ifindex, &state);
- if (state && !STR_IN_SET(state, "unknown", "degraded", "routable"))
- return false;
-
- LIST_FOREACH(addresses, a, l->addresses)
- if (a->family == family && link_address_relevant(a))
- return true;
-
- return false;
-}
-
-LinkAddress *link_find_address(Link *l, int family, const union in_addr_union *in_addr) {
- LinkAddress *a;
-
- assert(l);
-
- LIST_FOREACH(addresses, a, l->addresses)
- if (a->family == family && in_addr_equal(family, &a->in_addr, in_addr))
- return a;
-
- return NULL;
-}
-
-DnsServer* link_find_dns_server(Link *l, int family, const union in_addr_union *in_addr) {
- DnsServer *s;
-
- assert(l);
-
- LIST_FOREACH(servers, s, l->dns_servers)
- if (s->family == family && in_addr_equal(family, &s->address, in_addr))
- return s;
- return NULL;
-}
-
-DnsServer* link_set_dns_server(Link *l, DnsServer *s) {
- assert(l);
-
- if (l->current_dns_server == s)
- return s;
-
- if (s) {
- _cleanup_free_ char *ip = NULL;
-
- in_addr_to_string(s->family, &s->address, &ip);
- log_info("Switching to DNS server %s for interface %s.", strna(ip), l->name);
- }
-
- l->current_dns_server = s;
-
- if (l->unicast_scope)
- dns_cache_flush(&l->unicast_scope->cache);
-
- return s;
-}
-
-DnsServer *link_get_dns_server(Link *l) {
- assert(l);
-
- if (!l->current_dns_server)
- link_set_dns_server(l, l->dns_servers);
-
- return l->current_dns_server;
-}
-
-void link_next_dns_server(Link *l) {
- assert(l);
-
- if (!l->current_dns_server)
- return;
-
- if (l->current_dns_server->servers_next) {
- link_set_dns_server(l, l->current_dns_server->servers_next);
- return;
- }
-
- link_set_dns_server(l, l->dns_servers);
-}
-
-int link_address_new(Link *l, LinkAddress **ret, int family, const union in_addr_union *in_addr) {
- LinkAddress *a;
-
- assert(l);
- assert(in_addr);
-
- a = new0(LinkAddress, 1);
- if (!a)
- return -ENOMEM;
-
- a->family = family;
- a->in_addr = *in_addr;
-
- a->link = l;
- LIST_PREPEND(addresses, l->addresses, a);
-
- if (ret)
- *ret = a;
-
- return 0;
-}
-
-LinkAddress *link_address_free(LinkAddress *a) {
- if (!a)
- return NULL;
-
- if (a->link) {
- LIST_REMOVE(addresses, a->link->addresses, a);
-
- if (a->llmnr_address_rr) {
- if (a->family == AF_INET && a->link->llmnr_ipv4_scope)
- dns_zone_remove_rr(&a->link->llmnr_ipv4_scope->zone, a->llmnr_address_rr);
- else if (a->family == AF_INET6 && a->link->llmnr_ipv6_scope)
- dns_zone_remove_rr(&a->link->llmnr_ipv6_scope->zone, a->llmnr_address_rr);
- }
-
- if (a->llmnr_ptr_rr) {
- if (a->family == AF_INET && a->link->llmnr_ipv4_scope)
- dns_zone_remove_rr(&a->link->llmnr_ipv4_scope->zone, a->llmnr_ptr_rr);
- else if (a->family == AF_INET6 && a->link->llmnr_ipv6_scope)
- dns_zone_remove_rr(&a->link->llmnr_ipv6_scope->zone, a->llmnr_ptr_rr);
- }
- }
-
- dns_resource_record_unref(a->llmnr_address_rr);
- dns_resource_record_unref(a->llmnr_ptr_rr);
-
- free(a);
- return NULL;
-}
-
-void link_address_add_rrs(LinkAddress *a, bool force_remove) {
- int r;
-
- assert(a);
-
- if (a->family == AF_INET) {
-
- if (!force_remove &&
- link_address_relevant(a) &&
- a->link->llmnr_ipv4_scope &&
- a->link->llmnr_support == SUPPORT_YES &&
- a->link->manager->llmnr_support == SUPPORT_YES) {
-
- if (!a->link->manager->host_ipv4_key) {
- a->link->manager->host_ipv4_key = dns_resource_key_new(DNS_CLASS_IN, DNS_TYPE_A, a->link->manager->hostname);
- if (!a->link->manager->host_ipv4_key) {
- r = -ENOMEM;
- goto fail;
- }
- }
-
- if (!a->llmnr_address_rr) {
- a->llmnr_address_rr = dns_resource_record_new(a->link->manager->host_ipv4_key);
- if (!a->llmnr_address_rr) {
- r = -ENOMEM;
- goto fail;
- }
-
- a->llmnr_address_rr->a.in_addr = a->in_addr.in;
- a->llmnr_address_rr->ttl = LLMNR_DEFAULT_TTL;
- }
-
- if (!a->llmnr_ptr_rr) {
- r = dns_resource_record_new_reverse(&a->llmnr_ptr_rr, a->family, &a->in_addr, a->link->manager->hostname);
- if (r < 0)
- goto fail;
-
- a->llmnr_ptr_rr->ttl = LLMNR_DEFAULT_TTL;
- }
-
- r = dns_zone_put(&a->link->llmnr_ipv4_scope->zone, a->link->llmnr_ipv4_scope, a->llmnr_address_rr, true);
- if (r < 0)
- log_warning_errno(r, "Failed to add A record to LLMNR zone: %m");
-
- r = dns_zone_put(&a->link->llmnr_ipv4_scope->zone, a->link->llmnr_ipv4_scope, a->llmnr_ptr_rr, false);
- if (r < 0)
- log_warning_errno(r, "Failed to add IPv6 PTR record to LLMNR zone: %m");
- } else {
- if (a->llmnr_address_rr) {
- if (a->link->llmnr_ipv4_scope)
- dns_zone_remove_rr(&a->link->llmnr_ipv4_scope->zone, a->llmnr_address_rr);
- a->llmnr_address_rr = dns_resource_record_unref(a->llmnr_address_rr);
- }
-
- if (a->llmnr_ptr_rr) {
- if (a->link->llmnr_ipv4_scope)
- dns_zone_remove_rr(&a->link->llmnr_ipv4_scope->zone, a->llmnr_ptr_rr);
- a->llmnr_ptr_rr = dns_resource_record_unref(a->llmnr_ptr_rr);
- }
- }
- }
-
- if (a->family == AF_INET6) {
-
- if (!force_remove &&
- link_address_relevant(a) &&
- a->link->llmnr_ipv6_scope &&
- a->link->llmnr_support == SUPPORT_YES &&
- a->link->manager->llmnr_support == SUPPORT_YES) {
-
- if (!a->link->manager->host_ipv6_key) {
- a->link->manager->host_ipv6_key = dns_resource_key_new(DNS_CLASS_IN, DNS_TYPE_AAAA, a->link->manager->hostname);
- if (!a->link->manager->host_ipv6_key) {
- r = -ENOMEM;
- goto fail;
- }
- }
-
- if (!a->llmnr_address_rr) {
- a->llmnr_address_rr = dns_resource_record_new(a->link->manager->host_ipv6_key);
- if (!a->llmnr_address_rr) {
- r = -ENOMEM;
- goto fail;
- }
-
- a->llmnr_address_rr->aaaa.in6_addr = a->in_addr.in6;
- a->llmnr_address_rr->ttl = LLMNR_DEFAULT_TTL;
- }
-
- if (!a->llmnr_ptr_rr) {
- r = dns_resource_record_new_reverse(&a->llmnr_ptr_rr, a->family, &a->in_addr, a->link->manager->hostname);
- if (r < 0)
- goto fail;
-
- a->llmnr_ptr_rr->ttl = LLMNR_DEFAULT_TTL;
- }
-
- r = dns_zone_put(&a->link->llmnr_ipv6_scope->zone, a->link->llmnr_ipv6_scope, a->llmnr_address_rr, true);
- if (r < 0)
- log_warning_errno(r, "Failed to add AAAA record to LLMNR zone: %m");
-
- r = dns_zone_put(&a->link->llmnr_ipv6_scope->zone, a->link->llmnr_ipv6_scope, a->llmnr_ptr_rr, false);
- if (r < 0)
- log_warning_errno(r, "Failed to add IPv6 PTR record to LLMNR zone: %m");
- } else {
- if (a->llmnr_address_rr) {
- if (a->link->llmnr_ipv6_scope)
- dns_zone_remove_rr(&a->link->llmnr_ipv6_scope->zone, a->llmnr_address_rr);
- a->llmnr_address_rr = dns_resource_record_unref(a->llmnr_address_rr);
- }
-
- if (a->llmnr_ptr_rr) {
- if (a->link->llmnr_ipv6_scope)
- dns_zone_remove_rr(&a->link->llmnr_ipv6_scope->zone, a->llmnr_ptr_rr);
- a->llmnr_ptr_rr = dns_resource_record_unref(a->llmnr_ptr_rr);
- }
- }
- }
-
- return;
-
-fail:
- log_debug_errno(r, "Failed to update address RRs: %m");
-}
-
-int link_address_update_rtnl(LinkAddress *a, sd_rtnl_message *m) {
- int r;
- assert(a);
- assert(m);
-
- r = sd_rtnl_message_addr_get_flags(m, &a->flags);
- if (r < 0)
- return r;
-
- sd_rtnl_message_addr_get_scope(m, &a->scope);
-
- link_allocate_scopes(a->link);
- link_add_rrs(a->link, false);
-
- return 0;
-}
-
-bool link_address_relevant(LinkAddress *a) {
- assert(a);
-
- if (a->flags & (IFA_F_DEPRECATED|IFA_F_TENTATIVE))
- return false;
-
- if (IN_SET(a->scope, RT_SCOPE_HOST, RT_SCOPE_NOWHERE))
- return false;
-
- return true;
-}
diff --git a/src/resolve/resolved-link.h b/src/resolve/resolved-link.h
deleted file mode 100644
index eee1846108..0000000000
--- a/src/resolve/resolved-link.h
+++ /dev/null
@@ -1,89 +0,0 @@
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
-#pragma once
-
-/***
- This file is part of systemd.
-
- Copyright 2014 Lennart Poettering
-
- systemd is free software; you can redistribute it and/or modify it
- under the terms of the GNU Lesser General Public License as published by
- the Free Software Foundation; either version 2.1 of the License, or
- (at your option) any later version.
-
- systemd is distributed in the hope that it will be useful, but
- WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Lesser General Public License for more details.
-
- You should have received a copy of the GNU Lesser General Public License
- along with systemd; If not, see <http://www.gnu.org/licenses/>.
-***/
-
-#include <net/if.h>
-
-#include "in-addr-util.h"
-#include "ratelimit.h"
-
-typedef struct Link Link;
-typedef struct LinkAddress LinkAddress;
-
-#include "resolved-dns-rr.h"
-#include "resolved-manager.h"
-
-struct LinkAddress {
- Link *link;
-
- int family;
- union in_addr_union in_addr;
-
- unsigned char flags, scope;
-
- DnsResourceRecord *llmnr_address_rr;
- DnsResourceRecord *llmnr_ptr_rr;
-
- LIST_FIELDS(LinkAddress, addresses);
-};
-
-struct Link {
- Manager *manager;
-
- int ifindex;
- unsigned flags;
-
- LIST_HEAD(LinkAddress, addresses);
-
- LIST_HEAD(DnsServer, dns_servers);
- DnsServer *current_dns_server;
-
- Support llmnr_support;
-
- DnsScope *unicast_scope;
- DnsScope *llmnr_ipv4_scope;
- DnsScope *llmnr_ipv6_scope;
-
- char name[IF_NAMESIZE];
- uint32_t mtu;
-};
-
-int link_new(Manager *m, Link **ret, int ifindex);
-Link *link_free(Link *l);
-int link_update_rtnl(Link *l, sd_rtnl_message *m);
-int link_update_monitor(Link *l);
-bool link_relevant(Link *l, int family);
-LinkAddress* link_find_address(Link *l, int family, const union in_addr_union *in_addr);
-void link_add_rrs(Link *l, bool force_remove);
-
-DnsServer* link_set_dns_server(Link *l, DnsServer *s);
-DnsServer* link_find_dns_server(Link *l, int family, const union in_addr_union *in_addr);
-DnsServer* link_get_dns_server(Link *l);
-void link_next_dns_server(Link *l);
-
-int link_address_new(Link *l, LinkAddress **ret, int family, const union in_addr_union *in_addr);
-LinkAddress *link_address_free(LinkAddress *a);
-int link_address_update_rtnl(LinkAddress *a, sd_rtnl_message *m);
-bool link_address_relevant(LinkAddress *l);
-void link_address_add_rrs(LinkAddress *a, bool force_remove);
-
-DEFINE_TRIVIAL_CLEANUP_FUNC(Link*, link_free);
diff --git a/src/resolve/resolved-manager.c b/src/resolve/resolved-manager.c
deleted file mode 100644
index 167bea39b3..0000000000
--- a/src/resolve/resolved-manager.c
+++ /dev/null
@@ -1,1841 +0,0 @@
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
-/***
- This file is part of systemd.
-
- Copyright 2014 Tom Gundersen <teg@jklm.no>
-
- systemd is free software; you can redistribute it and/or modify it
- under the terms of the GNU Lesser General Public License as published by
- the Free Software Foundation; either version 2.1 of the License, or
- (at your option) any later version.
-
- systemd is distributed in the hope that it will be useful, but
- WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Lesser General Public License for more details.
-
- You should have received a copy of the GNU Lesser General Public License
- along with systemd; If not, see <http://www.gnu.org/licenses/>.
- ***/
-
-#include <resolv.h>
-#include <sys/ioctl.h>
-#include <poll.h>
-#include <netinet/in.h>
-
-#include "rtnl-util.h"
-#include "network-internal.h"
-#include "socket-util.h"
-#include "af-list.h"
-#include "utf8.h"
-#include "fileio-label.h"
-
-#include "resolved-dns-domain.h"
-#include "resolved-conf.h"
-#include "resolved-bus.h"
-#include "resolved-manager.h"
-
-#define SEND_TIMEOUT_USEC (200 * USEC_PER_MSEC)
-
-static int manager_process_link(sd_rtnl *rtnl, sd_rtnl_message *mm, void *userdata) {
- Manager *m = userdata;
- uint16_t type;
- Link *l;
- int ifindex, r;
-
- assert(rtnl);
- assert(m);
- assert(mm);
-
- r = sd_rtnl_message_get_type(mm, &type);
- if (r < 0)
- goto fail;
-
- r = sd_rtnl_message_link_get_ifindex(mm, &ifindex);
- if (r < 0)
- goto fail;
-
- l = hashmap_get(m->links, INT_TO_PTR(ifindex));
-
- switch (type) {
-
- case RTM_NEWLINK:{
- bool is_new = !l;
-
- if (!l) {
- r = link_new(m, &l, ifindex);
- if (r < 0)
- goto fail;
- }
-
- r = link_update_rtnl(l, mm);
- if (r < 0)
- goto fail;
-
- r = link_update_monitor(l);
- if (r < 0)
- goto fail;
-
- if (is_new)
- log_debug("Found new link %i/%s", ifindex, l->name);
-
- break;
- }
-
- case RTM_DELLINK:
- if (l) {
- log_debug("Removing link %i/%s", l->ifindex, l->name);
- link_free(l);
- }
-
- break;
- }
-
- return 0;
-
-fail:
- log_warning_errno(r, "Failed to process RTNL link message: %m");
- return 0;
-}
-
-static int manager_process_address(sd_rtnl *rtnl, sd_rtnl_message *mm, void *userdata) {
- Manager *m = userdata;
- union in_addr_union address;
- uint16_t type;
- int r, ifindex, family;
- LinkAddress *a;
- Link *l;
-
- assert(rtnl);
- assert(mm);
- assert(m);
-
- r = sd_rtnl_message_get_type(mm, &type);
- if (r < 0)
- goto fail;
-
- r = sd_rtnl_message_addr_get_ifindex(mm, &ifindex);
- if (r < 0)
- goto fail;
-
- l = hashmap_get(m->links, INT_TO_PTR(ifindex));
- if (!l)
- return 0;
-
- r = sd_rtnl_message_addr_get_family(mm, &family);
- if (r < 0)
- goto fail;
-
- switch (family) {
-
- case AF_INET:
- r = sd_rtnl_message_read_in_addr(mm, IFA_LOCAL, &address.in);
- if (r < 0) {
- r = sd_rtnl_message_read_in_addr(mm, IFA_ADDRESS, &address.in);
- if (r < 0)
- goto fail;
- }
-
- break;
-
- case AF_INET6:
- r = sd_rtnl_message_read_in6_addr(mm, IFA_LOCAL, &address.in6);
- if (r < 0) {
- r = sd_rtnl_message_read_in6_addr(mm, IFA_ADDRESS, &address.in6);
- if (r < 0)
- goto fail;
- }
-
- break;
-
- default:
- return 0;
- }
-
- a = link_find_address(l, family, &address);
-
- switch (type) {
-
- case RTM_NEWADDR:
-
- if (!a) {
- r = link_address_new(l, &a, family, &address);
- if (r < 0)
- return r;
- }
-
- r = link_address_update_rtnl(a, mm);
- if (r < 0)
- return r;
-
- break;
-
- case RTM_DELADDR:
- if (a)
- link_address_free(a);
- break;
- }
-
- return 0;
-
-fail:
- log_warning_errno(r, "Failed to process RTNL address message: %m");
- return 0;
-}
-
-static int manager_rtnl_listen(Manager *m) {
- _cleanup_rtnl_message_unref_ sd_rtnl_message *req = NULL, *reply = NULL;
- sd_rtnl_message *i;
- int r;
-
- assert(m);
-
- /* First, subscribe to interfaces coming and going */
- r = sd_rtnl_open(&m->rtnl, 3, RTNLGRP_LINK, RTNLGRP_IPV4_IFADDR, RTNLGRP_IPV6_IFADDR);
- if (r < 0)
- return r;
-
- r = sd_rtnl_attach_event(m->rtnl, m->event, 0);
- if (r < 0)
- return r;
-
- r = sd_rtnl_add_match(m->rtnl, RTM_NEWLINK, manager_process_link, m);
- if (r < 0)
- return r;
-
- r = sd_rtnl_add_match(m->rtnl, RTM_DELLINK, manager_process_link, m);
- if (r < 0)
- return r;
-
- r = sd_rtnl_add_match(m->rtnl, RTM_NEWADDR, manager_process_address, m);
- if (r < 0)
- return r;
-
- r = sd_rtnl_add_match(m->rtnl, RTM_DELADDR, manager_process_address, m);
- if (r < 0)
- return r;
-
- /* Then, enumerate all links */
- r = sd_rtnl_message_new_link(m->rtnl, &req, RTM_GETLINK, 0);
- if (r < 0)
- return r;
-
- r = sd_rtnl_message_request_dump(req, true);
- if (r < 0)
- return r;
-
- r = sd_rtnl_call(m->rtnl, req, 0, &reply);
- if (r < 0)
- return r;
-
- for (i = reply; i; i = sd_rtnl_message_next(i)) {
- r = manager_process_link(m->rtnl, i, m);
- if (r < 0)
- return r;
- }
-
- req = sd_rtnl_message_unref(req);
- reply = sd_rtnl_message_unref(reply);
-
- /* Finally, enumerate all addresses, too */
- r = sd_rtnl_message_new_addr(m->rtnl, &req, RTM_GETADDR, 0, AF_UNSPEC);
- if (r < 0)
- return r;
-
- r = sd_rtnl_message_request_dump(req, true);
- if (r < 0)
- return r;
-
- r = sd_rtnl_call(m->rtnl, req, 0, &reply);
- if (r < 0)
- return r;
-
- for (i = reply; i; i = sd_rtnl_message_next(i)) {
- r = manager_process_address(m->rtnl, i, m);
- if (r < 0)
- return r;
- }
-
- return r;
-}
-
-static int on_network_event(sd_event_source *s, int fd, uint32_t revents, void *userdata) {
- Manager *m = userdata;
- Iterator i;
- Link *l;
- int r;
-
- assert(m);
-
- sd_network_monitor_flush(m->network_monitor);
-
- HASHMAP_FOREACH(l, m->links, i) {
- r = link_update_monitor(l);
- if (r < 0)
- log_warning_errno(r, "Failed to update monitor information for %i: %m", l->ifindex);
- }
-
- r = manager_write_resolv_conf(m);
- if (r < 0)
- log_warning_errno(r, "Could not update resolv.conf: %m");
-
- return 0;
-}
-
-static int manager_network_monitor_listen(Manager *m) {
- int r, fd, events;
-
- assert(m);
-
- r = sd_network_monitor_new(&m->network_monitor, NULL);
- if (r < 0)
- return r;
-
- fd = sd_network_monitor_get_fd(m->network_monitor);
- if (fd < 0)
- return fd;
-
- events = sd_network_monitor_get_events(m->network_monitor);
- if (events < 0)
- return events;
-
- r = sd_event_add_io(m->event, &m->network_event_source, fd, events, &on_network_event, m);
- if (r < 0)
- return r;
-
- return 0;
-}
-
-static int determine_hostname(char **ret) {
- _cleanup_free_ char *h = NULL, *n = NULL;
- int r;
-
- assert(ret);
-
- h = gethostname_malloc();
- if (!h)
- return log_oom();
-
- if (!utf8_is_valid(h)) {
- log_error("System hostname is not UTF-8 clean.");
- return -EINVAL;
- }
-
- r = dns_name_normalize(h, &n);
- if (r < 0) {
- log_error("System hostname '%s' cannot be normalized.", h);
- return r;
- }
-
- *ret = n;
- n = NULL;
-
- return 0;
-}
-
-static int on_hostname_change(sd_event_source *es, int fd, uint32_t revents, void *userdata) {
- _cleanup_free_ char *h = NULL;
- Manager *m = userdata;
- int r;
-
- assert(m);
-
- r = determine_hostname(&h);
- if (r < 0)
- return 0; /* ignore invalid hostnames */
-
- if (streq(h, m->hostname))
- return 0;
-
- log_info("System hostname changed to '%s'.", h);
- free(m->hostname);
- m->hostname = h;
- h = NULL;
-
- manager_refresh_rrs(m);
-
- return 0;
-}
-
-static int manager_watch_hostname(Manager *m) {
- int r;
-
- assert(m);
-
- m->hostname_fd = open("/proc/sys/kernel/hostname", O_RDONLY|O_CLOEXEC|O_NDELAY|O_NOCTTY);
- if (m->hostname_fd < 0) {
- log_warning_errno(errno, "Failed to watch hostname: %m");
- return 0;
- }
-
- r = sd_event_add_io(m->event, &m->hostname_event_source, m->hostname_fd, 0, on_hostname_change, m);
- if (r < 0) {
- if (r == -EPERM)
- /* kernels prior to 3.2 don't support polling this file. Ignore the failure. */
- m->hostname_fd = safe_close(m->hostname_fd);
- else
- return log_error_errno(r, "Failed to add hostname event source: %m");
- }
-
- r = determine_hostname(&m->hostname);
- if (r < 0) {
- log_info("Defaulting to hostname 'linux'.");
- m->hostname = strdup("linux");
- if (!m->hostname)
- return log_oom();
- } else
- log_info("Using system hostname '%s'.", m->hostname);
-
- return 0;
-}
-
-static void manager_llmnr_stop(Manager *m) {
- assert(m);
-
- m->llmnr_ipv4_udp_event_source = sd_event_source_unref(m->llmnr_ipv4_udp_event_source);
- m->llmnr_ipv4_udp_fd = safe_close(m->llmnr_ipv4_udp_fd);
-
- m->llmnr_ipv6_udp_event_source = sd_event_source_unref(m->llmnr_ipv6_udp_event_source);
- m->llmnr_ipv6_udp_fd = safe_close(m->llmnr_ipv6_udp_fd);
-
- m->llmnr_ipv4_tcp_event_source = sd_event_source_unref(m->llmnr_ipv4_tcp_event_source);
- m->llmnr_ipv4_tcp_fd = safe_close(m->llmnr_ipv4_tcp_fd);
-
- m->llmnr_ipv6_tcp_event_source = sd_event_source_unref(m->llmnr_ipv6_tcp_event_source);
- m->llmnr_ipv6_tcp_fd = safe_close(m->llmnr_ipv6_tcp_fd);
-}
-
-static int manager_llmnr_start(Manager *m) {
- int r;
-
- assert(m);
-
- if (m->llmnr_support == SUPPORT_NO)
- return 0;
-
- r = manager_llmnr_ipv4_udp_fd(m);
- if (r == -EADDRINUSE)
- goto eaddrinuse;
- if (r < 0)
- return r;
-
- r = manager_llmnr_ipv4_tcp_fd(m);
- if (r == -EADDRINUSE)
- goto eaddrinuse;
- if (r < 0)
- return r;
-
- if (socket_ipv6_is_supported()) {
- r = manager_llmnr_ipv6_udp_fd(m);
- if (r == -EADDRINUSE)
- goto eaddrinuse;
- if (r < 0)
- return r;
-
- r = manager_llmnr_ipv6_tcp_fd(m);
- if (r == -EADDRINUSE)
- goto eaddrinuse;
- if (r < 0)
- return r;
- }
-
- return 0;
-
-eaddrinuse:
- log_warning("There appears to be another LLMNR responder running. Turning off LLMNR support.");
- m->llmnr_support = SUPPORT_NO;
- manager_llmnr_stop(m);
-
- return 0;
-}
-
-int manager_new(Manager **ret) {
- _cleanup_(manager_freep) Manager *m = NULL;
- int r;
-
- assert(ret);
-
- m = new0(Manager, 1);
- if (!m)
- return -ENOMEM;
-
- m->dns_ipv4_fd = m->dns_ipv6_fd = -1;
- m->llmnr_ipv4_udp_fd = m->llmnr_ipv6_udp_fd = -1;
- m->llmnr_ipv4_tcp_fd = m->llmnr_ipv6_tcp_fd = -1;
- m->hostname_fd = -1;
-
- m->llmnr_support = SUPPORT_YES;
- m->read_resolv_conf = true;
-
- r = manager_parse_dns_server(m, DNS_SERVER_FALLBACK, DNS_SERVERS);
- if (r < 0)
- return r;
-
- r = sd_event_default(&m->event);
- if (r < 0)
- return r;
-
- sd_event_add_signal(m->event, NULL, SIGTERM, NULL, NULL);
- sd_event_add_signal(m->event, NULL, SIGINT, NULL, NULL);
-
- sd_event_set_watchdog(m->event, true);
-
- r = manager_watch_hostname(m);
- if (r < 0)
- return r;
-
- r = dns_scope_new(m, &m->unicast_scope, NULL, DNS_PROTOCOL_DNS, AF_UNSPEC);
- if (r < 0)
- return r;
-
- r = manager_network_monitor_listen(m);
- if (r < 0)
- return r;
-
- r = manager_rtnl_listen(m);
- if (r < 0)
- return r;
-
- r = manager_connect_bus(m);
- if (r < 0)
- return r;
-
- *ret = m;
- m = NULL;
-
- return 0;
-}
-
-int manager_start(Manager *m) {
- int r;
-
- assert(m);
-
- r = manager_llmnr_start(m);
- if (r < 0)
- return r;
-
- return 0;
-}
-
-Manager *manager_free(Manager *m) {
- Link *l;
-
- if (!m)
- return NULL;
-
- while ((l = hashmap_first(m->links)))
- link_free(l);
-
- while (m->dns_queries)
- dns_query_free(m->dns_queries);
-
- dns_scope_free(m->unicast_scope);
-
- manager_flush_dns_servers(m, DNS_SERVER_SYSTEM);
- manager_flush_dns_servers(m, DNS_SERVER_FALLBACK);
-
- hashmap_free(m->links);
- hashmap_free(m->dns_transactions);
-
- sd_event_source_unref(m->network_event_source);
- sd_network_monitor_unref(m->network_monitor);
-
- sd_event_source_unref(m->dns_ipv4_event_source);
- sd_event_source_unref(m->dns_ipv6_event_source);
- safe_close(m->dns_ipv4_fd);
- safe_close(m->dns_ipv6_fd);
-
- manager_llmnr_stop(m);
-
- sd_bus_slot_unref(m->prepare_for_sleep_slot);
- sd_event_source_unref(m->bus_retry_event_source);
- sd_bus_unref(m->bus);
-
- sd_event_unref(m->event);
-
- dns_resource_key_unref(m->host_ipv4_key);
- dns_resource_key_unref(m->host_ipv6_key);
-
- safe_close(m->hostname_fd);
- sd_event_source_unref(m->hostname_event_source);
- free(m->hostname);
-
- free(m);
-
- return NULL;
-}
-
-int manager_read_resolv_conf(Manager *m) {
- _cleanup_fclose_ FILE *f = NULL;
- struct stat st, own;
- char line[LINE_MAX];
- DnsServer *s, *nx;
- usec_t t;
- int r;
-
- assert(m);
-
- /* Reads the system /etc/resolv.conf, if it exists and is not
- * symlinked to our own resolv.conf instance */
-
- if (!m->read_resolv_conf)
- return 0;
-
- r = stat("/etc/resolv.conf", &st);
- if (r < 0) {
- if (errno != ENOENT)
- log_warning_errno(errno, "Failed to open /etc/resolv.conf: %m");
- r = -errno;
- goto clear;
- }
-
- /* Have we already seen the file? */
- t = timespec_load(&st.st_mtim);
- if (t == m->resolv_conf_mtime)
- return 0;
-
- m->resolv_conf_mtime = t;
-
- /* Is it symlinked to our own file? */
- if (stat("/run/systemd/resolve/resolv.conf", &own) >= 0 &&
- st.st_dev == own.st_dev &&
- st.st_ino == own.st_ino) {
- r = 0;
- goto clear;
- }
-
- f = fopen("/etc/resolv.conf", "re");
- if (!f) {
- if (errno != ENOENT)
- log_warning_errno(errno, "Failed to open /etc/resolv.conf: %m");
- r = -errno;
- goto clear;
- }
-
- if (fstat(fileno(f), &st) < 0) {
- log_error_errno(errno, "Failed to stat open file: %m");
- r = -errno;
- goto clear;
- }
-
- LIST_FOREACH(servers, s, m->dns_servers)
- s->marked = true;
-
- FOREACH_LINE(line, f, r = -errno; goto clear) {
- union in_addr_union address;
- int family;
- char *l;
- const char *a;
-
- truncate_nl(line);
-
- l = strstrip(line);
- if (*l == '#' || *l == ';')
- continue;
-
- a = first_word(l, "nameserver");
- if (!a)
- continue;
-
- r = in_addr_from_string_auto(a, &family, &address);
- if (r < 0) {
- log_warning("Failed to parse name server %s.", a);
- continue;
- }
-
- LIST_FOREACH(servers, s, m->dns_servers)
- if (s->family == family && in_addr_equal(family, &s->address, &address) > 0)
- break;
-
- if (s)
- s->marked = false;
- else {
- r = dns_server_new(m, NULL, DNS_SERVER_SYSTEM, NULL, family, &address);
- if (r < 0)
- goto clear;
- }
- }
-
- LIST_FOREACH_SAFE(servers, s, nx, m->dns_servers)
- if (s->marked)
- dns_server_free(s);
-
- /* Whenever /etc/resolv.conf changes, start using the first
- * DNS server of it. This is useful to deal with broken
- * network managing implementations (like NetworkManager),
- * that when connecting to a VPN place both the VPN DNS
- * servers and the local ones in /etc/resolv.conf. Without
- * resetting the DNS server to use back to the first entry we
- * will continue to use the local one thus being unable to
- * resolve VPN domains. */
- manager_set_dns_server(m, m->dns_servers);
-
- return 0;
-
-clear:
- while (m->dns_servers)
- dns_server_free(m->dns_servers);
-
- return r;
-}
-
-static void write_resolv_conf_server(DnsServer *s, FILE *f, unsigned *count) {
- _cleanup_free_ char *t = NULL;
- int r;
-
- assert(s);
- assert(f);
- assert(count);
-
- r = in_addr_to_string(s->family, &s->address, &t);
- if (r < 0) {
- log_warning_errno(r, "Invalid DNS address. Ignoring: %m");
- return;
- }
-
- if (*count == MAXNS)
- fputs("# Too many DNS servers configured, the following entries may be ignored.\n", f);
-
- fprintf(f, "nameserver %s\n", t);
- (*count) ++;
-}
-
-static void write_resolv_conf_search(const char *domain, FILE *f,
- unsigned *count, unsigned *length) {
- assert(domain);
- assert(f);
- assert(length);
-
- if (*count >= MAXDNSRCH ||
- *length + strlen(domain) > 256) {
- if (*count == MAXDNSRCH)
- fputs(" # Too many search domains configured, remaining ones ignored.", f);
- if (*length <= 256)
- fputs(" # Total length of all search domains is too long, remaining ones ignored.", f);
-
- return;
- }
-
- fprintf(f, " %s", domain);
-
- (*length) += strlen(domain);
- (*count) ++;
-}
-
-static int write_resolv_conf_contents(FILE *f, Set *dns, Set *domains) {
- Iterator i;
-
- fputs("# This file is managed by systemd-resolved(8). Do not edit.\n#\n"
- "# Third party programs must not access this file directly, but\n"
- "# only through the symlink at /etc/resolv.conf. To manage\n"
- "# resolv.conf(5) in a different way, replace the symlink by a\n"
- "# static file or a different symlink.\n\n", f);
-
- if (set_isempty(dns))
- fputs("# No DNS servers known.\n", f);
- else {
- DnsServer *s;
- unsigned count = 0;
-
- SET_FOREACH(s, dns, i)
- write_resolv_conf_server(s, f, &count);
- }
-
- if (!set_isempty(domains)) {
- unsigned length = 0, count = 0;
- char *domain;
-
- fputs("search", f);
- SET_FOREACH(domain, domains, i)
- write_resolv_conf_search(domain, f, &count, &length);
- fputs("\n", f);
- }
-
- return fflush_and_check(f);
-}
-
-
-int manager_write_resolv_conf(Manager *m) {
- static const char path[] = "/run/systemd/resolve/resolv.conf";
- _cleanup_free_ char *temp_path = NULL;
- _cleanup_fclose_ FILE *f = NULL;
- _cleanup_set_free_ Set *dns = NULL, *domains = NULL;
- DnsServer *s;
- Iterator i;
- Link *l;
- int r;
-
- assert(m);
-
- /* Read the system /etc/resolv.conf first */
- manager_read_resolv_conf(m);
-
- /* Add the full list to a set, to filter out duplicates */
- dns = set_new(&dns_server_hash_ops);
- if (!dns)
- return -ENOMEM;
-
- domains = set_new(&dns_name_hash_ops);
- if (!domains)
- return -ENOMEM;
-
- /* First add the system-wide servers */
- LIST_FOREACH(servers, s, m->dns_servers) {
- r = set_put(dns, s);
- if (r == -EEXIST)
- continue;
- if (r < 0)
- return r;
- }
-
- /* Then, add the per-link servers and domains */
- HASHMAP_FOREACH(l, m->links, i) {
- char **domain;
-
- LIST_FOREACH(servers, s, l->dns_servers) {
- r = set_put(dns, s);
- if (r == -EEXIST)
- continue;
- if (r < 0)
- return r;
- }
-
- if (!l->unicast_scope)
- continue;
-
- STRV_FOREACH(domain, l->unicast_scope->domains) {
- r = set_put(domains, *domain);
- if (r == -EEXIST)
- continue;
- if (r < 0)
- return r;
- }
- }
-
- /* If we found nothing, add the fallback servers */
- if (set_isempty(dns)) {
- LIST_FOREACH(servers, s, m->fallback_dns_servers) {
- r = set_put(dns, s);
- if (r == -EEXIST)
- continue;
- if (r < 0)
- return r;
- }
- }
-
- r = fopen_temporary_label(path, path, &f, &temp_path);
- if (r < 0)
- return r;
-
- fchmod(fileno(f), 0644);
-
- r = write_resolv_conf_contents(f, dns, domains);
- if (r < 0)
- goto fail;
-
- if (rename(temp_path, path) < 0) {
- r = -errno;
- goto fail;
- }
-
- return 0;
-
-fail:
- unlink(path);
- unlink(temp_path);
- return r;
-}
-
-int manager_recv(Manager *m, int fd, DnsProtocol protocol, DnsPacket **ret) {
- _cleanup_(dns_packet_unrefp) DnsPacket *p = NULL;
- union {
- struct cmsghdr header; /* For alignment */
- uint8_t buffer[CMSG_SPACE(MAXSIZE(struct in_pktinfo, struct in6_pktinfo))
- + CMSG_SPACE(int) /* ttl/hoplimit */
- + EXTRA_CMSG_SPACE /* kernel appears to require extra buffer space */];
- } control;
- union sockaddr_union sa;
- struct msghdr mh = {};
- struct cmsghdr *cmsg;
- struct iovec iov;
- int ms = 0, r;
- ssize_t l;
-
- assert(m);
- assert(fd >= 0);
- assert(ret);
-
- r = ioctl(fd, FIONREAD, &ms);
- if (r < 0)
- return -errno;
- if (ms < 0)
- return -EIO;
-
- r = dns_packet_new(&p, protocol, ms);
- if (r < 0)
- return r;
-
- iov.iov_base = DNS_PACKET_DATA(p);
- iov.iov_len = p->allocated;
-
- mh.msg_name = &sa.sa;
- mh.msg_namelen = sizeof(sa);
- mh.msg_iov = &iov;
- mh.msg_iovlen = 1;
- mh.msg_control = &control;
- mh.msg_controllen = sizeof(control);
-
- l = recvmsg(fd, &mh, 0);
- if (l < 0) {
- if (errno == EAGAIN || errno == EINTR)
- return 0;
-
- return -errno;
- }
-
- if (l <= 0)
- return -EIO;
-
- assert(!(mh.msg_flags & MSG_CTRUNC));
- assert(!(mh.msg_flags & MSG_TRUNC));
-
- p->size = (size_t) l;
-
- p->family = sa.sa.sa_family;
- p->ipproto = IPPROTO_UDP;
- if (p->family == AF_INET) {
- p->sender.in = sa.in.sin_addr;
- p->sender_port = be16toh(sa.in.sin_port);
- } else if (p->family == AF_INET6) {
- p->sender.in6 = sa.in6.sin6_addr;
- p->sender_port = be16toh(sa.in6.sin6_port);
- p->ifindex = sa.in6.sin6_scope_id;
- } else
- return -EAFNOSUPPORT;
-
- for (cmsg = CMSG_FIRSTHDR(&mh); cmsg; cmsg = CMSG_NXTHDR(&mh, cmsg)) {
-
- if (cmsg->cmsg_level == IPPROTO_IPV6) {
- assert(p->family == AF_INET6);
-
- switch (cmsg->cmsg_type) {
-
- case IPV6_PKTINFO: {
- struct in6_pktinfo *i = (struct in6_pktinfo*) CMSG_DATA(cmsg);
-
- if (p->ifindex <= 0)
- p->ifindex = i->ipi6_ifindex;
-
- p->destination.in6 = i->ipi6_addr;
- break;
- }
-
- case IPV6_HOPLIMIT:
- p->ttl = *(int *) CMSG_DATA(cmsg);
- break;
-
- }
- } else if (cmsg->cmsg_level == IPPROTO_IP) {
- assert(p->family == AF_INET);
-
- switch (cmsg->cmsg_type) {
-
- case IP_PKTINFO: {
- struct in_pktinfo *i = (struct in_pktinfo*) CMSG_DATA(cmsg);
-
- if (p->ifindex <= 0)
- p->ifindex = i->ipi_ifindex;
-
- p->destination.in = i->ipi_addr;
- break;
- }
-
- case IP_TTL:
- p->ttl = *(int *) CMSG_DATA(cmsg);
- break;
- }
- }
- }
-
- /* The Linux kernel sets the interface index to the loopback
- * device if the packet came from the local host since it
- * avoids the routing table in such a case. Let's unset the
- * interface index in such a case. */
- if (p->ifindex == LOOPBACK_IFINDEX)
- p->ifindex = 0;
-
- /* If we don't know the interface index still, we look for the
- * first local interface with a matching address. Yuck! */
- if (p->ifindex <= 0)
- p->ifindex = manager_find_ifindex(m, p->family, &p->destination);
-
- *ret = p;
- p = NULL;
-
- return 1;
-}
-
-static int on_dns_packet(sd_event_source *s, int fd, uint32_t revents, void *userdata) {
- _cleanup_(dns_packet_unrefp) DnsPacket *p = NULL;
- DnsTransaction *t = NULL;
- Manager *m = userdata;
- int r;
-
- r = manager_recv(m, fd, DNS_PROTOCOL_DNS, &p);
- if (r <= 0)
- return r;
-
- if (dns_packet_validate_reply(p) > 0) {
- t = hashmap_get(m->dns_transactions, UINT_TO_PTR(DNS_PACKET_ID(p)));
- if (!t)
- return 0;
-
- dns_transaction_process_reply(t, p);
-
- } else
- log_debug("Invalid DNS packet.");
-
- return 0;
-}
-
-int manager_dns_ipv4_fd(Manager *m) {
- const int one = 1;
- int r;
-
- assert(m);
-
- if (m->dns_ipv4_fd >= 0)
- return m->dns_ipv4_fd;
-
- m->dns_ipv4_fd = socket(AF_INET, SOCK_DGRAM|SOCK_CLOEXEC|SOCK_NONBLOCK, 0);
- if (m->dns_ipv4_fd < 0)
- return -errno;
-
- r = setsockopt(m->dns_ipv4_fd, IPPROTO_IP, IP_PKTINFO, &one, sizeof(one));
- if (r < 0) {
- r = -errno;
- goto fail;
- }
-
- r = sd_event_add_io(m->event, &m->dns_ipv4_event_source, m->dns_ipv4_fd, EPOLLIN, on_dns_packet, m);
- if (r < 0)
- goto fail;
-
- return m->dns_ipv4_fd;
-
-fail:
- m->dns_ipv4_fd = safe_close(m->dns_ipv4_fd);
- return r;
-}
-
-int manager_dns_ipv6_fd(Manager *m) {
- const int one = 1;
- int r;
-
- assert(m);
-
- if (m->dns_ipv6_fd >= 0)
- return m->dns_ipv6_fd;
-
- m->dns_ipv6_fd = socket(AF_INET6, SOCK_DGRAM|SOCK_CLOEXEC|SOCK_NONBLOCK, 0);
- if (m->dns_ipv6_fd < 0)
- return -errno;
-
- r = setsockopt(m->dns_ipv6_fd, IPPROTO_IPV6, IPV6_RECVPKTINFO, &one, sizeof(one));
- if (r < 0) {
- r = -errno;
- goto fail;
- }
-
- r = sd_event_add_io(m->event, &m->dns_ipv6_event_source, m->dns_ipv6_fd, EPOLLIN, on_dns_packet, m);
- if (r < 0)
- goto fail;
-
- return m->dns_ipv6_fd;
-
-fail:
- m->dns_ipv6_fd = safe_close(m->dns_ipv6_fd);
- return r;
-}
-
-static int sendmsg_loop(int fd, struct msghdr *mh, int flags) {
- int r;
-
- assert(fd >= 0);
- assert(mh);
-
- for (;;) {
- if (sendmsg(fd, mh, flags) >= 0)
- return 0;
-
- if (errno == EINTR)
- continue;
-
- if (errno != EAGAIN)
- return -errno;
-
- r = fd_wait_for_event(fd, POLLOUT, SEND_TIMEOUT_USEC);
- if (r < 0)
- return r;
- if (r == 0)
- return -ETIMEDOUT;
- }
-}
-
-static int manager_ipv4_send(Manager *m, int fd, int ifindex, const struct in_addr *addr, uint16_t port, DnsPacket *p) {
- union sockaddr_union sa = {
- .in.sin_family = AF_INET,
- };
- union {
- struct cmsghdr header; /* For alignment */
- uint8_t buffer[CMSG_SPACE(sizeof(struct in_pktinfo))];
- } control;
- struct msghdr mh = {};
- struct iovec iov;
-
- assert(m);
- assert(fd >= 0);
- assert(addr);
- assert(port > 0);
- assert(p);
-
- iov.iov_base = DNS_PACKET_DATA(p);
- iov.iov_len = p->size;
-
- sa.in.sin_addr = *addr;
- sa.in.sin_port = htobe16(port),
-
- mh.msg_iov = &iov;
- mh.msg_iovlen = 1;
- mh.msg_name = &sa.sa;
- mh.msg_namelen = sizeof(sa.in);
-
- if (ifindex > 0) {
- struct cmsghdr *cmsg;
- struct in_pktinfo *pi;
-
- zero(control);
-
- mh.msg_control = &control;
- mh.msg_controllen = CMSG_LEN(sizeof(struct in_pktinfo));
-
- cmsg = CMSG_FIRSTHDR(&mh);
- cmsg->cmsg_len = mh.msg_controllen;
- cmsg->cmsg_level = IPPROTO_IP;
- cmsg->cmsg_type = IP_PKTINFO;
-
- pi = (struct in_pktinfo*) CMSG_DATA(cmsg);
- pi->ipi_ifindex = ifindex;
- }
-
- return sendmsg_loop(fd, &mh, 0);
-}
-
-static int manager_ipv6_send(Manager *m, int fd, int ifindex, const struct in6_addr *addr, uint16_t port, DnsPacket *p) {
- union sockaddr_union sa = {
- .in6.sin6_family = AF_INET6,
- };
- union {
- struct cmsghdr header; /* For alignment */
- uint8_t buffer[CMSG_SPACE(sizeof(struct in6_pktinfo))];
- } control;
- struct msghdr mh = {};
- struct iovec iov;
-
- assert(m);
- assert(fd >= 0);
- assert(addr);
- assert(port > 0);
- assert(p);
-
- iov.iov_base = DNS_PACKET_DATA(p);
- iov.iov_len = p->size;
-
- sa.in6.sin6_addr = *addr;
- sa.in6.sin6_port = htobe16(port),
- sa.in6.sin6_scope_id = ifindex;
-
- mh.msg_iov = &iov;
- mh.msg_iovlen = 1;
- mh.msg_name = &sa.sa;
- mh.msg_namelen = sizeof(sa.in6);
-
- if (ifindex > 0) {
- struct cmsghdr *cmsg;
- struct in6_pktinfo *pi;
-
- zero(control);
-
- mh.msg_control = &control;
- mh.msg_controllen = CMSG_LEN(sizeof(struct in6_pktinfo));
-
- cmsg = CMSG_FIRSTHDR(&mh);
- cmsg->cmsg_len = mh.msg_controllen;
- cmsg->cmsg_level = IPPROTO_IPV6;
- cmsg->cmsg_type = IPV6_PKTINFO;
-
- pi = (struct in6_pktinfo*) CMSG_DATA(cmsg);
- pi->ipi6_ifindex = ifindex;
- }
-
- return sendmsg_loop(fd, &mh, 0);
-}
-
-int manager_send(Manager *m, int fd, int ifindex, int family, const union in_addr_union *addr, uint16_t port, DnsPacket *p) {
- assert(m);
- assert(fd >= 0);
- assert(addr);
- assert(port > 0);
- assert(p);
-
- log_debug("Sending %s packet with id %u on interface %i/%s", DNS_PACKET_QR(p) ? "response" : "query", DNS_PACKET_ID(p), ifindex, af_to_name(family));
-
- if (family == AF_INET)
- return manager_ipv4_send(m, fd, ifindex, &addr->in, port, p);
- else if (family == AF_INET6)
- return manager_ipv6_send(m, fd, ifindex, &addr->in6, port, p);
-
- return -EAFNOSUPPORT;
-}
-
-DnsServer* manager_find_dns_server(Manager *m, int family, const union in_addr_union *in_addr) {
- DnsServer *s;
-
- assert(m);
- assert(in_addr);
-
- LIST_FOREACH(servers, s, m->dns_servers)
- if (s->family == family && in_addr_equal(family, &s->address, in_addr) > 0)
- return s;
-
- LIST_FOREACH(servers, s, m->fallback_dns_servers)
- if (s->family == family && in_addr_equal(family, &s->address, in_addr) > 0)
- return s;
-
- return NULL;
-}
-
-DnsServer *manager_set_dns_server(Manager *m, DnsServer *s) {
- assert(m);
-
- if (m->current_dns_server == s)
- return s;
-
- if (s) {
- _cleanup_free_ char *ip = NULL;
-
- in_addr_to_string(s->family, &s->address, &ip);
- log_info("Switching to system DNS server %s.", strna(ip));
- }
-
- m->current_dns_server = s;
-
- if (m->unicast_scope)
- dns_cache_flush(&m->unicast_scope->cache);
-
- return s;
-}
-
-DnsServer *manager_get_dns_server(Manager *m) {
- Link *l;
- assert(m);
-
- /* Try to read updates resolv.conf */
- manager_read_resolv_conf(m);
-
- if (!m->current_dns_server)
- manager_set_dns_server(m, m->dns_servers);
-
- if (!m->current_dns_server) {
- bool found = false;
- Iterator i;
-
- /* No DNS servers configured, let's see if there are
- * any on any links. If not, we use the fallback
- * servers */
-
- HASHMAP_FOREACH(l, m->links, i)
- if (l->dns_servers) {
- found = true;
- break;
- }
-
- if (!found)
- manager_set_dns_server(m, m->fallback_dns_servers);
- }
-
- return m->current_dns_server;
-}
-
-void manager_next_dns_server(Manager *m) {
- assert(m);
-
- /* If there's currently no DNS server set, then the next
- * manager_get_dns_server() will find one */
- if (!m->current_dns_server)
- return;
-
- /* Change to the next one */
- if (m->current_dns_server->servers_next) {
- manager_set_dns_server(m, m->current_dns_server->servers_next);
- return;
- }
-
- /* If there was no next one, then start from the beginning of
- * the list */
- if (m->current_dns_server->type == DNS_SERVER_FALLBACK)
- manager_set_dns_server(m, m->fallback_dns_servers);
- else
- manager_set_dns_server(m, m->dns_servers);
-}
-
-uint32_t manager_find_mtu(Manager *m) {
- uint32_t mtu = 0;
- Link *l;
- Iterator i;
-
- /* If we don't know on which link a DNS packet would be
- * delivered, let's find the largest MTU that works on all
- * interfaces we know of */
-
- HASHMAP_FOREACH(l, m->links, i) {
- if (l->mtu <= 0)
- continue;
-
- if (mtu <= 0 || l->mtu < mtu)
- mtu = l->mtu;
- }
-
- return mtu;
-}
-
-static int on_llmnr_packet(sd_event_source *s, int fd, uint32_t revents, void *userdata) {
- _cleanup_(dns_packet_unrefp) DnsPacket *p = NULL;
- DnsTransaction *t = NULL;
- Manager *m = userdata;
- DnsScope *scope;
- int r;
-
- r = manager_recv(m, fd, DNS_PROTOCOL_LLMNR, &p);
- if (r <= 0)
- return r;
-
- scope = manager_find_scope(m, p);
- if (!scope) {
- log_warning("Got LLMNR UDP packet on unknown scope. Ignoring.");
- return 0;
- }
-
- if (dns_packet_validate_reply(p) > 0) {
- log_debug("Got reply packet for id %u", DNS_PACKET_ID(p));
-
- dns_scope_check_conflicts(scope, p);
-
- t = hashmap_get(m->dns_transactions, UINT_TO_PTR(DNS_PACKET_ID(p)));
- if (t)
- dns_transaction_process_reply(t, p);
-
- } else if (dns_packet_validate_query(p) > 0) {
- log_debug("Got query packet for id %u", DNS_PACKET_ID(p));
-
- dns_scope_process_query(scope, NULL, p);
- } else
- log_debug("Invalid LLMNR UDP packet.");
-
- return 0;
-}
-
-int manager_llmnr_ipv4_udp_fd(Manager *m) {
- union sockaddr_union sa = {
- .in.sin_family = AF_INET,
- .in.sin_port = htobe16(5355),
- };
- static const int one = 1, pmtu = IP_PMTUDISC_DONT, ttl = 255;
- int r;
-
- assert(m);
-
- if (m->llmnr_ipv4_udp_fd >= 0)
- return m->llmnr_ipv4_udp_fd;
-
- m->llmnr_ipv4_udp_fd = socket(AF_INET, SOCK_DGRAM|SOCK_CLOEXEC|SOCK_NONBLOCK, 0);
- if (m->llmnr_ipv4_udp_fd < 0)
- return -errno;
-
- /* RFC 4795, section 2.5 recommends setting the TTL of UDP packets to 255. */
- r = setsockopt(m->llmnr_ipv4_udp_fd, IPPROTO_IP, IP_TTL, &ttl, sizeof(ttl));
- if (r < 0) {
- r = -errno;
- goto fail;
- }
-
- r = setsockopt(m->llmnr_ipv4_udp_fd, IPPROTO_IP, IP_MULTICAST_TTL, &ttl, sizeof(ttl));
- if (r < 0) {
- r = -errno;
- goto fail;
- }
-
- r = setsockopt(m->llmnr_ipv4_udp_fd, IPPROTO_IP, IP_MULTICAST_LOOP, &one, sizeof(one));
- if (r < 0) {
- r = -errno;
- goto fail;
- }
-
- r = setsockopt(m->llmnr_ipv4_udp_fd, SOL_SOCKET, SO_REUSEADDR, &one, sizeof(one));
- if (r < 0) {
- r = -errno;
- goto fail;
- }
-
- r = setsockopt(m->llmnr_ipv4_udp_fd, IPPROTO_IP, IP_PKTINFO, &one, sizeof(one));
- if (r < 0) {
- r = -errno;
- goto fail;
- }
-
- r = setsockopt(m->llmnr_ipv4_udp_fd, IPPROTO_IP, IP_RECVTTL, &one, sizeof(one));
- if (r < 0) {
- r = -errno;
- goto fail;
- }
-
- /* Disable Don't-Fragment bit in the IP header */
- r = setsockopt(m->llmnr_ipv4_udp_fd, IPPROTO_IP, IP_MTU_DISCOVER, &pmtu, sizeof(pmtu));
- if (r < 0) {
- r = -errno;
- goto fail;
- }
-
- r = bind(m->llmnr_ipv4_udp_fd, &sa.sa, sizeof(sa.in));
- if (r < 0) {
- r = -errno;
- goto fail;
- }
-
- r = sd_event_add_io(m->event, &m->llmnr_ipv4_udp_event_source, m->llmnr_ipv4_udp_fd, EPOLLIN, on_llmnr_packet, m);
- if (r < 0)
- goto fail;
-
- return m->llmnr_ipv4_udp_fd;
-
-fail:
- m->llmnr_ipv4_udp_fd = safe_close(m->llmnr_ipv4_udp_fd);
- return r;
-}
-
-int manager_llmnr_ipv6_udp_fd(Manager *m) {
- union sockaddr_union sa = {
- .in6.sin6_family = AF_INET6,
- .in6.sin6_port = htobe16(5355),
- };
- static const int one = 1, ttl = 255;
- int r;
-
- assert(m);
-
- if (m->llmnr_ipv6_udp_fd >= 0)
- return m->llmnr_ipv6_udp_fd;
-
- m->llmnr_ipv6_udp_fd = socket(AF_INET6, SOCK_DGRAM|SOCK_CLOEXEC|SOCK_NONBLOCK, 0);
- if (m->llmnr_ipv6_udp_fd < 0)
- return -errno;
-
- r = setsockopt(m->llmnr_ipv6_udp_fd, IPPROTO_IPV6, IPV6_UNICAST_HOPS, &ttl, sizeof(ttl));
- if (r < 0) {
- r = -errno;
- goto fail;
- }
-
- /* RFC 4795, section 2.5 recommends setting the TTL of UDP packets to 255. */
- r = setsockopt(m->llmnr_ipv6_udp_fd, IPPROTO_IPV6, IPV6_MULTICAST_HOPS, &ttl, sizeof(ttl));
- if (r < 0) {
- r = -errno;
- goto fail;
- }
-
- r = setsockopt(m->llmnr_ipv6_udp_fd, IPPROTO_IPV6, IPV6_MULTICAST_LOOP, &one, sizeof(one));
- if (r < 0) {
- r = -errno;
- goto fail;
- }
-
- r = setsockopt(m->llmnr_ipv6_udp_fd, IPPROTO_IPV6, IPV6_V6ONLY, &one, sizeof(one));
- if (r < 0) {
- r = -errno;
- goto fail;
- }
-
- r = setsockopt(m->llmnr_ipv6_udp_fd, SOL_SOCKET, SO_REUSEADDR, &one, sizeof(one));
- if (r < 0) {
- r = -errno;
- goto fail;
- }
-
- r = setsockopt(m->llmnr_ipv6_udp_fd, IPPROTO_IPV6, IPV6_RECVPKTINFO, &one, sizeof(one));
- if (r < 0) {
- r = -errno;
- goto fail;
- }
-
- r = setsockopt(m->llmnr_ipv6_udp_fd, IPPROTO_IPV6, IPV6_RECVHOPLIMIT, &one, sizeof(one));
- if (r < 0) {
- r = -errno;
- goto fail;
- }
-
- r = bind(m->llmnr_ipv6_udp_fd, &sa.sa, sizeof(sa.in6));
- if (r < 0) {
- r = -errno;
- goto fail;
- }
-
- r = sd_event_add_io(m->event, &m->llmnr_ipv6_udp_event_source, m->llmnr_ipv6_udp_fd, EPOLLIN, on_llmnr_packet, m);
- if (r < 0) {
- r = -errno;
- goto fail;
- }
-
- return m->llmnr_ipv6_udp_fd;
-
-fail:
- m->llmnr_ipv6_udp_fd = safe_close(m->llmnr_ipv6_udp_fd);
- return r;
-}
-
-static int on_llmnr_stream_packet(DnsStream *s) {
- DnsScope *scope;
-
- assert(s);
-
- scope = manager_find_scope(s->manager, s->read_packet);
- if (!scope) {
- log_warning("Got LLMNR TCP packet on unknown scope. Ignroing.");
- return 0;
- }
-
- if (dns_packet_validate_query(s->read_packet) > 0) {
- log_debug("Got query packet for id %u", DNS_PACKET_ID(s->read_packet));
-
- dns_scope_process_query(scope, s, s->read_packet);
-
- /* If no reply packet was set, we free the stream */
- if (s->write_packet)
- return 0;
- } else
- log_debug("Invalid LLMNR TCP packet.");
-
- dns_stream_free(s);
- return 0;
-}
-
-static int on_llmnr_stream(sd_event_source *s, int fd, uint32_t revents, void *userdata) {
- DnsStream *stream;
- Manager *m = userdata;
- int cfd, r;
-
- cfd = accept4(fd, NULL, NULL, SOCK_NONBLOCK|SOCK_CLOEXEC);
- if (cfd < 0) {
- if (errno == EAGAIN || errno == EINTR)
- return 0;
-
- return -errno;
- }
-
- r = dns_stream_new(m, &stream, DNS_PROTOCOL_LLMNR, cfd);
- if (r < 0) {
- safe_close(cfd);
- return r;
- }
-
- stream->on_packet = on_llmnr_stream_packet;
- return 0;
-}
-
-int manager_llmnr_ipv4_tcp_fd(Manager *m) {
- union sockaddr_union sa = {
- .in.sin_family = AF_INET,
- .in.sin_port = htobe16(5355),
- };
- static const int one = 1, pmtu = IP_PMTUDISC_DONT;
- int r;
-
- assert(m);
-
- if (m->llmnr_ipv4_tcp_fd >= 0)
- return m->llmnr_ipv4_tcp_fd;
-
- m->llmnr_ipv4_tcp_fd = socket(AF_INET, SOCK_STREAM|SOCK_CLOEXEC|SOCK_NONBLOCK, 0);
- if (m->llmnr_ipv4_tcp_fd < 0)
- return -errno;
-
- /* RFC 4795, section 2.5. requires setting the TTL of TCP streams to 1 */
- r = setsockopt(m->llmnr_ipv4_tcp_fd, IPPROTO_IP, IP_TTL, &one, sizeof(one));
- if (r < 0) {
- r = -errno;
- goto fail;
- }
-
- r = setsockopt(m->llmnr_ipv4_tcp_fd, SOL_SOCKET, SO_REUSEADDR, &one, sizeof(one));
- if (r < 0) {
- r = -errno;
- goto fail;
- }
-
- r = setsockopt(m->llmnr_ipv4_tcp_fd, IPPROTO_IP, IP_PKTINFO, &one, sizeof(one));
- if (r < 0) {
- r = -errno;
- goto fail;
- }
-
- r = setsockopt(m->llmnr_ipv4_tcp_fd, IPPROTO_IP, IP_RECVTTL, &one, sizeof(one));
- if (r < 0) {
- r = -errno;
- goto fail;
- }
-
- /* Disable Don't-Fragment bit in the IP header */
- r = setsockopt(m->llmnr_ipv4_tcp_fd, IPPROTO_IP, IP_MTU_DISCOVER, &pmtu, sizeof(pmtu));
- if (r < 0) {
- r = -errno;
- goto fail;
- }
-
- r = bind(m->llmnr_ipv4_tcp_fd, &sa.sa, sizeof(sa.in));
- if (r < 0) {
- r = -errno;
- goto fail;
- }
-
- r = listen(m->llmnr_ipv4_tcp_fd, SOMAXCONN);
- if (r < 0) {
- r = -errno;
- goto fail;
- }
-
- r = sd_event_add_io(m->event, &m->llmnr_ipv4_tcp_event_source, m->llmnr_ipv4_tcp_fd, EPOLLIN, on_llmnr_stream, m);
- if (r < 0)
- goto fail;
-
- return m->llmnr_ipv4_tcp_fd;
-
-fail:
- m->llmnr_ipv4_tcp_fd = safe_close(m->llmnr_ipv4_tcp_fd);
- return r;
-}
-
-int manager_llmnr_ipv6_tcp_fd(Manager *m) {
- union sockaddr_union sa = {
- .in6.sin6_family = AF_INET6,
- .in6.sin6_port = htobe16(5355),
- };
- static const int one = 1;
- int r;
-
- assert(m);
-
- if (m->llmnr_ipv6_tcp_fd >= 0)
- return m->llmnr_ipv6_tcp_fd;
-
- m->llmnr_ipv6_tcp_fd = socket(AF_INET6, SOCK_STREAM|SOCK_CLOEXEC|SOCK_NONBLOCK, 0);
- if (m->llmnr_ipv6_tcp_fd < 0)
- return -errno;
-
- /* RFC 4795, section 2.5. requires setting the TTL of TCP streams to 1 */
- r = setsockopt(m->llmnr_ipv6_tcp_fd, IPPROTO_IPV6, IPV6_UNICAST_HOPS, &one, sizeof(one));
- if (r < 0) {
- r = -errno;
- goto fail;
- }
-
- r = setsockopt(m->llmnr_ipv6_tcp_fd, IPPROTO_IPV6, IPV6_V6ONLY, &one, sizeof(one));
- if (r < 0) {
- r = -errno;
- goto fail;
- }
-
- r = setsockopt(m->llmnr_ipv6_tcp_fd, SOL_SOCKET, SO_REUSEADDR, &one, sizeof(one));
- if (r < 0) {
- r = -errno;
- goto fail;
- }
-
- r = setsockopt(m->llmnr_ipv6_tcp_fd, IPPROTO_IPV6, IPV6_RECVPKTINFO, &one, sizeof(one));
- if (r < 0) {
- r = -errno;
- goto fail;
- }
-
- r = setsockopt(m->llmnr_ipv6_tcp_fd, IPPROTO_IPV6, IPV6_RECVHOPLIMIT, &one, sizeof(one));
- if (r < 0) {
- r = -errno;
- goto fail;
- }
-
- r = bind(m->llmnr_ipv6_tcp_fd, &sa.sa, sizeof(sa.in6));
- if (r < 0) {
- r = -errno;
- goto fail;
- }
-
- r = listen(m->llmnr_ipv6_tcp_fd, SOMAXCONN);
- if (r < 0) {
- r = -errno;
- goto fail;
- }
-
- r = sd_event_add_io(m->event, &m->llmnr_ipv6_tcp_event_source, m->llmnr_ipv6_tcp_fd, EPOLLIN, on_llmnr_stream, m);
- if (r < 0) {
- r = -errno;
- goto fail;
- }
-
- return m->llmnr_ipv6_tcp_fd;
-
-fail:
- m->llmnr_ipv6_tcp_fd = safe_close(m->llmnr_ipv6_tcp_fd);
- return r;
-}
-
-int manager_find_ifindex(Manager *m, int family, const union in_addr_union *in_addr) {
- LinkAddress *a;
-
- assert(m);
-
- a = manager_find_link_address(m, family, in_addr);
- if (a)
- return a->link->ifindex;
-
- return 0;
-}
-
-void manager_refresh_rrs(Manager *m) {
- Iterator i;
- Link *l;
-
- assert(m);
-
- m->host_ipv4_key = dns_resource_key_unref(m->host_ipv4_key);
- m->host_ipv6_key = dns_resource_key_unref(m->host_ipv6_key);
-
- HASHMAP_FOREACH(l, m->links, i) {
- link_add_rrs(l, true);
- link_add_rrs(l, false);
- }
-}
-
-int manager_next_hostname(Manager *m) {
- const char *p;
- uint64_t u, a;
- char *h;
-
- assert(m);
-
- p = strchr(m->hostname, 0);
- assert(p);
-
- while (p > m->hostname) {
- if (!strchr("0123456789", p[-1]))
- break;
-
- p--;
- }
-
- if (*p == 0 || safe_atou64(p, &u) < 0 || u <= 0)
- u = 1;
-
- /* Add a random number to the old value. This way we can avoid
- * that two hosts pick the same hostname, win on IPv4 and lose
- * on IPv6 (or vice versa), and pick the same hostname
- * replacement hostname, ad infinitum. We still want the
- * numbers to go up monotonically, hence we just add a random
- * value 1..10 */
-
- random_bytes(&a, sizeof(a));
- u += 1 + a % 10;
-
- if (asprintf(&h, "%.*s%" PRIu64, (int) (p - m->hostname), m->hostname, u) < 0)
- return -ENOMEM;
-
- log_info("Hostname conflict, changing published hostname from '%s' to '%s'.", m->hostname, h);
-
- free(m->hostname);
- m->hostname = h;
-
- manager_refresh_rrs(m);
-
- return 0;
-}
-
-LinkAddress* manager_find_link_address(Manager *m, int family, const union in_addr_union *in_addr) {
- Iterator i;
- Link *l;
-
- assert(m);
-
- HASHMAP_FOREACH(l, m->links, i) {
- LinkAddress *a;
-
- a = link_find_address(l, family, in_addr);
- if (a)
- return a;
- }
-
- return NULL;
-}
-
-bool manager_our_packet(Manager *m, DnsPacket *p) {
- assert(m);
- assert(p);
-
- return !!manager_find_link_address(m, p->family, &p->sender);
-}
-
-DnsScope* manager_find_scope(Manager *m, DnsPacket *p) {
- Link *l;
-
- assert(m);
- assert(p);
-
- l = hashmap_get(m->links, INT_TO_PTR(p->ifindex));
- if (!l)
- return NULL;
-
- if (p->protocol == DNS_PROTOCOL_LLMNR) {
- if (p->family == AF_INET)
- return l->llmnr_ipv4_scope;
- else if (p->family == AF_INET6)
- return l->llmnr_ipv6_scope;
- }
-
- return NULL;
-}
-
-void manager_verify_all(Manager *m) {
- DnsScope *s;
-
- assert(m);
-
- LIST_FOREACH(scopes, s, m->dns_scopes)
- dns_zone_verify_all(&s->zone);
-}
-
-void manager_flush_dns_servers(Manager *m, DnsServerType t) {
- assert(m);
-
- if (t == DNS_SERVER_SYSTEM)
- while (m->dns_servers)
- dns_server_free(m->dns_servers);
-
- if (t == DNS_SERVER_FALLBACK)
- while (m->fallback_dns_servers)
- dns_server_free(m->fallback_dns_servers);
-}
-
-static const char* const support_table[_SUPPORT_MAX] = {
- [SUPPORT_NO] = "no",
- [SUPPORT_YES] = "yes",
- [SUPPORT_RESOLVE] = "resolve",
-};
-DEFINE_STRING_TABLE_LOOKUP(support, Support);
diff --git a/src/resolve/resolved-manager.h b/src/resolve/resolved-manager.h
deleted file mode 100644
index 5a581cc13a..0000000000
--- a/src/resolve/resolved-manager.h
+++ /dev/null
@@ -1,156 +0,0 @@
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
-#pragma once
-
-/***
- This file is part of systemd.
-
- Copyright 2014 Tom Gundersen <teg@jklm.no>
-
- systemd is free software; you can redistribute it and/or modify it
- under the terms of the GNU Lesser General Public License as published by
- the Free Software Foundation; either version 2.1 of the License, or
- (at your option) any later version.
-
- systemd is distributed in the hope that it will be useful, but
- WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Lesser General Public License for more details.
-
- You should have received a copy of the GNU Lesser General Public License
- along with systemd; If not, see <http://www.gnu.org/licenses/>.
-***/
-
-#include "sd-event.h"
-#include "sd-network.h"
-#include "sd-rtnl.h"
-#include "list.h"
-#include "hashmap.h"
-
-typedef struct Manager Manager;
-typedef enum Support Support;
-
-enum Support {
- SUPPORT_NO,
- SUPPORT_YES,
- SUPPORT_RESOLVE,
- _SUPPORT_MAX,
- _SUPPORT_INVALID = -1
-};
-
-#include "resolved-dns-query.h"
-#include "resolved-dns-stream.h"
-#include "resolved-link.h"
-
-struct Manager {
- sd_event *event;
-
- Support llmnr_support;
-
- /* Network */
- Hashmap *links;
-
- sd_rtnl *rtnl;
- sd_event_source *rtnl_event_source;
-
- sd_network_monitor *network_monitor;
- sd_event_source *network_event_source;
-
- /* DNS query management */
- Hashmap *dns_transactions;
- LIST_HEAD(DnsQuery, dns_queries);
- unsigned n_dns_queries;
-
- LIST_HEAD(DnsStream, dns_streams);
- unsigned n_dns_streams;
-
- /* Unicast dns */
- int dns_ipv4_fd;
- int dns_ipv6_fd;
-
- sd_event_source *dns_ipv4_event_source;
- sd_event_source *dns_ipv6_event_source;
-
- LIST_HEAD(DnsServer, dns_servers);
- LIST_HEAD(DnsServer, fallback_dns_servers);
- DnsServer *current_dns_server;
-
- bool read_resolv_conf;
- usec_t resolv_conf_mtime;
-
- LIST_HEAD(DnsScope, dns_scopes);
- DnsScope *unicast_scope;
-
- /* LLMNR */
- int llmnr_ipv4_udp_fd;
- int llmnr_ipv6_udp_fd;
- int llmnr_ipv4_tcp_fd;
- int llmnr_ipv6_tcp_fd;
-
- sd_event_source *llmnr_ipv4_udp_event_source;
- sd_event_source *llmnr_ipv6_udp_event_source;
- sd_event_source *llmnr_ipv4_tcp_event_source;
- sd_event_source *llmnr_ipv6_tcp_event_source;
-
- /* dbus */
- sd_bus *bus;
- sd_event_source *bus_retry_event_source;
-
- /* The hostname we publish on LLMNR and mDNS */
- char *hostname;
- DnsResourceKey *host_ipv4_key;
- DnsResourceKey *host_ipv6_key;
-
- /* Watch the system hostname */
- int hostname_fd;
- sd_event_source *hostname_event_source;
-
- /* Watch for system suspends */
- sd_bus_slot *prepare_for_sleep_slot;
-};
-
-/* Manager */
-
-int manager_new(Manager **ret);
-Manager* manager_free(Manager *m);
-
-int manager_start(Manager *m);
-int manager_read_resolv_conf(Manager *m);
-int manager_write_resolv_conf(Manager *m);
-
-DnsServer *manager_set_dns_server(Manager *m, DnsServer *s);
-DnsServer *manager_find_dns_server(Manager *m, int family, const union in_addr_union *in_addr);
-DnsServer *manager_get_dns_server(Manager *m);
-void manager_next_dns_server(Manager *m);
-
-uint32_t manager_find_mtu(Manager *m);
-
-int manager_send(Manager *m, int fd, int ifindex, int family, const union in_addr_union *addr, uint16_t port, DnsPacket *p);
-int manager_recv(Manager *m, int fd, DnsProtocol protocol, DnsPacket **ret);
-
-int manager_dns_ipv4_fd(Manager *m);
-int manager_dns_ipv6_fd(Manager *m);
-int manager_llmnr_ipv4_udp_fd(Manager *m);
-int manager_llmnr_ipv6_udp_fd(Manager *m);
-int manager_llmnr_ipv4_tcp_fd(Manager *m);
-int manager_llmnr_ipv6_tcp_fd(Manager *m);
-
-int manager_find_ifindex(Manager *m, int family, const union in_addr_union *in_addr);
-LinkAddress* manager_find_link_address(Manager *m, int family, const union in_addr_union *in_addr);
-
-void manager_refresh_rrs(Manager *m);
-int manager_next_hostname(Manager *m);
-
-bool manager_our_packet(Manager *m, DnsPacket *p);
-DnsScope* manager_find_scope(Manager *m, DnsPacket *p);
-
-void manager_verify_all(Manager *m);
-
-void manager_flush_dns_servers(Manager *m, DnsServerType t);
-
-DEFINE_TRIVIAL_CLEANUP_FUNC(Manager*, manager_free);
-
-#define EXTRA_CMSG_SPACE 1024
-
-const char* support_to_string(Support p) _const_;
-int support_from_string(const char *s) _pure_;
diff --git a/src/resolve/resolved.c b/src/resolve/resolved.c
deleted file mode 100644
index 271247ca3f..0000000000
--- a/src/resolve/resolved.c
+++ /dev/null
@@ -1,115 +0,0 @@
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
-/***
- This file is part of systemd.
-
- Copyright 2014 Tom Gundersen <teg@jklm.no>
-
- systemd is free software; you can redistribute it and/or modify it
- under the terms of the GNU Lesser General Public License as published by
- the Free Software Foundation; either version 2.1 of the License, or
- (at your option) any later version.
-
- systemd is distributed in the hope that it will be useful, but
- WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Lesser General Public License for more details.
-
- You should have received a copy of the GNU Lesser General Public License
- along with systemd; If not, see <http://www.gnu.org/licenses/>.
-***/
-
-#include "sd-event.h"
-#include "sd-daemon.h"
-#include "mkdir.h"
-#include "capability.h"
-#include "selinux-util.h"
-
-#include "resolved-manager.h"
-#include "resolved-conf.h"
-
-int main(int argc, char *argv[]) {
- _cleanup_(manager_freep) Manager *m = NULL;
- const char *user = "systemd-resolve";
- uid_t uid;
- gid_t gid;
- int r;
-
- log_set_target(LOG_TARGET_AUTO);
- log_parse_environment();
- log_open();
-
- if (argc != 1) {
- log_error("This program takes no arguments.");
- r = -EINVAL;
- goto finish;
- }
-
- umask(0022);
-
- r = mac_selinux_init(NULL);
- if (r < 0) {
- log_error_errno(r, "SELinux setup failed: %m");
- goto finish;
- }
-
- r = get_user_creds(&user, &uid, &gid, NULL, NULL);
- if (r < 0) {
- log_error_errno(r, "Cannot resolve user name %s: %m", user);
- goto finish;
- }
-
- /* Always create the directory where resolv.conf will live */
- r = mkdir_safe_label("/run/systemd/resolve", 0755, uid, gid);
- if (r < 0) {
- log_error_errno(r, "Could not create runtime directory: %m");
- goto finish;
- }
-
- r = drop_privileges(uid, gid, 0);
- if (r < 0)
- goto finish;
-
- assert_se(sigprocmask_many(SIG_BLOCK, SIGTERM, SIGINT, -1) == 0);
-
- r = manager_new(&m);
- if (r < 0) {
- log_error_errno(r, "Could not create manager: %m");
- goto finish;
- }
-
- r = manager_parse_config_file(m);
- if (r < 0)
- log_warning_errno(r, "Failed to parse configuration file: %m");
-
- r = manager_start(m);
- if (r < 0) {
- log_error_errno(r, "Failed to start manager: %m");
- goto finish;
- }
-
- /* Write finish default resolv.conf to avoid a dangling
- * symlink */
- r = manager_write_resolv_conf(m);
- if (r < 0)
- log_warning_errno(r, "Could not create resolv.conf: %m");
-
- sd_notify(false,
- "READY=1\n"
- "STATUS=Processing requests...");
-
- r = sd_event_loop(m->event);
- if (r < 0) {
- log_error_errno(r, "Event loop failed: %m");
- goto finish;
- }
-
- sd_event_get_exit_code(m->event, &r);
-
-finish:
- sd_notify(false,
- "STOPPING=1\n"
- "STATUS=Shutting down...");
-
- return r < 0 ? EXIT_FAILURE : EXIT_SUCCESS;
-}
diff --git a/src/resolve/resolved.conf.in b/src/resolve/resolved.conf.in
deleted file mode 100644
index 3eb19e42b7..0000000000
--- a/src/resolve/resolved.conf.in
+++ /dev/null
@@ -1,17 +0,0 @@
-# This file is part of systemd.
-#
-# systemd is free software; you can redistribute it and/or modify it
-# under the terms of the GNU Lesser General Public License as published by
-# the Free Software Foundation; either version 2.1 of the License, or
-# (at your option) any later version.
-#
-# Entries in this file show the compile time defaults.
-# You can change settings by editing this file.
-# Defaults can be restored by simply deleting this file.
-#
-# See resolved.conf(5) for details
-
-[Resolve]
-#DNS=
-#FallbackDNS=@DNS_SERVERS@
-#LLMNR=yes
diff --git a/src/resolve/test-dns-domain.c b/src/resolve/test-dns-domain.c
deleted file mode 100644
index c3208abc78..0000000000
--- a/src/resolve/test-dns-domain.c
+++ /dev/null
@@ -1,192 +0,0 @@
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
-/***
- This file is part of systemd.
-
- Copyright 2014 Lennart Poettering
-
- systemd is free software; you can redistribute it and/or modify it
- under the terms of the GNU Lesser General Public License as published by
- the Free Software Foundation; either version 2.1 of the License, or
- (at your option) any later version.
-
- systemd is distributed in the hope that it will be useful, but
- WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Lesser General Public License for more details.
-
- You should have received a copy of the GNU Lesser General Public License
- along with systemd; If not, see <http://www.gnu.org/licenses/>.
- ***/
-
-#include "macro.h"
-#include "resolved-dns-domain.h"
-
-static void test_dns_label_unescape_one(const char *what, const char *expect, size_t buffer_sz, int ret) {
- char buffer[buffer_sz];
- int r;
-
- r = dns_label_unescape(&what, buffer, buffer_sz);
- assert_se(r == ret);
-
- if (r < 0)
- return;
-
- assert_se(streq(buffer, expect));
-}
-
-static void test_dns_label_unescape(void) {
- test_dns_label_unescape_one("hallo", "hallo", 6, 5);
- test_dns_label_unescape_one("hallo", "hallo", 4, -ENOSPC);
- test_dns_label_unescape_one("", "", 10, 0);
- test_dns_label_unescape_one("hallo\\.foobar", "hallo.foobar", 20, 12);
- test_dns_label_unescape_one("hallo.foobar", "hallo", 10, 5);
- test_dns_label_unescape_one("hallo\n.foobar", "hallo", 20, -EINVAL);
- test_dns_label_unescape_one("hallo\\", "hallo", 20, -EINVAL);
- test_dns_label_unescape_one("hallo\\032 ", "hallo ", 20, 7);
- test_dns_label_unescape_one(".", "", 20, 0);
- test_dns_label_unescape_one("..", "", 20, -EINVAL);
- test_dns_label_unescape_one(".foobar", "", 20, -EINVAL);
- test_dns_label_unescape_one("foobar.", "foobar", 20, 6);
-}
-
-static void test_dns_label_escape_one(const char *what, size_t l, const char *expect, int ret) {
- _cleanup_free_ char *t = NULL;
- int r;
-
- r = dns_label_escape(what, l, &t);
- assert_se(r == ret);
-
- if (r < 0)
- return;
-
- assert_se(streq_ptr(expect, t));
-}
-
-static void test_dns_label_escape(void) {
- test_dns_label_escape_one("", 0, "", 0);
- test_dns_label_escape_one("hallo", 5, "hallo", 5);
- test_dns_label_escape_one("hallo", 6, NULL, -EINVAL);
- test_dns_label_escape_one("hallo hallo.foobar,waldi", 24, "hallo\\032hallo\\.foobar\\044waldi", 31);
-}
-
-static void test_dns_name_normalize_one(const char *what, const char *expect, int ret) {
- _cleanup_free_ char *t = NULL;
- int r;
-
- r = dns_name_normalize(what, &t);
- assert_se(r == ret);
-
- if (r < 0)
- return;
-
- assert_se(streq_ptr(expect, t));
-}
-
-static void test_dns_name_normalize(void) {
- test_dns_name_normalize_one("", "", 0);
- test_dns_name_normalize_one("f", "f", 0);
- test_dns_name_normalize_one("f.waldi", "f.waldi", 0);
- test_dns_name_normalize_one("f \\032.waldi", "f\\032\\032.waldi", 0);
- test_dns_name_normalize_one("\\000", NULL, -EINVAL);
- test_dns_name_normalize_one("..", NULL, -EINVAL);
- test_dns_name_normalize_one(".foobar", NULL, -EINVAL);
- test_dns_name_normalize_one("foobar.", "foobar", 0);
- test_dns_name_normalize_one(".", "", 0);
-}
-
-static void test_dns_name_equal_one(const char *a, const char *b, int ret) {
- int r;
-
- r = dns_name_equal(a, b);
- assert_se(r == ret);
-
- r = dns_name_equal(b, a);
- assert_se(r == ret);
-}
-
-static void test_dns_name_equal(void) {
- test_dns_name_equal_one("", "", true);
- test_dns_name_equal_one("x", "x", true);
- test_dns_name_equal_one("x", "x.", true);
- test_dns_name_equal_one("abc.def", "abc.def", true);
- test_dns_name_equal_one("abc.def", "ABC.def", true);
- test_dns_name_equal_one("abc.def", "CBA.def", false);
- test_dns_name_equal_one("", "xxx", false);
- test_dns_name_equal_one("ab", "a", false);
- test_dns_name_equal_one("\\000", "xxxx", -EINVAL);
- test_dns_name_equal_one(".", "", true);
- test_dns_name_equal_one(".", ".", true);
- test_dns_name_equal_one("..", "..", -EINVAL);
-}
-
-static void test_dns_name_endswith_one(const char *a, const char *b, int ret) {
- assert_se(dns_name_endswith(a, b) == ret);
-}
-
-static void test_dns_name_endswith(void) {
- test_dns_name_endswith_one("", "", true);
- test_dns_name_endswith_one("", "xxx", false);
- test_dns_name_endswith_one("xxx", "", true);
- test_dns_name_endswith_one("x", "x", true);
- test_dns_name_endswith_one("x", "y", false);
- test_dns_name_endswith_one("x.y", "y", true);
- test_dns_name_endswith_one("x.y", "Y", true);
- test_dns_name_endswith_one("x.y", "x", false);
- test_dns_name_endswith_one("x.y.z", "Z", true);
- test_dns_name_endswith_one("x.y.z", "y.Z", true);
- test_dns_name_endswith_one("x.y.z", "x.y.Z", true);
- test_dns_name_endswith_one("x.y.z", "waldo", false);
- test_dns_name_endswith_one("x.y.z.u.v.w", "y.z", false);
- test_dns_name_endswith_one("x.y.z.u.v.w", "u.v.w", true);
- test_dns_name_endswith_one("x.y\001.z", "waldo", -EINVAL);
-}
-
-static void test_dns_name_root(void) {
- assert_se(dns_name_root("") == true);
- assert_se(dns_name_root(".") == true);
- assert_se(dns_name_root("xxx") == false);
- assert_se(dns_name_root("xxx.") == false);
- assert_se(dns_name_root("..") == -EINVAL);
-}
-
-static void test_dns_name_single_label(void) {
- assert_se(dns_name_single_label("") == false);
- assert_se(dns_name_single_label(".") == false);
- assert_se(dns_name_single_label("..") == -EINVAL);
- assert_se(dns_name_single_label("x") == true);
- assert_se(dns_name_single_label("x.") == true);
- assert_se(dns_name_single_label("xx.yy") == false);
-}
-
-static void test_dns_name_reverse_one(const char *address, const char *name) {
- _cleanup_free_ char *p = NULL;
- union in_addr_union a, b = {};
- int familya, familyb;
-
- assert_se(in_addr_from_string_auto(address, &familya, &a) >= 0);
- assert_se(dns_name_reverse(familya, &a, &p) >= 0);
- assert_se(streq(p, name));
- assert_se(dns_name_address(p, &familyb, &b) > 0);
- assert_se(familya == familyb);
- assert_se(in_addr_equal(familya, &a, &b));
-}
-
-static void test_dns_name_reverse(void) {
- test_dns_name_reverse_one("47.11.8.15", "15.8.11.47.in-addr.arpa");
- test_dns_name_reverse_one("fe80::47", "7.4.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.8.e.f.ip6.arpa");
-}
-
-int main(int argc, char *argv[]) {
-
- test_dns_label_unescape();
- test_dns_label_escape();
- test_dns_name_normalize();
- test_dns_name_equal();
- test_dns_name_endswith();
- test_dns_name_root();
- test_dns_name_single_label();
- test_dns_name_reverse();
-
- return 0;
-}