mirror of
https://github.com/systemd/systemd.git
synced 2025-03-22 06:50:18 +03:00
Merge pull request #2372 from poettering/dnssec17
resolved bus API improvements
This commit is contained in:
commit
f7e29f72bf
@ -5171,6 +5171,8 @@ systemd_resolved_SOURCES = \
|
||||
src/resolve/resolved-bus.h \
|
||||
src/resolve/resolved-link.h \
|
||||
src/resolve/resolved-link.c \
|
||||
src/resolve/resolved-link-bus.c \
|
||||
src/resolve/resolved-link-bus.h \
|
||||
src/resolve/resolved-llmnr.h \
|
||||
src/resolve/resolved-llmnr.c \
|
||||
src/resolve/resolved-mdns.h \
|
||||
|
@ -33,6 +33,11 @@ union in_addr_union {
|
||||
struct in6_addr in6;
|
||||
};
|
||||
|
||||
struct in_addr_data {
|
||||
int family;
|
||||
union in_addr_union address;
|
||||
};
|
||||
|
||||
int in_addr_is_null(int family, const union in_addr_union *u);
|
||||
int in_addr_is_link_local(int family, const union in_addr_union *u);
|
||||
int in_addr_is_localhost(int family, const union in_addr_union *u);
|
||||
|
@ -75,6 +75,11 @@ BUS_ERROR_MAP_ELF_REGISTER const sd_bus_error_map bus_common_errors[] = {
|
||||
SD_BUS_ERROR_MAP(BUS_ERROR_ABORTED, ECANCELED),
|
||||
SD_BUS_ERROR_MAP(BUS_ERROR_CONNECTION_FAILURE, ECONNREFUSED),
|
||||
SD_BUS_ERROR_MAP(BUS_ERROR_NO_SUCH_SERVICE, EUNATCH),
|
||||
SD_BUS_ERROR_MAP(BUS_ERROR_DNSSEC_FAILED, EHOSTUNREACH),
|
||||
SD_BUS_ERROR_MAP(BUS_ERROR_NO_TRUST_ANCHOR, EHOSTUNREACH),
|
||||
SD_BUS_ERROR_MAP(BUS_ERROR_RR_TYPE_UNSUPPORTED, EOPNOTSUPP),
|
||||
SD_BUS_ERROR_MAP(BUS_ERROR_NO_SUCH_LINK, ENXIO),
|
||||
SD_BUS_ERROR_MAP(BUS_ERROR_LINK_BUSY, EBUSY),
|
||||
|
||||
SD_BUS_ERROR_MAP(BUS_ERROR_NO_SUCH_TRANSFER, ENXIO),
|
||||
SD_BUS_ERROR_MAP(BUS_ERROR_TRANSFER_IN_PROGRESS, EBUSY),
|
||||
|
@ -77,6 +77,8 @@
|
||||
#define BUS_ERROR_DNSSEC_FAILED "org.freedesktop.resolve1.DnssecFailed"
|
||||
#define BUS_ERROR_NO_TRUST_ANCHOR "org.freedesktop.resolve1.NoTrustAnchor"
|
||||
#define BUS_ERROR_RR_TYPE_UNSUPPORTED "org.freedesktop.resolve1.ResourceRecordTypeUnsupported"
|
||||
#define BUS_ERROR_NO_SUCH_LINK "org.freedesktop.resolve1.NoSuchLink"
|
||||
#define BUS_ERROR_LINK_BUSY "org.freedesktop.resolve1.LinkBusy"
|
||||
#define _BUS_ERROR_DNS "org.freedesktop.resolve1.DnsError."
|
||||
|
||||
#define BUS_ERROR_NO_SUCH_TRANSFER "org.freedesktop.import1.NoSuchTransfer"
|
||||
|
@ -59,15 +59,19 @@ static char *link_bus_path(Link *link) {
|
||||
int link_node_enumerator(sd_bus *bus, const char *path, void *userdata, char ***nodes, sd_bus_error *error) {
|
||||
_cleanup_strv_free_ char **l = NULL;
|
||||
Manager *m = userdata;
|
||||
unsigned c = 0;
|
||||
Link *link;
|
||||
Iterator i;
|
||||
int r;
|
||||
|
||||
assert(bus);
|
||||
assert(path);
|
||||
assert(m);
|
||||
assert(nodes);
|
||||
|
||||
l = new0(char*, hashmap_size(m->links) + 1);
|
||||
if (!l)
|
||||
return -ENOMEM;
|
||||
|
||||
HASHMAP_FOREACH(link, m->links, i) {
|
||||
char *p;
|
||||
|
||||
@ -75,11 +79,10 @@ int link_node_enumerator(sd_bus *bus, const char *path, void *userdata, char ***
|
||||
if (!p)
|
||||
return -ENOMEM;
|
||||
|
||||
r = strv_consume(&l, p);
|
||||
if (r < 0)
|
||||
return r;
|
||||
l[c++] = p;
|
||||
}
|
||||
|
||||
l[c] = NULL;
|
||||
*nodes = l;
|
||||
l = NULL;
|
||||
|
||||
@ -99,7 +102,7 @@ int link_object_find(sd_bus *bus, const char *path, const char *interface, void
|
||||
assert(found);
|
||||
|
||||
r = sd_bus_path_decode(path, "/org/freedesktop/network1/link", &identifier);
|
||||
if (r < 0)
|
||||
if (r <= 0)
|
||||
return 0;
|
||||
|
||||
r = parse_ifindex(identifier, &ifindex);
|
||||
|
@ -64,10 +64,12 @@ static void print_source(uint64_t flags, usec_t rtt) {
|
||||
fputs("\n-- Information acquired via", stdout);
|
||||
|
||||
if (flags != 0)
|
||||
printf(" protocol%s%s%s",
|
||||
printf(" protocol%s%s%s%s%s",
|
||||
flags & SD_RESOLVED_DNS ? " DNS" :"",
|
||||
flags & SD_RESOLVED_LLMNR_IPV4 ? " LLMNR/IPv4" : "",
|
||||
flags & SD_RESOLVED_LLMNR_IPV6 ? " LLMNR/IPv6" : "");
|
||||
flags & SD_RESOLVED_LLMNR_IPV6 ? " LLMNR/IPv6" : "",
|
||||
flags & SD_RESOLVED_MDNS_IPV4 ? "mDNS/IPv4" : "",
|
||||
flags & SD_RESOLVED_MDNS_IPV6 ? "mDNS/IPv6" : "");
|
||||
|
||||
assert_se(format_timespan(rtt_str, sizeof(rtt_str), rtt, 100));
|
||||
|
||||
@ -769,10 +771,26 @@ static int show_statistics(sd_bus *bus) {
|
||||
uint64_t n_current_transactions, n_total_transactions,
|
||||
cache_size, n_cache_hit, n_cache_miss,
|
||||
n_dnssec_secure, n_dnssec_insecure, n_dnssec_bogus, n_dnssec_indeterminate;
|
||||
int r;
|
||||
int r, dnssec_supported;
|
||||
|
||||
assert(bus);
|
||||
|
||||
r = sd_bus_get_property_trivial(bus,
|
||||
"org.freedesktop.resolve1",
|
||||
"/org/freedesktop/resolve1",
|
||||
"org.freedesktop.resolve1.Manager",
|
||||
"DNSSECSupported",
|
||||
&error,
|
||||
'b',
|
||||
&dnssec_supported);
|
||||
if (r < 0)
|
||||
return log_error_errno(r, "Failed to get DNSSEC supported state: %s", bus_error_message(&error, r));
|
||||
|
||||
printf("DNSSEC supported by current servers: %s%s%s\n\n",
|
||||
ansi_highlight(),
|
||||
yes_no(dnssec_supported),
|
||||
ansi_normal());
|
||||
|
||||
r = sd_bus_get_property(bus,
|
||||
"org.freedesktop.resolve1",
|
||||
"/org/freedesktop/resolve1",
|
||||
@ -916,7 +934,7 @@ static void help(void) {
|
||||
" --version Show package version\n"
|
||||
" -4 Resolve IPv4 addresses\n"
|
||||
" -6 Resolve IPv6 addresses\n"
|
||||
" -i INTERFACE Look on interface\n"
|
||||
" -i --interface=INTERFACE Look on interface\n"
|
||||
" -p --protocol=PROTOCOL Look via protocol\n"
|
||||
" -t --type=TYPE Query RR with DNS type\n"
|
||||
" -c --class=CLASS Query RR with DNS class\n"
|
||||
@ -950,6 +968,7 @@ static int parse_argv(int argc, char *argv[]) {
|
||||
{ "type", required_argument, NULL, 't' },
|
||||
{ "class", required_argument, NULL, 'c' },
|
||||
{ "legend", required_argument, NULL, ARG_LEGEND },
|
||||
{ "interface", required_argument, NULL, 'i' },
|
||||
{ "protocol", required_argument, NULL, 'p' },
|
||||
{ "cname", required_argument, NULL, ARG_CNAME },
|
||||
{ "service", no_argument, NULL, ARG_SERVICE },
|
||||
|
@ -25,6 +25,7 @@
|
||||
#include "dns-domain.h"
|
||||
#include "resolved-bus.h"
|
||||
#include "resolved-def.h"
|
||||
#include "resolved-link-bus.h"
|
||||
|
||||
static int reply_query_state(DnsQuery *q) {
|
||||
|
||||
@ -1116,17 +1117,23 @@ fail:
|
||||
return r;
|
||||
}
|
||||
|
||||
static int append_dns_server(sd_bus_message *reply, DnsServer *s) {
|
||||
int bus_dns_server_append(sd_bus_message *reply, DnsServer *s, bool with_ifindex) {
|
||||
int r;
|
||||
|
||||
assert(reply);
|
||||
assert(s);
|
||||
|
||||
r = sd_bus_message_open_container(reply, 'r', "iiay");
|
||||
r = sd_bus_message_open_container(reply, 'r', with_ifindex ? "iiay" : "iay");
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
||||
r = sd_bus_message_append(reply, "ii", s->link ? s->link->ifindex : 0, s->family);
|
||||
if (with_ifindex) {
|
||||
r = sd_bus_message_append(reply, "i", s->link ? s->link->ifindex : 0);
|
||||
if (r < 0)
|
||||
return r;
|
||||
}
|
||||
|
||||
r = sd_bus_message_append(reply, "i", s->family);
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
||||
@ -1161,7 +1168,7 @@ static int bus_property_get_dns_servers(
|
||||
return r;
|
||||
|
||||
LIST_FOREACH(servers, s, m->dns_servers) {
|
||||
r = append_dns_server(reply, s);
|
||||
r = bus_dns_server_append(reply, s, true);
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
||||
@ -1170,7 +1177,7 @@ static int bus_property_get_dns_servers(
|
||||
|
||||
HASHMAP_FOREACH(l, m->links, i) {
|
||||
LIST_FOREACH(servers, s, l->dns_servers) {
|
||||
r = append_dns_server(reply, s);
|
||||
r = bus_dns_server_append(reply, s, true);
|
||||
if (r < 0)
|
||||
return r;
|
||||
c++;
|
||||
@ -1179,7 +1186,7 @@ static int bus_property_get_dns_servers(
|
||||
|
||||
if (c == 0) {
|
||||
LIST_FOREACH(servers, s, m->fallback_dns_servers) {
|
||||
r = append_dns_server(reply, s);
|
||||
r = bus_dns_server_append(reply, s, true);
|
||||
if (r < 0)
|
||||
return r;
|
||||
}
|
||||
@ -1292,6 +1299,23 @@ static int bus_property_get_dnssec_statistics(
|
||||
(uint64_t) m->n_dnssec_indeterminate);
|
||||
}
|
||||
|
||||
static int bus_property_get_dnssec_supported(
|
||||
sd_bus *bus,
|
||||
const char *path,
|
||||
const char *interface,
|
||||
const char *property,
|
||||
sd_bus_message *reply,
|
||||
void *userdata,
|
||||
sd_bus_error *error) {
|
||||
|
||||
Manager *m = userdata;
|
||||
|
||||
assert(reply);
|
||||
assert(m);
|
||||
|
||||
return sd_bus_message_append(reply, "b", manager_dnssec_supported(m));
|
||||
}
|
||||
|
||||
static int bus_method_reset_statistics(sd_bus_message *message, void *userdata, sd_bus_error *error) {
|
||||
Manager *m = userdata;
|
||||
DnsScope *s;
|
||||
@ -1308,20 +1332,140 @@ static int bus_method_reset_statistics(sd_bus_message *message, void *userdata,
|
||||
return sd_bus_reply_method_return(message, NULL);
|
||||
}
|
||||
|
||||
static int get_any_link(Manager *m, int ifindex, Link **ret, sd_bus_error *error) {
|
||||
Link *l;
|
||||
|
||||
assert(m);
|
||||
assert(ret);
|
||||
|
||||
if (ifindex <= 0)
|
||||
return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Invalid interface index");
|
||||
|
||||
l = hashmap_get(m->links, INT_TO_PTR(ifindex));
|
||||
if (!l)
|
||||
return sd_bus_error_setf(error, BUS_ERROR_NO_SUCH_LINK, "Link %i not known", ifindex);
|
||||
|
||||
*ret = l;
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int get_unmanaged_link(Manager *m, int ifindex, Link **ret, sd_bus_error *error) {
|
||||
Link *l;
|
||||
int r;
|
||||
|
||||
assert(m);
|
||||
assert(ret);
|
||||
|
||||
r = get_any_link(m, ifindex, &l, error);
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
||||
if (l->flags & IFF_LOOPBACK)
|
||||
return sd_bus_error_setf(error, BUS_ERROR_LINK_BUSY, "Link %s is loopback device.", l->name);
|
||||
if (l->is_managed)
|
||||
return sd_bus_error_setf(error, BUS_ERROR_LINK_BUSY, "Link %s is managed.", l->name);
|
||||
|
||||
*ret = l;
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int call_link_method(Manager *m, sd_bus_message *message, sd_bus_message_handler_t handler, sd_bus_error *error) {
|
||||
int ifindex, r;
|
||||
Link *l;
|
||||
|
||||
assert(m);
|
||||
assert(message);
|
||||
assert(handler);
|
||||
|
||||
assert_cc(sizeof(int) == sizeof(int32_t));
|
||||
r = sd_bus_message_read(message, "i", &ifindex);
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
||||
r = get_unmanaged_link(m, ifindex, &l, error);
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
||||
return handler(message, l, error);
|
||||
}
|
||||
|
||||
static int bus_method_set_link_dns_servers(sd_bus_message *message, void *userdata, sd_bus_error *error) {
|
||||
return call_link_method(userdata, message, bus_link_method_set_dns_servers, error);
|
||||
}
|
||||
|
||||
static int bus_method_set_link_search_domains(sd_bus_message *message, void *userdata, sd_bus_error *error) {
|
||||
return call_link_method(userdata, message, bus_link_method_set_search_domains, error);
|
||||
}
|
||||
|
||||
static int bus_method_set_link_llmnr(sd_bus_message *message, void *userdata, sd_bus_error *error) {
|
||||
return call_link_method(userdata, message, bus_link_method_set_llmnr, error);
|
||||
}
|
||||
|
||||
static int bus_method_set_link_mdns(sd_bus_message *message, void *userdata, sd_bus_error *error) {
|
||||
return call_link_method(userdata, message, bus_link_method_set_mdns, error);
|
||||
}
|
||||
|
||||
static int bus_method_set_link_dnssec(sd_bus_message *message, void *userdata, sd_bus_error *error) {
|
||||
return call_link_method(userdata, message, bus_link_method_set_dnssec, error);
|
||||
}
|
||||
|
||||
static int bus_method_set_link_dnssec_negative_trust_anchors(sd_bus_message *message, void *userdata, sd_bus_error *error) {
|
||||
return call_link_method(userdata, message, bus_link_method_set_dnssec_negative_trust_anchors, error);
|
||||
}
|
||||
|
||||
static int bus_method_revert_link(sd_bus_message *message, void *userdata, sd_bus_error *error) {
|
||||
return call_link_method(userdata, message, bus_link_method_revert, error);
|
||||
}
|
||||
|
||||
static int bus_method_get_link(sd_bus_message *message, void *userdata, sd_bus_error *error) {
|
||||
_cleanup_free_ char *p = NULL;
|
||||
Manager *m = userdata;
|
||||
int r, ifindex;
|
||||
Link *l;
|
||||
|
||||
assert(message);
|
||||
assert(m);
|
||||
|
||||
assert_cc(sizeof(int) == sizeof(int32_t));
|
||||
r = sd_bus_message_read(message, "i", &ifindex);
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
||||
r = get_any_link(m, ifindex, &l, error);
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
||||
p = link_bus_path(l);
|
||||
if (!p)
|
||||
return -ENOMEM;
|
||||
|
||||
return sd_bus_reply_method_return(message, "o", p);
|
||||
}
|
||||
|
||||
static const sd_bus_vtable resolve_vtable[] = {
|
||||
SD_BUS_VTABLE_START(0),
|
||||
SD_BUS_PROPERTY("LLMNRHostname", "s", NULL, offsetof(Manager, llmnr_hostname), 0),
|
||||
SD_BUS_PROPERTY("DNSServers", "a(iiay)", bus_property_get_dns_servers, 0, 0),
|
||||
SD_BUS_PROPERTY("SearchDomains", "a(is)", bus_property_get_search_domains, 0, 0),
|
||||
SD_BUS_PROPERTY("DNS", "a(iiay)", bus_property_get_dns_servers, 0, 0),
|
||||
SD_BUS_PROPERTY("Domains", "a(is)", bus_property_get_search_domains, 0, 0),
|
||||
SD_BUS_PROPERTY("TransactionStatistics", "(tt)", bus_property_get_transaction_statistics, 0, 0),
|
||||
SD_BUS_PROPERTY("CacheStatistics", "(ttt)", bus_property_get_cache_statistics, 0, 0),
|
||||
SD_BUS_PROPERTY("DNSSECStatistics", "(tttt)", bus_property_get_dnssec_statistics, 0, 0),
|
||||
SD_BUS_PROPERTY("DNSSECSupported", "b", bus_property_get_dnssec_supported, 0, 0),
|
||||
|
||||
SD_BUS_METHOD("ResolveHostname", "isit", "a(iiay)st", bus_method_resolve_hostname, SD_BUS_VTABLE_UNPRIVILEGED),
|
||||
SD_BUS_METHOD("ResolveAddress", "iiayt", "a(is)t", bus_method_resolve_address, SD_BUS_VTABLE_UNPRIVILEGED),
|
||||
SD_BUS_METHOD("ResolveRecord", "isqqt", "a(iqqay)t", bus_method_resolve_record, SD_BUS_VTABLE_UNPRIVILEGED),
|
||||
SD_BUS_METHOD("ResolveService", "isssit", "a(qqqsa(iiay)s)aayssst", bus_method_resolve_service, SD_BUS_VTABLE_UNPRIVILEGED),
|
||||
SD_BUS_METHOD("ResetStatistics", NULL, NULL, bus_method_reset_statistics, 0),
|
||||
SD_BUS_METHOD("GetLink", "i", "o", bus_method_get_link, SD_BUS_VTABLE_UNPRIVILEGED),
|
||||
SD_BUS_METHOD("SetLinkDNS", "ia(iay)", NULL, bus_method_set_link_dns_servers, 0),
|
||||
SD_BUS_METHOD("SetLinkDomains", "ias", NULL, bus_method_set_link_search_domains, 0),
|
||||
SD_BUS_METHOD("SetLinkLLMNR", "is", NULL, bus_method_set_link_llmnr, 0),
|
||||
SD_BUS_METHOD("SetLinkMulticastDNS", "is", NULL, bus_method_set_link_mdns, 0),
|
||||
SD_BUS_METHOD("SetLinkDNSSEC", "is", NULL, bus_method_set_link_dnssec, 0),
|
||||
SD_BUS_METHOD("SetLinkDNSSECNegativeTrustAnchors", "ias", NULL, bus_method_set_link_dnssec_negative_trust_anchors, 0),
|
||||
SD_BUS_METHOD("RevertLink", "i", NULL, bus_method_revert_link, 0),
|
||||
|
||||
SD_BUS_VTABLE_END,
|
||||
};
|
||||
|
||||
@ -1387,6 +1531,14 @@ int manager_connect_bus(Manager *m) {
|
||||
if (r < 0)
|
||||
return log_error_errno(r, "Failed to register object: %m");
|
||||
|
||||
r = sd_bus_add_fallback_vtable(m->bus, NULL, "/org/freedesktop/resolve1/link", "org.freedesktop.resolve1.Link", link_vtable, link_object_find, m);
|
||||
if (r < 0)
|
||||
return log_error_errno(r, "Failed to register link objects: %m");
|
||||
|
||||
r = sd_bus_add_node_enumerator(m->bus, NULL, "/org/freedesktop/resolve1/link", link_node_enumerator, m);
|
||||
if (r < 0)
|
||||
return log_error_errno(r, "Failed to register link enumerator: %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");
|
||||
|
@ -24,3 +24,4 @@
|
||||
#include "resolved-manager.h"
|
||||
|
||||
int manager_connect_bus(Manager *m);
|
||||
int bus_dns_server_append(sd_bus_message *reply, DnsServer *s, bool with_ifindex);
|
||||
|
@ -67,11 +67,9 @@ int dns_scope_new(Manager *m, DnsScope **ret, Link *l, DnsProtocol protocol, int
|
||||
* changes. */
|
||||
|
||||
if (l)
|
||||
s->dnssec_mode = l->dnssec_mode;
|
||||
if (s->dnssec_mode == _DNSSEC_MODE_INVALID)
|
||||
s->dnssec_mode = m->dnssec_mode;
|
||||
if (s->dnssec_mode == _DNSSEC_MODE_INVALID)
|
||||
s->dnssec_mode = DNSSEC_NO;
|
||||
s->dnssec_mode = link_get_dnssec_mode(l);
|
||||
else
|
||||
s->dnssec_mode = manager_get_dnssec_mode(m);
|
||||
}
|
||||
|
||||
LIST_PREPEND(scopes, m->dns_scopes, s);
|
||||
|
528
src/resolve/resolved-link-bus.c
Normal file
528
src/resolve/resolved-link-bus.c
Normal file
@ -0,0 +1,528 @@
|
||||
/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
|
||||
|
||||
/***
|
||||
This file is part of systemd.
|
||||
|
||||
Copyright 2016 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 "alloc-util.h"
|
||||
#include "bus-util.h"
|
||||
#include "parse-util.h"
|
||||
#include "resolve-util.h"
|
||||
#include "resolved-bus.h"
|
||||
#include "resolved-link-bus.h"
|
||||
#include "strv.h"
|
||||
|
||||
static BUS_DEFINE_PROPERTY_GET_ENUM(property_get_resolve_support, resolve_support, ResolveSupport);
|
||||
static BUS_DEFINE_PROPERTY_GET_ENUM(property_get_dnssec_mode, dnssec_mode, DnssecMode);
|
||||
|
||||
static int property_get_dns(
|
||||
sd_bus *bus,
|
||||
const char *path,
|
||||
const char *interface,
|
||||
const char *property,
|
||||
sd_bus_message *reply,
|
||||
void *userdata,
|
||||
sd_bus_error *error) {
|
||||
|
||||
Link *l = userdata;
|
||||
DnsServer *s;
|
||||
int r;
|
||||
|
||||
assert(reply);
|
||||
assert(l);
|
||||
|
||||
r = sd_bus_message_open_container(reply, 'a', "(iay)");
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
||||
LIST_FOREACH(servers, s, l->dns_servers) {
|
||||
r = bus_dns_server_append(reply, s, false);
|
||||
if (r < 0)
|
||||
return r;
|
||||
}
|
||||
|
||||
return sd_bus_message_close_container(reply);
|
||||
}
|
||||
|
||||
static int property_get_domains(
|
||||
sd_bus *bus,
|
||||
const char *path,
|
||||
const char *interface,
|
||||
const char *property,
|
||||
sd_bus_message *reply,
|
||||
void *userdata,
|
||||
sd_bus_error *error) {
|
||||
|
||||
Link *l = userdata;
|
||||
DnsSearchDomain *d;
|
||||
int r;
|
||||
|
||||
assert(reply);
|
||||
assert(l);
|
||||
|
||||
r = sd_bus_message_open_container(reply, 'a', "s");
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
||||
LIST_FOREACH(domains, d, l->search_domains) {
|
||||
r = sd_bus_message_append(reply, "s", d->name);
|
||||
if (r < 0)
|
||||
return r;
|
||||
}
|
||||
|
||||
return sd_bus_message_close_container(reply);
|
||||
}
|
||||
|
||||
static int property_get_scopes_mask(
|
||||
sd_bus *bus,
|
||||
const char *path,
|
||||
const char *interface,
|
||||
const char *property,
|
||||
sd_bus_message *reply,
|
||||
void *userdata,
|
||||
sd_bus_error *error) {
|
||||
|
||||
Link *l = userdata;
|
||||
uint64_t mask;
|
||||
|
||||
assert(reply);
|
||||
assert(l);
|
||||
|
||||
mask = (l->unicast_scope ? SD_RESOLVED_DNS : 0) |
|
||||
(l->llmnr_ipv4_scope ? SD_RESOLVED_LLMNR_IPV4 : 0) |
|
||||
(l->llmnr_ipv6_scope ? SD_RESOLVED_LLMNR_IPV6 : 0) |
|
||||
(l->mdns_ipv4_scope ? SD_RESOLVED_MDNS_IPV4 : 0) |
|
||||
(l->mdns_ipv6_scope ? SD_RESOLVED_MDNS_IPV6 : 0);
|
||||
|
||||
return sd_bus_message_append(reply, "t", mask);
|
||||
}
|
||||
|
||||
static int property_get_ntas(
|
||||
sd_bus *bus,
|
||||
const char *path,
|
||||
const char *interface,
|
||||
const char *property,
|
||||
sd_bus_message *reply,
|
||||
void *userdata,
|
||||
sd_bus_error *error) {
|
||||
|
||||
Link *l = userdata;
|
||||
const char *name;
|
||||
Iterator i;
|
||||
int r;
|
||||
|
||||
assert(reply);
|
||||
assert(l);
|
||||
|
||||
r = sd_bus_message_open_container(reply, 'a', "s");
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
||||
SET_FOREACH(name, l->dnssec_negative_trust_anchors, i) {
|
||||
r = sd_bus_message_append(reply, "s", name);
|
||||
if (r < 0)
|
||||
return r;
|
||||
}
|
||||
|
||||
return sd_bus_message_close_container(reply);
|
||||
}
|
||||
|
||||
static int property_get_dnssec_supported(
|
||||
sd_bus *bus,
|
||||
const char *path,
|
||||
const char *interface,
|
||||
const char *property,
|
||||
sd_bus_message *reply,
|
||||
void *userdata,
|
||||
sd_bus_error *error) {
|
||||
|
||||
Link *l = userdata;
|
||||
|
||||
assert(reply);
|
||||
assert(l);
|
||||
|
||||
return sd_bus_message_append(reply, "b", link_dnssec_supported(l));
|
||||
}
|
||||
|
||||
int bus_link_method_set_dns_servers(sd_bus_message *message, void *userdata, sd_bus_error *error) {
|
||||
_cleanup_free_ struct in_addr_data *dns = NULL;
|
||||
size_t allocated = 0, n = 0;
|
||||
Link *l = userdata;
|
||||
unsigned i;
|
||||
int r;
|
||||
|
||||
assert(message);
|
||||
assert(l);
|
||||
|
||||
r = sd_bus_message_enter_container(message, 'a', "(iay)");
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
||||
for (;;) {
|
||||
int family;
|
||||
size_t sz;
|
||||
const void *d;
|
||||
|
||||
assert_cc(sizeof(int) == sizeof(int32_t));
|
||||
|
||||
r = sd_bus_message_enter_container(message, 'r', "iay");
|
||||
if (r < 0)
|
||||
return r;
|
||||
if (r == 0)
|
||||
break;
|
||||
|
||||
r = sd_bus_message_read(message, "i", &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_exit_container(message);
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
||||
if (!GREEDY_REALLOC(dns, allocated, n+1))
|
||||
return -ENOMEM;
|
||||
|
||||
dns[n].family = family;
|
||||
memcpy(&dns[n].address, d, sz);
|
||||
n++;
|
||||
}
|
||||
|
||||
r = sd_bus_message_exit_container(message);
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
||||
dns_server_mark_all(l->dns_servers);
|
||||
|
||||
for (i = 0; i < n; i++) {
|
||||
DnsServer *s;
|
||||
|
||||
s = dns_server_find(l->dns_servers, dns[i].family, &dns[i].address);
|
||||
if (s)
|
||||
dns_server_move_back_and_unmark(s);
|
||||
else {
|
||||
r = dns_server_new(l->manager, NULL, DNS_SERVER_LINK, l, dns[i].family, &dns[i].address);
|
||||
if (r < 0)
|
||||
goto clear;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
dns_server_unlink_marked(l->dns_servers);
|
||||
link_allocate_scopes(l);
|
||||
|
||||
return sd_bus_reply_method_return(message, NULL);
|
||||
|
||||
clear:
|
||||
dns_server_unlink_all(l->dns_servers);
|
||||
return r;
|
||||
}
|
||||
|
||||
int bus_link_method_set_search_domains(sd_bus_message *message, void *userdata, sd_bus_error *error) {
|
||||
_cleanup_free_ char **domains = NULL;
|
||||
Link *l = userdata;
|
||||
char **i;
|
||||
int r;
|
||||
|
||||
assert(message);
|
||||
assert(l);
|
||||
|
||||
r = sd_bus_message_read_strv(message, &domains);
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
||||
STRV_FOREACH(i, domains) {
|
||||
|
||||
r = dns_name_is_valid(*i);
|
||||
if (r < 0)
|
||||
return r;
|
||||
if (r == 0)
|
||||
return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Invalid search domain %s", *i);
|
||||
if (dns_name_is_root(*i))
|
||||
return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Root domain is not suitable as search domain");
|
||||
}
|
||||
|
||||
dns_search_domain_mark_all(l->search_domains);
|
||||
|
||||
STRV_FOREACH(i, domains) {
|
||||
DnsSearchDomain *d;
|
||||
|
||||
r = dns_search_domain_find(l->search_domains, *i, &d);
|
||||
if (r < 0)
|
||||
goto clear;
|
||||
|
||||
if (r > 0)
|
||||
dns_search_domain_move_back_and_unmark(d);
|
||||
else {
|
||||
r = dns_search_domain_new(l->manager, NULL, DNS_SEARCH_DOMAIN_LINK, l, *i);
|
||||
if (r < 0)
|
||||
goto clear;
|
||||
}
|
||||
}
|
||||
|
||||
dns_search_domain_unlink_marked(l->search_domains);
|
||||
return sd_bus_reply_method_return(message, NULL);
|
||||
|
||||
clear:
|
||||
dns_search_domain_unlink_all(l->search_domains);
|
||||
return r;
|
||||
}
|
||||
|
||||
int bus_link_method_set_llmnr(sd_bus_message *message, void *userdata, sd_bus_error *error) {
|
||||
Link *l = userdata;
|
||||
ResolveSupport mode;
|
||||
const char *llmnr;
|
||||
int r;
|
||||
|
||||
assert(message);
|
||||
assert(l);
|
||||
|
||||
r = sd_bus_message_read(message, "s", &llmnr);
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
||||
if (isempty(llmnr))
|
||||
mode = RESOLVE_SUPPORT_YES;
|
||||
else {
|
||||
mode = resolve_support_from_string(llmnr);
|
||||
if (mode < 0)
|
||||
return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Invalid LLMNR setting: %s", llmnr);
|
||||
}
|
||||
|
||||
l->llmnr_support = mode;
|
||||
link_allocate_scopes(l);
|
||||
link_add_rrs(l, false);
|
||||
|
||||
return sd_bus_reply_method_return(message, NULL);
|
||||
}
|
||||
|
||||
int bus_link_method_set_mdns(sd_bus_message *message, void *userdata, sd_bus_error *error) {
|
||||
Link *l = userdata;
|
||||
ResolveSupport mode;
|
||||
const char *mdns;
|
||||
int r;
|
||||
|
||||
assert(message);
|
||||
assert(l);
|
||||
|
||||
r = sd_bus_message_read(message, "s", &mdns);
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
||||
if (isempty(mdns))
|
||||
mode = RESOLVE_SUPPORT_NO;
|
||||
else {
|
||||
mode = resolve_support_from_string(mdns);
|
||||
if (mode < 0)
|
||||
return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Invalid MulticastDNS setting: %s", mdns);
|
||||
}
|
||||
|
||||
l->mdns_support = mode;
|
||||
link_allocate_scopes(l);
|
||||
link_add_rrs(l, false);
|
||||
|
||||
return sd_bus_reply_method_return(message, NULL);
|
||||
}
|
||||
|
||||
int bus_link_method_set_dnssec(sd_bus_message *message, void *userdata, sd_bus_error *error) {
|
||||
Link *l = userdata;
|
||||
const char *dnssec;
|
||||
DnssecMode mode;
|
||||
int r;
|
||||
|
||||
assert(message);
|
||||
assert(l);
|
||||
|
||||
r = sd_bus_message_read(message, "s", &dnssec);
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
||||
if (isempty(dnssec))
|
||||
mode = _DNSSEC_MODE_INVALID;
|
||||
else {
|
||||
mode = dnssec_mode_from_string(dnssec);
|
||||
if (mode < 0)
|
||||
return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Invalid DNSSEC setting: %s", dnssec);
|
||||
}
|
||||
|
||||
link_set_dnssec_mode(l, mode);
|
||||
|
||||
return sd_bus_reply_method_return(message, NULL);
|
||||
}
|
||||
|
||||
int bus_link_method_set_dnssec_negative_trust_anchors(sd_bus_message *message, void *userdata, sd_bus_error *error) {
|
||||
_cleanup_set_free_free_ Set *ns = NULL;
|
||||
_cleanup_free_ char **ntas = NULL;
|
||||
Link *l = userdata;
|
||||
int r;
|
||||
char **i;
|
||||
|
||||
assert(message);
|
||||
assert(l);
|
||||
|
||||
r = sd_bus_message_read_strv(message, &ntas);
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
||||
STRV_FOREACH(i, ntas) {
|
||||
r = dns_name_is_valid(*i);
|
||||
if (r < 0)
|
||||
return r;
|
||||
if (r == 0)
|
||||
return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Invalid search negative trust anchor domain: %s", *i);
|
||||
}
|
||||
|
||||
ns = set_new(&dns_name_hash_ops);
|
||||
if (!ns)
|
||||
return -ENOMEM;
|
||||
|
||||
STRV_FOREACH(i, ntas) {
|
||||
r = set_put_strdup(ns, *i);
|
||||
if (r < 0)
|
||||
return r;
|
||||
}
|
||||
|
||||
set_free_free(l->dnssec_negative_trust_anchors);
|
||||
l->dnssec_negative_trust_anchors = ns;
|
||||
ns = NULL;
|
||||
|
||||
return sd_bus_reply_method_return(message, NULL);
|
||||
}
|
||||
|
||||
int bus_link_method_revert(sd_bus_message *message, void *userdata, sd_bus_error *error) {
|
||||
Link *l = userdata;
|
||||
|
||||
assert(message);
|
||||
assert(l);
|
||||
|
||||
link_flush_settings(l);
|
||||
link_allocate_scopes(l);
|
||||
link_add_rrs(l, false);
|
||||
|
||||
return sd_bus_reply_method_return(message, NULL);
|
||||
}
|
||||
|
||||
const sd_bus_vtable link_vtable[] = {
|
||||
SD_BUS_VTABLE_START(0),
|
||||
|
||||
SD_BUS_PROPERTY("ScopesMask", "t", property_get_scopes_mask, 0, 0),
|
||||
SD_BUS_PROPERTY("DNS", "a(iay)", property_get_dns, 0, 0),
|
||||
SD_BUS_PROPERTY("Domains", "as", property_get_domains, 0, 0),
|
||||
SD_BUS_PROPERTY("LLMNR", "s", property_get_resolve_support, offsetof(Link, llmnr_support), 0),
|
||||
SD_BUS_PROPERTY("MulticastDNS", "s", property_get_resolve_support, offsetof(Link, mdns_support), 0),
|
||||
SD_BUS_PROPERTY("DNSSEC", "s", property_get_dnssec_mode, offsetof(Link, dnssec_mode), 0),
|
||||
SD_BUS_PROPERTY("DNSSECNegativeTrustAnchors", "as", property_get_ntas, 0, 0),
|
||||
SD_BUS_PROPERTY("DNSSECSupport", "b", property_get_dnssec_supported, 0, 0),
|
||||
|
||||
SD_BUS_METHOD("SetDNS", "a(iay)", NULL, bus_link_method_set_dns_servers, 0),
|
||||
SD_BUS_METHOD("SetDomains", "as", NULL, bus_link_method_set_search_domains, 0),
|
||||
SD_BUS_METHOD("SetLLMNR", "s", NULL, bus_link_method_set_llmnr, 0),
|
||||
SD_BUS_METHOD("SetMulticastDNS", "s", NULL, bus_link_method_set_mdns, 0),
|
||||
SD_BUS_METHOD("SetDNSSEC", "s", NULL, bus_link_method_set_dnssec, 0),
|
||||
SD_BUS_METHOD("SetDNSSECNegativeTrustAnchors", "as", NULL, bus_link_method_set_dnssec_negative_trust_anchors, 0),
|
||||
SD_BUS_METHOD("Revert", NULL, NULL, bus_link_method_revert, 0),
|
||||
|
||||
SD_BUS_VTABLE_END
|
||||
};
|
||||
|
||||
int link_object_find(sd_bus *bus, const char *path, const char *interface, void *userdata, void **found, sd_bus_error *error) {
|
||||
_cleanup_free_ char *e = NULL;
|
||||
Manager *m = userdata;
|
||||
int ifindex;
|
||||
Link *link;
|
||||
int r;
|
||||
|
||||
assert(bus);
|
||||
assert(path);
|
||||
assert(interface);
|
||||
assert(found);
|
||||
assert(m);
|
||||
|
||||
r = sd_bus_path_decode(path, "/org/freedesktop/resolve1/link", &e);
|
||||
if (r <= 0)
|
||||
return 0;
|
||||
|
||||
r = parse_ifindex(e, &ifindex);
|
||||
if (r < 0)
|
||||
return 0;
|
||||
|
||||
link = hashmap_get(m->links, INT_TO_PTR(ifindex));
|
||||
if (!link)
|
||||
return 0;
|
||||
|
||||
*found = link;
|
||||
return 1;
|
||||
}
|
||||
|
||||
char *link_bus_path(Link *link) {
|
||||
_cleanup_free_ char *ifindex = NULL;
|
||||
char *p;
|
||||
int r;
|
||||
|
||||
assert(link);
|
||||
|
||||
if (asprintf(&ifindex, "%i", link->ifindex) < 0)
|
||||
return NULL;
|
||||
|
||||
r = sd_bus_path_encode("/org/freedesktop/resolve1/link", ifindex, &p);
|
||||
if (r < 0)
|
||||
return NULL;
|
||||
|
||||
return p;
|
||||
}
|
||||
|
||||
int link_node_enumerator(sd_bus *bus, const char *path, void *userdata, char ***nodes, sd_bus_error *error) {
|
||||
_cleanup_strv_free_ char **l = NULL;
|
||||
Manager *m = userdata;
|
||||
Link *link;
|
||||
Iterator i;
|
||||
unsigned c = 0;
|
||||
|
||||
assert(bus);
|
||||
assert(path);
|
||||
assert(m);
|
||||
assert(nodes);
|
||||
|
||||
l = new0(char*, hashmap_size(m->links) + 1);
|
||||
if (!l)
|
||||
return -ENOMEM;
|
||||
|
||||
HASHMAP_FOREACH(link, m->links, i) {
|
||||
char *p;
|
||||
|
||||
p = link_bus_path(link);
|
||||
if (!p)
|
||||
return -ENOMEM;
|
||||
|
||||
l[c++] = p;
|
||||
}
|
||||
|
||||
l[c] = NULL;
|
||||
*nodes = l;
|
||||
l = NULL;
|
||||
|
||||
return 1;
|
||||
}
|
40
src/resolve/resolved-link-bus.h
Normal file
40
src/resolve/resolved-link-bus.h
Normal file
@ -0,0 +1,40 @@
|
||||
/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
|
||||
|
||||
#pragma once
|
||||
|
||||
/***
|
||||
This file is part of systemd.
|
||||
|
||||
Copyright 2016 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 "resolved-link.h"
|
||||
|
||||
extern const sd_bus_vtable link_vtable[];
|
||||
|
||||
int link_object_find(sd_bus *bus, const char *path, const char *interface, void *userdata, void **found, sd_bus_error *error);
|
||||
char *link_bus_path(Link *link);
|
||||
int link_node_enumerator(sd_bus *bus, const char *path, void *userdata, char ***nodes, sd_bus_error *error);
|
||||
|
||||
int bus_link_method_set_dns_servers(sd_bus_message *message, void *userdata, sd_bus_error *error);
|
||||
int bus_link_method_set_search_domains(sd_bus_message *message, void *userdata, sd_bus_error *error);
|
||||
int bus_link_method_set_llmnr(sd_bus_message *message, void *userdata, sd_bus_error *error);
|
||||
int bus_link_method_set_mdns(sd_bus_message *message, void *userdata, sd_bus_error *error);
|
||||
int bus_link_method_set_dnssec(sd_bus_message *message, void *userdata, sd_bus_error *error);
|
||||
int bus_link_method_set_dnssec_negative_trust_anchors(sd_bus_message *message, void *userdata, sd_bus_error *error);
|
||||
int bus_link_method_revert(sd_bus_message *message, void *userdata, sd_bus_error *error);
|
@ -63,15 +63,27 @@ int link_new(Manager *m, Link **ret, int ifindex) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
Link *link_free(Link *l) {
|
||||
if (!l)
|
||||
return NULL;
|
||||
void link_flush_settings(Link *l) {
|
||||
assert(l);
|
||||
|
||||
l->llmnr_support = RESOLVE_SUPPORT_YES;
|
||||
l->mdns_support = RESOLVE_SUPPORT_NO;
|
||||
l->dnssec_mode = _DNSSEC_MODE_INVALID;
|
||||
|
||||
dns_server_unlink_all(l->dns_servers);
|
||||
dns_search_domain_unlink_all(l->search_domains);
|
||||
|
||||
l->dnssec_negative_trust_anchors = set_free_free(l->dnssec_negative_trust_anchors);
|
||||
}
|
||||
|
||||
Link *link_free(Link *l) {
|
||||
if (!l)
|
||||
return NULL;
|
||||
|
||||
link_flush_settings(l);
|
||||
|
||||
while (l->addresses)
|
||||
link_address_free(l->addresses);
|
||||
(void) link_address_free(l->addresses);
|
||||
|
||||
if (l->manager)
|
||||
hashmap_remove(l->manager->links, INT_TO_PTR(l->ifindex));
|
||||
@ -82,18 +94,17 @@ Link *link_free(Link *l) {
|
||||
dns_scope_free(l->mdns_ipv4_scope);
|
||||
dns_scope_free(l->mdns_ipv6_scope);
|
||||
|
||||
set_free_free(l->dnssec_negative_trust_anchors);
|
||||
|
||||
free(l);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static void link_allocate_scopes(Link *l) {
|
||||
void link_allocate_scopes(Link *l) {
|
||||
int r;
|
||||
|
||||
assert(l);
|
||||
|
||||
if (l->dns_servers) {
|
||||
if (link_relevant(l, AF_UNSPEC, false) &&
|
||||
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)
|
||||
@ -102,7 +113,7 @@ static void link_allocate_scopes(Link *l) {
|
||||
} else
|
||||
l->unicast_scope = dns_scope_free(l->unicast_scope);
|
||||
|
||||
if (link_relevant(l, AF_INET) &&
|
||||
if (link_relevant(l, AF_INET, true) &&
|
||||
l->llmnr_support != RESOLVE_SUPPORT_NO &&
|
||||
l->manager->llmnr_support != RESOLVE_SUPPORT_NO) {
|
||||
if (!l->llmnr_ipv4_scope) {
|
||||
@ -113,7 +124,7 @@ static void link_allocate_scopes(Link *l) {
|
||||
} else
|
||||
l->llmnr_ipv4_scope = dns_scope_free(l->llmnr_ipv4_scope);
|
||||
|
||||
if (link_relevant(l, AF_INET6) &&
|
||||
if (link_relevant(l, AF_INET6, true) &&
|
||||
l->llmnr_support != RESOLVE_SUPPORT_NO &&
|
||||
l->manager->llmnr_support != RESOLVE_SUPPORT_NO &&
|
||||
socket_ipv6_is_supported()) {
|
||||
@ -125,7 +136,7 @@ static void link_allocate_scopes(Link *l) {
|
||||
} else
|
||||
l->llmnr_ipv6_scope = dns_scope_free(l->llmnr_ipv6_scope);
|
||||
|
||||
if (link_relevant(l, AF_INET) &&
|
||||
if (link_relevant(l, AF_INET, true) &&
|
||||
l->mdns_support != RESOLVE_SUPPORT_NO &&
|
||||
l->manager->mdns_support != RESOLVE_SUPPORT_NO) {
|
||||
if (!l->mdns_ipv4_scope) {
|
||||
@ -136,7 +147,7 @@ static void link_allocate_scopes(Link *l) {
|
||||
} else
|
||||
l->mdns_ipv4_scope = dns_scope_free(l->mdns_ipv4_scope);
|
||||
|
||||
if (link_relevant(l, AF_INET6) &&
|
||||
if (link_relevant(l, AF_INET6, true) &&
|
||||
l->mdns_support != RESOLVE_SUPPORT_NO &&
|
||||
l->manager->mdns_support != RESOLVE_SUPPORT_NO) {
|
||||
if (!l->mdns_ipv6_scope) {
|
||||
@ -277,6 +288,26 @@ clear:
|
||||
return r;
|
||||
}
|
||||
|
||||
void link_set_dnssec_mode(Link *l, DnssecMode mode) {
|
||||
|
||||
assert(l);
|
||||
|
||||
if (l->dnssec_mode == mode)
|
||||
return;
|
||||
|
||||
if ((l->dnssec_mode == _DNSSEC_MODE_INVALID) ||
|
||||
(l->dnssec_mode == DNSSEC_NO && mode != DNSSEC_NO) ||
|
||||
(l->dnssec_mode == DNSSEC_ALLOW_DOWNGRADE && mode == DNSSEC_YES)) {
|
||||
|
||||
/* When switching from non-DNSSEC mode to DNSSEC mode, flush the cache. Also when switching from the
|
||||
* allow-downgrade mode to full DNSSEC mode, flush it too. */
|
||||
if (l->unicast_scope)
|
||||
dns_cache_flush(&l->unicast_scope->cache);
|
||||
}
|
||||
|
||||
l->dnssec_mode = mode;
|
||||
}
|
||||
|
||||
static int link_update_dnssec_mode(Link *l) {
|
||||
_cleanup_free_ char *m = NULL;
|
||||
DnssecMode mode;
|
||||
@ -298,16 +329,7 @@ static int link_update_dnssec_mode(Link *l) {
|
||||
goto clear;
|
||||
}
|
||||
|
||||
if ((l->dnssec_mode == DNSSEC_NO && mode != DNSSEC_NO) ||
|
||||
(l->dnssec_mode == DNSSEC_ALLOW_DOWNGRADE && mode == DNSSEC_YES)) {
|
||||
|
||||
/* When switching from non-DNSSEC mode to DNSSEC mode, flush the cache. Also when switching from the
|
||||
* allow-downgrade mode to full DNSSEC mode, flush it too. */
|
||||
if (l->unicast_scope)
|
||||
dns_cache_flush(&l->unicast_scope->cache);
|
||||
}
|
||||
|
||||
l->dnssec_mode = mode;
|
||||
link_set_dnssec_mode(l, mode);
|
||||
|
||||
return 0;
|
||||
|
||||
@ -395,11 +417,45 @@ clear:
|
||||
return r;
|
||||
}
|
||||
|
||||
int link_update_monitor(Link *l) {
|
||||
static int link_is_unmanaged(Link *l) {
|
||||
_cleanup_free_ char *state = NULL;
|
||||
int r;
|
||||
|
||||
assert(l);
|
||||
|
||||
r = sd_network_link_get_setup_state(l->ifindex, &state);
|
||||
if (r == -ENODATA)
|
||||
return 1;
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
||||
return STR_IN_SET(state, "pending", "unmanaged");
|
||||
}
|
||||
|
||||
static void link_read_settings(Link *l) {
|
||||
int r;
|
||||
|
||||
assert(l);
|
||||
|
||||
/* Read settings from networkd, except when networkd is not managing this interface. */
|
||||
|
||||
r = link_is_unmanaged(l);
|
||||
if (r < 0) {
|
||||
log_warning_errno(r, "Failed to determine whether interface %s is managed: %m", l->name);
|
||||
return;
|
||||
}
|
||||
if (r > 0) {
|
||||
|
||||
/* If this link used to be managed, but is now unmanaged, flush all our settings -- but only once. */
|
||||
if (l->is_managed)
|
||||
link_flush_settings(l);
|
||||
|
||||
l->is_managed = false;
|
||||
return;
|
||||
}
|
||||
|
||||
l->is_managed = true;
|
||||
|
||||
r = link_update_dns_servers(l);
|
||||
if (r < 0)
|
||||
log_warning_errno(r, "Failed to read DNS servers for interface %s, ignoring: %m", l->name);
|
||||
@ -423,35 +479,47 @@ int link_update_monitor(Link *l) {
|
||||
r = link_update_search_domains(l);
|
||||
if (r < 0)
|
||||
log_warning_errno(r, "Failed to read search domains for interface %s, ignoring: %m", l->name);
|
||||
}
|
||||
|
||||
int link_update_monitor(Link *l) {
|
||||
assert(l);
|
||||
|
||||
link_read_settings(l);
|
||||
link_allocate_scopes(l);
|
||||
link_add_rrs(l, false);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
bool link_relevant(Link *l, int family) {
|
||||
bool link_relevant(Link *l, int family, bool multicast) {
|
||||
_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 */
|
||||
/* A link is relevant for multicast traffic 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))
|
||||
if (l->flags & (IFF_LOOPBACK|IFF_DORMANT))
|
||||
return false;
|
||||
|
||||
if ((l->flags & (IFF_UP|IFF_LOWER_UP|IFF_MULTICAST)) != (IFF_UP|IFF_LOWER_UP|IFF_MULTICAST))
|
||||
if ((l->flags & (IFF_UP|IFF_LOWER_UP)) != (IFF_UP|IFF_LOWER_UP))
|
||||
return false;
|
||||
|
||||
if (multicast) {
|
||||
if (l->flags & IFF_POINTOPOINT)
|
||||
return false;
|
||||
|
||||
if ((l->flags & IFF_MULTICAST) != 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))
|
||||
if ((family == AF_UNSPEC || a->family == family) && link_address_relevant(a))
|
||||
return true;
|
||||
|
||||
return false;
|
||||
@ -512,6 +580,30 @@ void link_next_dns_server(Link *l) {
|
||||
link_set_dns_server(l, l->dns_servers);
|
||||
}
|
||||
|
||||
DnssecMode link_get_dnssec_mode(Link *l) {
|
||||
assert(l);
|
||||
|
||||
if (l->dnssec_mode != _DNSSEC_MODE_INVALID)
|
||||
return l->dnssec_mode;
|
||||
|
||||
return manager_get_dnssec_mode(l->manager);
|
||||
}
|
||||
|
||||
bool link_dnssec_supported(Link *l) {
|
||||
DnsServer *server;
|
||||
|
||||
assert(l);
|
||||
|
||||
if (link_get_dnssec_mode(l) == DNSSEC_NO)
|
||||
return false;
|
||||
|
||||
server = link_get_dns_server(l);
|
||||
if (server)
|
||||
return dns_server_dnssec_supported(server);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
int link_address_new(Link *l, LinkAddress **ret, int family, const union in_addr_union *in_addr) {
|
||||
LinkAddress *a;
|
||||
|
||||
|
@ -78,6 +78,8 @@ struct Link {
|
||||
DnsScope *mdns_ipv4_scope;
|
||||
DnsScope *mdns_ipv6_scope;
|
||||
|
||||
bool is_managed;
|
||||
|
||||
char name[IF_NAMESIZE];
|
||||
uint32_t mtu;
|
||||
};
|
||||
@ -86,14 +88,21 @@ int link_new(Manager *m, Link **ret, int ifindex);
|
||||
Link *link_free(Link *l);
|
||||
int link_update_rtnl(Link *l, sd_netlink_message *m);
|
||||
int link_update_monitor(Link *l);
|
||||
bool link_relevant(Link *l, int family);
|
||||
bool link_relevant(Link *l, int family, bool multicast);
|
||||
LinkAddress* link_find_address(Link *l, int family, const union in_addr_union *in_addr);
|
||||
void link_add_rrs(Link *l, bool force_remove);
|
||||
|
||||
void link_flush_settings(Link *l);
|
||||
void link_set_dnssec_mode(Link *l, DnssecMode mode);
|
||||
void link_allocate_scopes(Link *l);
|
||||
|
||||
DnsServer* link_set_dns_server(Link *l, DnsServer *s);
|
||||
DnsServer* link_get_dns_server(Link *l);
|
||||
void link_next_dns_server(Link *l);
|
||||
|
||||
DnssecMode link_get_dnssec_mode(Link *l);
|
||||
bool link_dnssec_supported(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_netlink_message *m);
|
||||
|
@ -1173,3 +1173,33 @@ int manager_compile_search_domains(Manager *m, OrderedSet **domains) {
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
DnssecMode manager_get_dnssec_mode(Manager *m) {
|
||||
assert(m);
|
||||
|
||||
if (m->dnssec_mode != _DNSSEC_MODE_INVALID)
|
||||
return m->dnssec_mode;
|
||||
|
||||
return DNSSEC_NO;
|
||||
}
|
||||
|
||||
bool manager_dnssec_supported(Manager *m) {
|
||||
DnsServer *server;
|
||||
Iterator i;
|
||||
Link *l;
|
||||
|
||||
assert(m);
|
||||
|
||||
if (manager_get_dnssec_mode(m) == DNSSEC_NO)
|
||||
return false;
|
||||
|
||||
server = manager_get_dns_server(m);
|
||||
if (server && !dns_server_dnssec_supported(server))
|
||||
return false;
|
||||
|
||||
HASHMAP_FOREACH(l, m->links, i)
|
||||
if (!link_dnssec_supported(l))
|
||||
return false;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
@ -158,3 +158,6 @@ int manager_is_own_hostname(Manager *m, const char *name);
|
||||
|
||||
int manager_compile_dns_servers(Manager *m, OrderedSet **servers);
|
||||
int manager_compile_search_domains(Manager *m, OrderedSet **domains);
|
||||
|
||||
DnssecMode manager_get_dnssec_mode(Manager *m);
|
||||
bool manager_dnssec_supported(Manager *m);
|
||||
|
@ -44,9 +44,9 @@ typedef int (*sd_resolve_getaddrinfo_handler_t)(sd_resolve_query *q, int ret, co
|
||||
typedef int (*sd_resolve_getnameinfo_handler_t)(sd_resolve_query *q, int ret, const char *host, const char *serv, void *userdata);
|
||||
|
||||
enum {
|
||||
SD_RESOLVE_GET_HOST = 1ULL,
|
||||
SD_RESOLVE_GET_SERVICE = 2ULL,
|
||||
SD_RESOLVE_GET_BOTH = 3ULL
|
||||
SD_RESOLVE_GET_HOST = UINT64_C(1),
|
||||
SD_RESOLVE_GET_SERVICE = UINT64_C(2),
|
||||
SD_RESOLVE_GET_BOTH = UINT64_C(3),
|
||||
};
|
||||
|
||||
int sd_resolve_default(sd_resolve **ret);
|
||||
|
Loading…
x
Reference in New Issue
Block a user