resolved-manager.c revision ad867662936a4c7ab2c7116d804c272338801231
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering This file is part of systemd.
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering Copyright 2014 Tom Gundersen <teg@jklm.no>
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering systemd is free software; you can redistribute it and/or modify it
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering under the terms of the GNU Lesser General Public License as published by
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering the Free Software Foundation; either version 2.1 of the License, or
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering (at your option) any later version.
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering systemd is distributed in the hope that it will be useful, but
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering WITHOUT ANY WARRANTY; without even the implied warranty of
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering Lesser General Public License for more details.
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering You should have received a copy of the GNU Lesser General Public License
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering along with systemd; If not, see <http://www.gnu.org/licenses/>.
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering#define SEND_TIMEOUT_USEC (200 * USEC_PER_MSEC)
875c2e220e2611165e09051c4747971811f1de58Lennart Poetteringstatic int manager_process_link(sd_rtnl *rtnl, sd_rtnl_message *mm, void *userdata) {
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering r = sd_rtnl_message_link_get_ifindex(mm, &ifindex);
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering l = hashmap_get(m->links, INT_TO_PTR(ifindex));
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering log_debug("Removing link %i", l->ifindex);
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering log_warning("Failed to process RTNL link message: %s", strerror(-r));
875c2e220e2611165e09051c4747971811f1de58Lennart Poetteringstatic int manager_process_address(sd_rtnl *rtnl, sd_rtnl_message *mm, void *userdata) {
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering unsigned char family;
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering r = sd_rtnl_message_addr_get_ifindex(mm, &ifindex);
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering l = hashmap_get(m->links, INT_TO_PTR(ifindex));
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering r = sd_rtnl_message_addr_get_family(mm, &family);
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering r = sd_rtnl_message_read_in_addr(mm, IFA_LOCAL, &address.in);
78fe420ff0bb4cd94de3c4d3f15a3021cc3e2878Lennart Poettering r = sd_rtnl_message_read_in_addr(mm, IFA_ADDRESS, &address.in);
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering r = sd_rtnl_message_read_in6_addr(mm, IFA_LOCAL, &address.in6);
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering r = sd_rtnl_message_read_in6_addr(mm, IFA_ADDRESS, &address.in6);
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering a = link_find_address(l, family, &address);
78fe420ff0bb4cd94de3c4d3f15a3021cc3e2878Lennart Poettering r = link_address_new(l, &a, family, &address);
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering log_warning("Failed to process RTNL address message: %s", strerror(-r));
9833a66c7eba011c3740867c80133bc6fa976aa3Lennart Poetteringstatic int manager_rtnl_listen(Manager *m) {
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering _cleanup_rtnl_message_unref_ sd_rtnl_message *req = NULL, *reply = NULL;
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering /* First, subscibe to interfaces coming and going */
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering r = sd_rtnl_open(&m->rtnl, 3, RTNLGRP_LINK, RTNLGRP_IPV4_IFADDR, RTNLGRP_IPV6_IFADDR);
9833a66c7eba011c3740867c80133bc6fa976aa3Lennart Poettering r = sd_rtnl_attach_event(m->rtnl, m->event, 0);
9833a66c7eba011c3740867c80133bc6fa976aa3Lennart Poettering r = sd_rtnl_add_match(m->rtnl, RTM_NEWLINK, manager_process_link, m);
9833a66c7eba011c3740867c80133bc6fa976aa3Lennart Poettering r = sd_rtnl_add_match(m->rtnl, RTM_DELLINK, manager_process_link, m);
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering r = sd_rtnl_add_match(m->rtnl, RTM_NEWADDR, manager_process_address, m);
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering r = sd_rtnl_add_match(m->rtnl, RTM_DELADDR, manager_process_address, m);
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering /* Then, enumerate all links */
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering r = sd_rtnl_message_new_link(m->rtnl, &req, RTM_GETLINK, 0);
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering r = sd_rtnl_message_request_dump(req, true);
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering r = sd_rtnl_call(m->rtnl, req, 0, &reply);
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering for (i = reply; i; i = sd_rtnl_message_next(i)) {
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering /* Finally, enumerate all addresses, too */
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering r = sd_rtnl_message_new_addr(m->rtnl, &req, RTM_GETADDR, 0, AF_UNSPEC);
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering r = sd_rtnl_message_request_dump(req, true);
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering r = sd_rtnl_call(m->rtnl, req, 0, &reply);
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering for (i = reply; i; i = sd_rtnl_message_next(i)) {
875c2e220e2611165e09051c4747971811f1de58Lennart Poetteringstatic int on_network_event(sd_event_source *s, int fd, uint32_t revents, void *userdata) {
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering sd_network_monitor_flush(m->network_monitor);
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering log_warning("Failed to update monitor information for %i: %s", l->ifindex, strerror(-r));
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering log_warning("Could not update resolv.conf: %s", strerror(-r));
875c2e220e2611165e09051c4747971811f1de58Lennart Poetteringstatic int manager_network_monitor_listen(Manager *m) {
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering r = sd_network_monitor_new(NULL, &m->network_monitor);
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering fd = sd_network_monitor_get_fd(m->network_monitor);
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering events = sd_network_monitor_get_events(m->network_monitor);
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering r = sd_event_add_io(m->event, &m->network_event_source, fd, events, &on_network_event, m);
875c2e220e2611165e09051c4747971811f1de58Lennart Poetteringstatic int parse_dns_server_string(Manager *m, const char *string) {
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering FOREACH_WORD_QUOTED(word, length, string, state) {
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering r = in_addr_from_string_auto(buffer, &family, &addr);
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering log_warning("Ignoring invalid DNS address '%s'", buffer);
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering /* filter out duplicates */
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering if (manager_find_dns_server(m, family, &addr))
23bbb0de4e3f85d9704a5c12a5afa2dfa0159e41Michal Schmidt r = dns_server_new(m, NULL, DNS_SERVER_SYSTEM, NULL, family, &addr);
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering /* Empty assignment means clear the list */
1fa2f38f0f011010bf57522b42fcc168856a7003Zbigniew Jędrzejewski-Szmek log_error("Failed to parse DNS server string");
875c2e220e2611165e09051c4747971811f1de58Lennart Poetteringint manager_parse_config_file(Manager *m) {
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering r = config_parse(NULL, "/etc/systemd/resolved.conf", NULL,
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering config_item_perf_lookup, resolved_gperf_lookup,
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering false, false, m);
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering log_warning("Failed to parse configuration file: %s", strerror(-r));
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering _cleanup_(manager_freep) Manager *m = NULL;
cd556b6ca8aec8dd371806afedec45f852f8f724Zbigniew Jędrzejewski-Szmek m->dns_ipv4_fd = m->dns_ipv6_fd = -1;
cd556b6ca8aec8dd371806afedec45f852f8f724Zbigniew Jędrzejewski-Szmek r = parse_dns_server_string(m, /* "172.31.0.125 2001:4860:4860::8888 2001:4860:4860::8889" */ DNS_SERVERS);
8bb3626dac93c0157989fb87afe0212958d7dbb4Zbigniew Jędrzejewski-Szmek r = sd_event_default(&m->event);
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering sd_event_add_signal(m->event, NULL, SIGTERM, NULL, NULL);
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering sd_event_add_signal(m->event, NULL, SIGINT, NULL, NULL);
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering r = dns_scope_new(m, &m->unicast_scope, DNS_SCOPE_DNS);
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering sd_event_source_unref(m->network_event_source);
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering sd_network_monitor_unref(m->network_monitor);
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering sd_event_source_unref(m->dns_ipv4_event_source);
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering sd_event_source_unref(m->dns_ipv6_event_source);
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering sd_event_source_unref(m->bus_retry_event_source);
4d9ced9956755901238fede6fc5a3d7e4e816aa6Lennart Poetteringstatic void write_resolve_conf_server(DnsServer *s, FILE *f, unsigned *count) {
4d9ced9956755901238fede6fc5a3d7e4e816aa6Lennart Poettering r = in_addr_to_string(s->family, &s->address, &t);
4d9ced9956755901238fede6fc5a3d7e4e816aa6Lennart Poettering log_warning("Invalid DNS address. Ignoring.");
4d9ced9956755901238fede6fc5a3d7e4e816aa6Lennart Poettering fputs("# Too many DNS servers configured, the following entries may be ignored\n", f);
4d9ced9956755901238fede6fc5a3d7e4e816aa6Lennart Poetteringint manager_write_resolv_conf(Manager *m) {
4d9ced9956755901238fede6fc5a3d7e4e816aa6Lennart Poettering const char *path = "/run/systemd/resolve/resolv.conf";
4d9ced9956755901238fede6fc5a3d7e4e816aa6Lennart Poettering r = fopen_temporary(path, &f, &temp_path);
4d9ced9956755901238fede6fc5a3d7e4e816aa6Lennart Poettering fputs("# This file is managed by systemd-resolved(8). Do not edit.\n#\n"
4d9ced9956755901238fede6fc5a3d7e4e816aa6Lennart Poettering "# Third party programs must not access this file directly, but\n"
4d9ced9956755901238fede6fc5a3d7e4e816aa6Lennart Poettering "# only through the symlink at /etc/resolv.conf. To manage\n"
4d9ced9956755901238fede6fc5a3d7e4e816aa6Lennart Poettering "# resolv.conf(5) in a different way, replace the symlink by a\n"
4d9ced9956755901238fede6fc5a3d7e4e816aa6Lennart Poettering "# static file or a different symlink.\n\n", f);
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering LIST_FOREACH(servers, s, l->link_dns_servers)
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering LIST_FOREACH(servers, s, l->dhcp_dns_servers)
417a7fdc418ec76cc4c321c9a07ec15c72b3ac7dLennart Poetteringint manager_dns_ipv4_recv(Manager *m, DnsPacket **ret) {
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering _cleanup_(dns_packet_unrefp) DnsPacket *p = NULL;
return -errno;
return -EIO;
*ret = p;
p = NULL;
ssize_t l;
assert(m);
if (fd < 0)
return fd;
return -errno;
if (ms < 0)
return -EIO;
return -errno;
return -EIO;
*ret = p;
p = NULL;
r = manager_dns_ipv4_recv(m, &p);
dns_query_transaction_reply(t, p);
r = manager_dns_ipv6_recv(m, &p);
dns_query_transaction_reply(t, p);
assert(m);
if (m->dns_ipv4_fd >= 0)
return m->dns_ipv4_fd;
if (m->dns_ipv4_fd < 0)
return -errno;
r = sd_event_add_io(m->event, &m->dns_ipv4_event_source, m->dns_ipv4_fd, EPOLLIN, on_dns_ipv4_packet, m);
return m->dns_ipv4_fd;
assert(m);
if (m->dns_ipv6_fd >= 0)
return m->dns_ipv6_fd;
if (m->dns_ipv6_fd < 0)
return -errno;
r = sd_event_add_io(m->event, &m->dns_ipv6_event_source, m->dns_ipv6_fd, EPOLLIN, on_dns_ipv6_packet, m);
return m->dns_ipv6_fd;
return -errno;
return -ETIMEDOUT;
int fd;
assert(m);
assert(p);
if (fd < 0)
return fd;
if (ifindex > 0) {
int fd;
assert(m);
assert(p);
if (fd < 0)
return fd;
if (ifindex > 0) {
DnsServer* manager_find_dns_server(Manager *m, unsigned char family, union in_addr_union *in_addr) {
DnsServer *s;
assert(m);
return NULL;
assert(m);
if (!m->current_dns_server)
return m->current_dns_server;
assert(m);
if (!m->current_dns_server) {
if (!m->current_dns_server)