resolved-manager.c revision eb60f9cd4e93ff5016dc1b5486fd1b7e1565fd92
bd3fa1d2434aa28564251ac4da34d01537de8c4bLennart Poettering/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
bd3fa1d2434aa28564251ac4da34d01537de8c4bLennart Poettering This file is part of systemd.
bd3fa1d2434aa28564251ac4da34d01537de8c4bLennart Poettering Copyright 2014 Tom Gundersen <teg@jklm.no>
bd3fa1d2434aa28564251ac4da34d01537de8c4bLennart Poettering systemd is free software; you can redistribute it and/or modify it
bd3fa1d2434aa28564251ac4da34d01537de8c4bLennart Poettering under the terms of the GNU Lesser General Public License as published by
bd3fa1d2434aa28564251ac4da34d01537de8c4bLennart Poettering the Free Software Foundation; either version 2.1 of the License, or
bd3fa1d2434aa28564251ac4da34d01537de8c4bLennart Poettering (at your option) any later version.
bd3fa1d2434aa28564251ac4da34d01537de8c4bLennart Poettering systemd is distributed in the hope that it will be useful, but
bd3fa1d2434aa28564251ac4da34d01537de8c4bLennart Poettering WITHOUT ANY WARRANTY; without even the implied warranty of
bd3fa1d2434aa28564251ac4da34d01537de8c4bLennart Poettering MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
bd3fa1d2434aa28564251ac4da34d01537de8c4bLennart Poettering Lesser General Public License for more details.
bd3fa1d2434aa28564251ac4da34d01537de8c4bLennart Poettering You should have received a copy of the GNU Lesser General Public License
bd3fa1d2434aa28564251ac4da34d01537de8c4bLennart Poettering along with systemd; If not, see <http://www.gnu.org/licenses/>.
bd3fa1d2434aa28564251ac4da34d01537de8c4bLennart Poettering#define SEND_TIMEOUT_USEC (200 * USEC_PER_MSEC)
bd3fa1d2434aa28564251ac4da34d01537de8c4bLennart Poetteringstatic int manager_process_link(sd_rtnl *rtnl, sd_rtnl_message *mm, void *userdata) {
bd3fa1d2434aa28564251ac4da34d01537de8c4bLennart Poettering r = sd_rtnl_message_link_get_ifindex(mm, &ifindex);
bd3fa1d2434aa28564251ac4da34d01537de8c4bLennart Poettering l = hashmap_get(m->links, INT_TO_PTR(ifindex));
aaf7eb81be912e7bed939f31e3bc4c631b2552b3Lennart Poettering log_debug("Found new link %i/%s", ifindex, l->name);
bd3fa1d2434aa28564251ac4da34d01537de8c4bLennart Poettering log_debug("Removing link %i/%s", l->ifindex, l->name);
bd3fa1d2434aa28564251ac4da34d01537de8c4bLennart Poettering log_warning("Failed to process RTNL link message: %s", strerror(-r));
aaf7eb81be912e7bed939f31e3bc4c631b2552b3Lennart Poetteringstatic int manager_process_address(sd_rtnl *rtnl, sd_rtnl_message *mm, void *userdata) {
aaf7eb81be912e7bed939f31e3bc4c631b2552b3Lennart Poettering r = sd_rtnl_message_addr_get_ifindex(mm, &ifindex);
aaf7eb81be912e7bed939f31e3bc4c631b2552b3Lennart Poettering l = hashmap_get(m->links, INT_TO_PTR(ifindex));
bd3fa1d2434aa28564251ac4da34d01537de8c4bLennart Poettering r = sd_rtnl_message_addr_get_family(mm, &family);
bd3fa1d2434aa28564251ac4da34d01537de8c4bLennart Poettering r = sd_rtnl_message_read_in_addr(mm, IFA_LOCAL, &address.in);
bd3fa1d2434aa28564251ac4da34d01537de8c4bLennart Poettering r = sd_rtnl_message_read_in_addr(mm, IFA_ADDRESS, &address.in);
bd3fa1d2434aa28564251ac4da34d01537de8c4bLennart Poettering r = sd_rtnl_message_read_in6_addr(mm, IFA_LOCAL, &address.in6);
bd3fa1d2434aa28564251ac4da34d01537de8c4bLennart Poettering r = sd_rtnl_message_read_in6_addr(mm, IFA_ADDRESS, &address.in6);
bd3fa1d2434aa28564251ac4da34d01537de8c4bLennart Poettering a = link_find_address(l, family, &address);
bd3fa1d2434aa28564251ac4da34d01537de8c4bLennart Poettering r = link_address_new(l, &a, family, &address);
bd3fa1d2434aa28564251ac4da34d01537de8c4bLennart Poettering log_warning("Failed to process RTNL address message: %s", strerror(-r));
3d141780b8d509e4a6c3083de207cd84cbce187bLennart Poetteringstatic int manager_rtnl_listen(Manager *m) {
bd3fa1d2434aa28564251ac4da34d01537de8c4bLennart Poettering _cleanup_rtnl_message_unref_ sd_rtnl_message *req = NULL, *reply = NULL;
bd3fa1d2434aa28564251ac4da34d01537de8c4bLennart Poettering /* First, subscibe to interfaces coming and going */
bd3fa1d2434aa28564251ac4da34d01537de8c4bLennart Poettering r = sd_rtnl_open(&m->rtnl, 3, RTNLGRP_LINK, RTNLGRP_IPV4_IFADDR, RTNLGRP_IPV6_IFADDR);
bd3fa1d2434aa28564251ac4da34d01537de8c4bLennart Poettering r = sd_rtnl_attach_event(m->rtnl, m->event, 0);
bd3fa1d2434aa28564251ac4da34d01537de8c4bLennart Poettering r = sd_rtnl_add_match(m->rtnl, RTM_NEWLINK, manager_process_link, m);
aaf7eb81be912e7bed939f31e3bc4c631b2552b3Lennart Poettering r = sd_rtnl_add_match(m->rtnl, RTM_DELLINK, manager_process_link, m);
aaf7eb81be912e7bed939f31e3bc4c631b2552b3Lennart Poettering r = sd_rtnl_add_match(m->rtnl, RTM_NEWADDR, manager_process_address, m);
Iterator i;
Link *l;
assert(m);
r = link_update_monitor(l);
r = manager_write_resolv_conf(m);
assert(m);
if (fd < 0)
return fd;
if (events < 0)
return events;
assert(m);
int family;
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) {
assert(m);
while (m->dns_servers)
assert(m);
h = gethostname_malloc();
return log_oom();
if (!utf8_is_valid(h)) {
return -EINVAL;
r = dns_name_normalize(h, &n);
*ret = n;
n = NULL;
assert(m);
r = determine_hostname(&h);
m->hostname = h;
h = NULL;
assert(m);
if (m->hostname_fd < 0) {
if (r == -EPERM)
if (!m->hostname)
return log_oom();
return -ENOMEM;
m->use_llmnr = true;
r = manager_watch_hostname(m);
r = manager_network_monitor_listen(m);
r = manager_rtnl_listen(m);
r = manager_connect_bus(m);
r = manager_llmnr_ipv4_udp_fd(m);
r = manager_llmnr_ipv6_udp_fd(m);
r = manager_llmnr_ipv4_tcp_fd(m);
r = manager_llmnr_ipv6_tcp_fd(m);
*ret = m;
m = NULL;
Link *l;
return NULL;
while (m->dns_queries)
link_free(l);
while (m->dns_servers)
free(m);
return NULL;
assert(s);
assert(f);
(*count) ++;
unsigned count = 0;
DnsServer *s;
Iterator i;
Link *l;
assert(m);
"# only through the symlink at /etc/resolv.conf. To manage\n"
"# resolv.conf(5) in a different way, replace the symlink by a\n"
r = fflush_and_check(f);
goto fail;
r = -errno;
goto fail;
fail:
} control;
int ms = 0, r;
ssize_t l;
assert(m);
return -errno;
if (ms < 0)
return -EIO;
return -errno;
return -EIO;
return -EAFNOSUPPORT;
case IPV6_PKTINFO: {
if (p->ifindex <= 0)
case IPV6_HOPLIMIT:
case IP_PKTINFO: {
if (p->ifindex <= 0)
case IP_TTL:
p->ifindex = 0;
if (p->ifindex <= 0)
*ret = p;
p = NULL;
if (dns_packet_validate_reply(p) > 0) {
assert(m);
if (m->dns_ipv4_fd >= 0)
return m->dns_ipv4_fd;
if (m->dns_ipv4_fd < 0)
return -errno;
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);
goto fail;
return m->dns_ipv4_fd;
fail:
assert(m);
if (m->dns_ipv6_fd >= 0)
return m->dns_ipv6_fd;
if (m->dns_ipv6_fd < 0)
return -errno;
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);
goto fail;
return m->dns_ipv6_fd;
fail:
return -errno;
return -ETIMEDOUT;
static int manager_ipv4_send(Manager *m, int fd, int ifindex, const struct in_addr *addr, uint16_t port, DnsPacket *p) {
} control;
assert(m);
assert(p);
if (ifindex > 0) {
static int manager_ipv6_send(Manager *m, int fd, int ifindex, const struct in6_addr *addr, uint16_t port, DnsPacket *p) {
} control;
assert(m);
assert(p);
if (ifindex > 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(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));
return -EAFNOSUPPORT;
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)
Link *l;
Iterator i;
if (l->mtu <= 0)
return mtu;
if (dns_packet_validate_reply(p) > 0) {
} else if (dns_packet_validate_query(p) > 0) {
Link *l;
if (scope)
assert(m);
if (m->llmnr_ipv4_udp_fd >= 0)
return m->llmnr_ipv4_udp_fd;
if (m->llmnr_ipv4_udp_fd < 0)
return -errno;
r = -errno;
goto fail;
r = -errno;
goto fail;
r = -errno;
goto fail;
r = -errno;
goto fail;
r = -errno;
goto fail;
r = -errno;
goto fail;
r = -errno;
goto fail;
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);
goto fail;
return m->llmnr_ipv4_udp_fd;
fail:
assert(m);
if (m->llmnr_ipv6_udp_fd >= 0)
return m->llmnr_ipv6_udp_fd;
if (m->llmnr_ipv6_udp_fd < 0)
return -errno;
r = -errno;
goto fail;
r = -errno;
goto fail;
r = -errno;
goto fail;
r = -errno;
goto fail;
r = -errno;
goto fail;
r = -errno;
goto fail;
r = -errno;
goto fail;
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);
r = -errno;
goto fail;
return m->llmnr_ipv6_udp_fd;
fail:
assert(s);
Link *l;
if (scope) {
if (s->write_packet)
dns_stream_free(s);
int cfd, r;
if (cfd < 0) {
return -errno;
assert(m);
if (m->llmnr_ipv4_tcp_fd >= 0)
return m->llmnr_ipv4_tcp_fd;
if (m->llmnr_ipv4_tcp_fd < 0)
return -errno;
r = -errno;
goto fail;
r = -errno;
goto fail;
r = -errno;
goto fail;
r = -errno;
goto fail;
r = -errno;
goto fail;
r = -errno;
goto fail;
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);
goto fail;
return m->llmnr_ipv4_tcp_fd;
fail:
assert(m);
if (m->llmnr_ipv6_tcp_fd >= 0)
return m->llmnr_ipv6_tcp_fd;
if (m->llmnr_ipv6_tcp_fd < 0)
return -errno;
r = -errno;
goto fail;
r = -errno;
goto fail;
r = -errno;
goto fail;
r = -errno;
goto fail;
r = -errno;
goto fail;
r = -errno;
goto fail;
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);
r = -errno;
goto fail;
return m->llmnr_ipv6_tcp_fd;
fail:
Link *l;
assert(m);
if (ifindex <= 0)
return -EINVAL;
LinkAddress *a;
assert(m);
Iterator i;
Link *l;
assert(m);
link_add_rrs(l, true);
link_add_rrs(l, false);
uint64_t u;
assert(m);
assert(p);
while (p > m->hostname) {
if (*p == 0 || safe_atou64(p, &u) < 0 || u <= 0)
return -ENOMEM;
m->hostname = h;
Iterator i;
Link *l;
assert(m);
LinkAddress *a;
return NULL;
assert(m);
assert(p);