resolved-manager.c revision 36a03ca2a8952ca1acb29fbe796210c27ff71aff
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poettering/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poettering This file is part of systemd.
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poettering Copyright 2014 Tom Gundersen <teg@jklm.no>
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poettering systemd is free software; you can redistribute it and/or modify it
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poettering under the terms of the GNU Lesser General Public License as published by
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poettering the Free Software Foundation; either version 2.1 of the License, or
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poettering (at your option) any later version.
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poettering systemd is distributed in the hope that it will be useful, but
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poettering WITHOUT ANY WARRANTY; without even the implied warranty of
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poettering MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poettering Lesser General Public License for more details.
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poettering You should have received a copy of the GNU Lesser General Public License
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poettering along with systemd; If not, see <http://www.gnu.org/licenses/>.
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poettering#define SEND_TIMEOUT_USEC (200 * USEC_PER_MSEC)
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poetteringstatic int manager_process_link(sd_rtnl *rtnl, sd_rtnl_message *mm, void *userdata) {
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poettering r = sd_rtnl_message_link_get_ifindex(mm, &ifindex);
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poettering l = hashmap_get(m->links, INT_TO_PTR(ifindex));
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poettering log_debug("Found new link %i/%s", ifindex, l->name);
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poettering log_debug("Removing link %i/%s", l->ifindex, l->name);
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poettering log_warning_errno(r, "Failed to process RTNL link message: %m");
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poetteringstatic int manager_process_address(sd_rtnl *rtnl, sd_rtnl_message *mm, void *userdata) {
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poettering r = sd_rtnl_message_addr_get_ifindex(mm, &ifindex);
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poettering l = hashmap_get(m->links, INT_TO_PTR(ifindex));
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poettering r = sd_rtnl_message_addr_get_family(mm, &family);
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poettering r = sd_rtnl_message_read_in_addr(mm, IFA_LOCAL, &address.in);
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poettering r = sd_rtnl_message_read_in_addr(mm, IFA_ADDRESS, &address.in);
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poettering r = sd_rtnl_message_read_in6_addr(mm, IFA_LOCAL, &address.in6);
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poettering r = sd_rtnl_message_read_in6_addr(mm, IFA_ADDRESS, &address.in6);
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poettering a = link_find_address(l, family, &address);
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poettering r = link_address_new(l, &a, family, &address);
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poettering log_warning_errno(r, "Failed to process RTNL address message: %m");
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poetteringstatic int manager_rtnl_listen(Manager *m) {
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poettering _cleanup_rtnl_message_unref_ sd_rtnl_message *req = NULL, *reply = NULL;
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poettering /* First, subscibe to interfaces coming and going */
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poettering r = sd_rtnl_open(&m->rtnl, 3, RTNLGRP_LINK, RTNLGRP_IPV4_IFADDR, RTNLGRP_IPV6_IFADDR);
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poettering r = sd_rtnl_attach_event(m->rtnl, m->event, 0);
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poettering r = sd_rtnl_add_match(m->rtnl, RTM_NEWLINK, manager_process_link, m);
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poettering r = sd_rtnl_add_match(m->rtnl, RTM_DELLINK, manager_process_link, m);
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poettering r = sd_rtnl_add_match(m->rtnl, RTM_NEWADDR, manager_process_address, m);
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poettering r = sd_rtnl_add_match(m->rtnl, RTM_DELADDR, manager_process_address, m);
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poettering /* Then, enumerate all links */
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poettering r = sd_rtnl_message_new_link(m->rtnl, &req, RTM_GETLINK, 0);
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poettering r = sd_rtnl_message_request_dump(req, true);
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poettering r = sd_rtnl_call(m->rtnl, req, 0, &reply);
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poettering for (i = reply; i; i = sd_rtnl_message_next(i)) {
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poettering /* Finally, enumerate all addresses, too */
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poettering r = sd_rtnl_message_new_addr(m->rtnl, &req, RTM_GETADDR, 0, AF_UNSPEC);
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poettering r = sd_rtnl_message_request_dump(req, true);
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poettering r = sd_rtnl_call(m->rtnl, req, 0, &reply);
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poettering for (i = reply; i; i = sd_rtnl_message_next(i)) {
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poettering r = manager_process_address(m->rtnl, i, m);
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poetteringstatic int on_network_event(sd_event_source *s, int fd, uint32_t revents, void *userdata) {
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poettering sd_network_monitor_flush(m->network_monitor);
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poettering log_warning_errno(r, "Failed to update monitor information for %i: %m", l->ifindex);
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poettering log_warning_errno(r, "Could not update resolv.conf: %m");
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poetteringstatic int manager_network_monitor_listen(Manager *m) {
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poettering r = sd_network_monitor_new(&m->network_monitor, NULL);
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poettering fd = sd_network_monitor_get_fd(m->network_monitor);
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poettering events = sd_network_monitor_get_events(m->network_monitor);
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poettering r = sd_event_add_io(m->event, &m->network_event_source, fd, events, &on_network_event, m);
17d33cecaa762f7e43200307328af5e9135e2091Giovanni Campagnastatic int determine_hostname(char **ret) {
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poettering _cleanup_free_ char *h = NULL, *n = NULL;
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poettering log_error("System hostname is not UTF-8 clean.");
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poettering log_error("System hostname '%s' cannot be normalized.", h);
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poetteringstatic int on_hostname_change(sd_event_source *es, int fd, uint32_t revents, void *userdata) {
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poettering return 0; /* ignore invalid hostnames */
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poettering log_info("System hostname changed to '%s'.", h);
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poetteringstatic int manager_watch_hostname(Manager *m) {
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poettering m->hostname_fd = open("/proc/sys/kernel/hostname", O_RDONLY|O_CLOEXEC|O_NDELAY|O_NOCTTY);
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poettering log_warning_errno(errno, "Failed to watch hostname: %m");
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poettering r = sd_event_add_io(m->event, &m->hostname_event_source, m->hostname_fd, 0, on_hostname_change, m);
17d33cecaa762f7e43200307328af5e9135e2091Giovanni Campagna /* kernels prior to 3.2 don't support polling this file. Ignore the failure. */
17d33cecaa762f7e43200307328af5e9135e2091Giovanni Campagna m->hostname_fd = safe_close(m->hostname_fd);
17d33cecaa762f7e43200307328af5e9135e2091Giovanni Campagna return log_error_errno(r, "Failed to add hostname event source: %m");
17d33cecaa762f7e43200307328af5e9135e2091Giovanni Campagna log_info("Defaulting to hostname 'linux'.");
17d33cecaa762f7e43200307328af5e9135e2091Giovanni Campagna log_info("Using system hostname '%s'.", m->hostname);
17d33cecaa762f7e43200307328af5e9135e2091Giovanni Campagnastatic void manager_llmnr_stop(Manager *m) {
17d33cecaa762f7e43200307328af5e9135e2091Giovanni Campagna m->llmnr_ipv4_udp_event_source = sd_event_source_unref(m->llmnr_ipv4_udp_event_source);
17d33cecaa762f7e43200307328af5e9135e2091Giovanni Campagna m->llmnr_ipv4_udp_fd = safe_close(m->llmnr_ipv4_udp_fd);
17d33cecaa762f7e43200307328af5e9135e2091Giovanni Campagna m->llmnr_ipv6_udp_event_source = sd_event_source_unref(m->llmnr_ipv6_udp_event_source);
17d33cecaa762f7e43200307328af5e9135e2091Giovanni Campagna m->llmnr_ipv6_udp_fd = safe_close(m->llmnr_ipv6_udp_fd);
17d33cecaa762f7e43200307328af5e9135e2091Giovanni Campagna m->llmnr_ipv4_tcp_event_source = sd_event_source_unref(m->llmnr_ipv4_tcp_event_source);
17d33cecaa762f7e43200307328af5e9135e2091Giovanni Campagna m->llmnr_ipv4_tcp_fd = safe_close(m->llmnr_ipv4_tcp_fd);
17d33cecaa762f7e43200307328af5e9135e2091Giovanni Campagna m->llmnr_ipv6_tcp_event_source = sd_event_source_unref(m->llmnr_ipv6_tcp_event_source);
bac3c8eefe23a820caac930d41629cebafbfc7b2Zbigniew Jędrzejewski-Szmek m->llmnr_ipv6_tcp_fd = safe_close(m->llmnr_ipv6_tcp_fd);
17d33cecaa762f7e43200307328af5e9135e2091Giovanni Campagnastatic int manager_llmnr_start(Manager *m) {
17d33cecaa762f7e43200307328af5e9135e2091Giovanni Campagna log_warning("There appears to be another LLMNR responder running. Turning off LLMNR support.");
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poettering _cleanup_(manager_freep) Manager *m = NULL;
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poettering m->llmnr_ipv4_udp_fd = m->llmnr_ipv6_udp_fd = -1;
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poettering m->llmnr_ipv4_tcp_fd = m->llmnr_ipv6_tcp_fd = -1;
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poettering r = manager_parse_dns_server(m, DNS_SERVER_FALLBACK, DNS_SERVERS);
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poettering sd_event_add_signal(m->event, NULL, SIGTERM, NULL, NULL);
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poettering sd_event_add_signal(m->event, NULL, SIGINT, NULL, NULL);
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poettering r = dns_scope_new(m, &m->unicast_scope, NULL, DNS_PROTOCOL_DNS, AF_UNSPEC);
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poettering manager_flush_dns_servers(m, DNS_SERVER_SYSTEM);
7fd1b19bc9e9f5574f2877936b8ac267c7706947Harald Hoyer manager_flush_dns_servers(m, DNS_SERVER_FALLBACK);
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poettering sd_event_source_unref(m->network_event_source);
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poettering sd_network_monitor_unref(m->network_monitor);
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poettering sd_event_source_unref(m->dns_ipv4_event_source);
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poettering sd_event_source_unref(m->dns_ipv6_event_source);
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poettering sd_bus_slot_unref(m->prepare_for_sleep_slot);
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poettering sd_event_source_unref(m->bus_retry_event_source);
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poettering dns_resource_key_unref(m->host_ipv4_key);
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poettering dns_resource_key_unref(m->host_ipv6_key);
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poettering sd_event_source_unref(m->hostname_event_source);
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poetteringint manager_read_resolv_conf(Manager *m) {
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poettering /* Reads the system /etc/resolv.conf, if it exists and is not
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poettering * symlinked to our own resolv.conf instance */
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poettering log_warning_errno(errno, "Failed to open /etc/resolv.conf: %m");
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poettering /* Have we already seen the file? */
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poettering /* Is it symlinked to our own file? */
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poettering if (stat("/run/systemd/resolve/resolv.conf", &own) >= 0 &&
50cfc579280fb42569488079bd2e249e32a27df2Lennart Poettering log_warning_errno(errno, "Failed to open /etc/resolv.conf: %m");
50cfc579280fb42569488079bd2e249e32a27df2Lennart Poettering log_error_errno(errno, "Failed to stat open file: %m");
50cfc579280fb42569488079bd2e249e32a27df2Lennart Poettering FOREACH_LINE(line, f, r = -errno; goto clear) {
50cfc579280fb42569488079bd2e249e32a27df2Lennart Poettering const char *a;
50cfc579280fb42569488079bd2e249e32a27df2Lennart Poettering r = in_addr_from_string_auto(a, &family, &address);
50cfc579280fb42569488079bd2e249e32a27df2Lennart Poettering log_warning("Failed to parse name server %s.", a);
50cfc579280fb42569488079bd2e249e32a27df2Lennart Poettering if (s->family == family && in_addr_equal(family, &s->address, &address) > 0)
50cfc579280fb42569488079bd2e249e32a27df2Lennart Poettering r = dns_server_new(m, NULL, DNS_SERVER_SYSTEM, NULL, family, &address);
50cfc579280fb42569488079bd2e249e32a27df2Lennart Poettering LIST_FOREACH_SAFE(servers, s, nx, m->dns_servers)
50cfc579280fb42569488079bd2e249e32a27df2Lennart Poettering /* Whenever /etc/resolv.conf changes, start using the first
50cfc579280fb42569488079bd2e249e32a27df2Lennart Poettering * DNS server of it. This is useful to deal with broken
50cfc579280fb42569488079bd2e249e32a27df2Lennart Poettering * network managing implementations (like NetworkManager),
50cfc579280fb42569488079bd2e249e32a27df2Lennart Poettering * that when connecting to a VPN place both the VPN DNS
50cfc579280fb42569488079bd2e249e32a27df2Lennart Poettering * servers and the local ones in /etc/resolv.conf. Without
50cfc579280fb42569488079bd2e249e32a27df2Lennart Poettering * resetting the DNS server to use back to the first entry we
50cfc579280fb42569488079bd2e249e32a27df2Lennart Poettering * will continue to use the local one thus being unable to
50cfc579280fb42569488079bd2e249e32a27df2Lennart Poettering * resolve VPN domains. */
50cfc579280fb42569488079bd2e249e32a27df2Lennart Poettering manager_set_dns_server(m, m->dns_servers);
50cfc579280fb42569488079bd2e249e32a27df2Lennart Poetteringstatic void write_resolv_conf_server(DnsServer *s, FILE *f, unsigned *count) {
50cfc579280fb42569488079bd2e249e32a27df2Lennart Poettering r = in_addr_to_string(s->family, &s->address, &t);
50cfc579280fb42569488079bd2e249e32a27df2Lennart Poettering log_warning_errno(r, "Invalid DNS address. Ignoring: %m");
50cfc579280fb42569488079bd2e249e32a27df2Lennart Poettering fputs("# Too many DNS servers configured, the following entries may be ignored.\n", f);
50cfc579280fb42569488079bd2e249e32a27df2Lennart Poetteringstatic void write_resolv_conf_search(const char *domain, FILE *f,
50cfc579280fb42569488079bd2e249e32a27df2Lennart Poettering fputs(" # Too many search domains configured, remaining ones ignored.", f);
50cfc579280fb42569488079bd2e249e32a27df2Lennart Poettering fputs(" # Total length of all search domains is too long, remaining ones ignored.", f);
50cfc579280fb42569488079bd2e249e32a27df2Lennart Poetteringstatic int write_resolv_conf_contents(FILE *f, Set *dns, Set *domains) {
50cfc579280fb42569488079bd2e249e32a27df2Lennart Poettering fputs("# This file is managed by systemd-resolved(8). Do not edit.\n#\n"
50cfc579280fb42569488079bd2e249e32a27df2Lennart Poettering "# Third party programs must not access this file directly, but\n"
50cfc579280fb42569488079bd2e249e32a27df2Lennart Poettering "# only through the symlink at /etc/resolv.conf. To manage\n"
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poettering "# resolv.conf(5) in a different way, replace the symlink by a\n"
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poettering "# static file or a different symlink.\n\n", f);
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poettering write_resolv_conf_search(domain, f, &count, &length);
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poetteringint manager_write_resolv_conf(Manager *m) {
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poettering static const char path[] = "/run/systemd/resolve/resolv.conf";
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poettering _cleanup_set_free_ Set *dns = NULL, *domains = NULL;
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poettering /* Read the system /etc/resolv.conf first */
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poettering /* Add the full list to a set, to filter out duplicates */
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poettering /* First add the system-wide servers */
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poettering LIST_FOREACH(servers, s, m->dns_servers) {
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poettering /* Then, add the per-link servers and domains */
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poettering LIST_FOREACH(servers, s, l->dns_servers) {
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poettering STRV_FOREACH(domain, l->unicast_scope->domains) {
50cfc579280fb42569488079bd2e249e32a27df2Lennart Poettering /* If we found nothing, add the fallback servers */
50cfc579280fb42569488079bd2e249e32a27df2Lennart Poettering LIST_FOREACH(servers, s, m->fallback_dns_servers) {
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poettering r = fopen_temporary_label(path, path, &f, &temp_path);
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poettering r = write_resolv_conf_contents(f, dns, domains);
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poetteringint manager_recv(Manager *m, int fd, DnsProtocol protocol, DnsPacket **ret) {
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poettering _cleanup_(dns_packet_unrefp) DnsPacket *p = NULL;
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poettering struct cmsghdr header; /* For alignment */
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poettering uint8_t buffer[CMSG_SPACE(MAXSIZE(struct in_pktinfo, struct in6_pktinfo))
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poettering + EXTRA_CMSG_SPACE /* kernel appears to require extra buffer space */];
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poettering p->sender_port = be16toh(sa.in.sin_port);
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poettering p->sender_port = be16toh(sa.in6.sin6_port);
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poettering for (cmsg = CMSG_FIRSTHDR(&mh); cmsg; cmsg = CMSG_NXTHDR(&mh, cmsg)) {
2087a7aff26ea5d1bc2c7c29add3275328f36baaLennart Poettering struct in6_pktinfo *i = (struct in6_pktinfo*) CMSG_DATA(cmsg);
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 == s)
m->current_dns_server = s;
if (m->unicast_scope)
Link *l;
assert(m);
/* Try to read updates resolv.conf */
if (!m->current_dns_server)
if (!m->current_dns_server) {
bool found = false;
Iterator i;
if (l->dns_servers) {
found = true;
if (!found)
return m->current_dns_server;
assert(m);
if (!m->current_dns_server)
Link *l;
Iterator i;
if (l->mtu <= 0)
return mtu;
if (!scope) {
if (dns_packet_validate_reply(p) > 0) {
} else if (dns_packet_validate_query(p) > 0) {
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);
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:
LinkAddress *a;
assert(m);
Iterator i;
Link *l;
assert(m);
link_add_rrs(l, true);
link_add_rrs(l, false);
uint64_t u, a;
assert(m);
assert(p);
while (p > m->hostname) {
if (*p == 0 || safe_atou64(p, &u) < 0 || u <= 0)
random_bytes(&a, sizeof(a));
return -ENOMEM;
m->hostname = h;
LinkAddress* manager_find_link_address(Manager *m, int family, const union in_addr_union *in_addr) {
Iterator i;
Link *l;
assert(m);
LinkAddress *a;
return NULL;
assert(m);
assert(p);
Link *l;
assert(m);
assert(p);
return NULL;
return l->llmnr_ipv4_scope;
return l->llmnr_ipv6_scope;
return NULL;
DnsScope *s;
assert(m);
assert(m);
if (t == DNS_SERVER_SYSTEM)
while (m->dns_servers)
if (t == DNS_SERVER_FALLBACK)
while (m->fallback_dns_servers)