resolved-manager.c revision ad867662936a4c7ab2c7116d804c272338801231
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering/***
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering This file is part of systemd.
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering Copyright 2014 Tom Gundersen <teg@jklm.no>
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering
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
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
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 ***/
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering
b5efdb8af40ea759a1ea584c1bc44ecc81dd00ceLennart Poettering#include <arpa/inet.h>
07630cea1f3a845c09309f197ac7c4f11edd3b62Lennart Poettering#include <resolv.h>
3ffd4af22052963e7a29431721ee204e634bea75Lennart Poettering#include <linux/if.h>
afc5dbf37fd2399d37976388d9dd9ab470ecf446Lennart Poettering#include <sys/ioctl.h>
afc5dbf37fd2399d37976388d9dd9ab470ecf446Lennart Poettering#include <sys/poll.h>
3ffd4af22052963e7a29431721ee204e634bea75Lennart Poettering#include <netinet/in.h>
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering
07630cea1f3a845c09309f197ac7c4f11edd3b62Lennart Poettering#include "rtnl-util.h"
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering#include "event-util.h"
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering#include "network-util.h"
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering#include "sd-dhcp-lease.h"
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering#include "dhcp-lease-internal.h"
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering#include "network-internal.h"
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering#include "conf-parser.h"
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering#include "socket-util.h"
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering#include "resolved.h"
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering#define SEND_TIMEOUT_USEC (200 * USEC_PER_MSEC)
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering
875c2e220e2611165e09051c4747971811f1de58Lennart Poetteringstatic int manager_process_link(sd_rtnl *rtnl, sd_rtnl_message *mm, void *userdata) {
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering Manager *m = userdata;
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering uint16_t type;
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering Link *l;
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering int ifindex, r;
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering assert(rtnl);
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering assert(m);
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering assert(mm);
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering r = sd_rtnl_message_get_type(mm, &type);
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering if (r < 0)
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering goto fail;
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering r = sd_rtnl_message_link_get_ifindex(mm, &ifindex);
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering if (r < 0)
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering goto fail;
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering l = hashmap_get(m->links, INT_TO_PTR(ifindex));
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering switch (type) {
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering case RTM_NEWLINK:
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering if (!l) {
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering log_debug("Found link %i", ifindex);
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering r = link_new(m, &l, ifindex);
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering if (r < 0)
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering goto fail;
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering }
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering r = link_update_rtnl(l, mm);
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering if (r < 0)
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering goto fail;
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering
78fe420ff0bb4cd94de3c4d3f15a3021cc3e2878Lennart Poettering break;
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering case RTM_DELLINK:
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering if (l) {
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering log_debug("Removing link %i", l->ifindex);
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering link_free(l);
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering }
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering break;
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering }
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering return 0;
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering
875c2e220e2611165e09051c4747971811f1de58Lennart Poetteringfail:
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering log_warning("Failed to process RTNL link message: %s", strerror(-r));
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering return 0;
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering}
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering
875c2e220e2611165e09051c4747971811f1de58Lennart Poetteringstatic int manager_process_address(sd_rtnl *rtnl, sd_rtnl_message *mm, void *userdata) {
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering Manager *m = userdata;
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering union in_addr_union address;
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering unsigned char family;
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering uint16_t type;
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering int r, ifindex;
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering LinkAddress *a;
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering Link *l;
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering assert(rtnl);
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering assert(mm);
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering assert(m);
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering r = sd_rtnl_message_get_type(mm, &type);
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering if (r < 0)
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering goto fail;
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering r = sd_rtnl_message_addr_get_ifindex(mm, &ifindex);
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering if (r < 0)
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering goto fail;
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering l = hashmap_get(m->links, INT_TO_PTR(ifindex));
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering if (!l)
78fe420ff0bb4cd94de3c4d3f15a3021cc3e2878Lennart Poettering return 0;
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering r = sd_rtnl_message_addr_get_family(mm, &family);
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering if (r < 0)
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering goto fail;
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering switch (family) {
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering case AF_INET:
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering r = sd_rtnl_message_read_in_addr(mm, IFA_LOCAL, &address.in);
78fe420ff0bb4cd94de3c4d3f15a3021cc3e2878Lennart Poettering if (r < 0) {
78fe420ff0bb4cd94de3c4d3f15a3021cc3e2878Lennart Poettering r = sd_rtnl_message_read_in_addr(mm, IFA_ADDRESS, &address.in);
78fe420ff0bb4cd94de3c4d3f15a3021cc3e2878Lennart Poettering if (r < 0)
78fe420ff0bb4cd94de3c4d3f15a3021cc3e2878Lennart Poettering goto fail;
78fe420ff0bb4cd94de3c4d3f15a3021cc3e2878Lennart Poettering }
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering break;
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering
78fe420ff0bb4cd94de3c4d3f15a3021cc3e2878Lennart Poettering case AF_INET6:
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering r = sd_rtnl_message_read_in6_addr(mm, IFA_LOCAL, &address.in6);
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering if (r < 0) {
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering r = sd_rtnl_message_read_in6_addr(mm, IFA_ADDRESS, &address.in6);
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering if (r < 0)
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering goto fail;
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering }
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering break;
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering default:
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering return 0;
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering }
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering a = link_find_address(l, family, &address);
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering switch (type) {
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering case RTM_NEWADDR:
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering
78fe420ff0bb4cd94de3c4d3f15a3021cc3e2878Lennart Poettering if (!a) {
78fe420ff0bb4cd94de3c4d3f15a3021cc3e2878Lennart Poettering r = link_address_new(l, &a, family, &address);
78fe420ff0bb4cd94de3c4d3f15a3021cc3e2878Lennart Poettering if (r < 0)
78fe420ff0bb4cd94de3c4d3f15a3021cc3e2878Lennart Poettering return r;
78fe420ff0bb4cd94de3c4d3f15a3021cc3e2878Lennart Poettering }
78fe420ff0bb4cd94de3c4d3f15a3021cc3e2878Lennart Poettering
78fe420ff0bb4cd94de3c4d3f15a3021cc3e2878Lennart Poettering r = link_address_update_rtnl(a, mm);
78fe420ff0bb4cd94de3c4d3f15a3021cc3e2878Lennart Poettering if (r < 0)
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering return r;
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering break;
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering case RTM_DELADDR:
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering if (a)
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering link_address_free(a);
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering break;
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering }
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering return 0;
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering
875c2e220e2611165e09051c4747971811f1de58Lennart Poetteringfail:
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering log_warning("Failed to process RTNL address message: %s", strerror(-r));
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering return 0;
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering}
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering
9833a66c7eba011c3740867c80133bc6fa976aa3Lennart Poetteringstatic int manager_rtnl_listen(Manager *m) {
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering _cleanup_rtnl_message_unref_ sd_rtnl_message *req = NULL, *reply = NULL;
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering sd_rtnl_message *i;
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering int r;
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering assert(m);
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering
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);
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering if (r < 0)
9833a66c7eba011c3740867c80133bc6fa976aa3Lennart Poettering return r;
9833a66c7eba011c3740867c80133bc6fa976aa3Lennart Poettering
9833a66c7eba011c3740867c80133bc6fa976aa3Lennart Poettering r = sd_rtnl_attach_event(m->rtnl, m->event, 0);
9833a66c7eba011c3740867c80133bc6fa976aa3Lennart Poettering if (r < 0)
9833a66c7eba011c3740867c80133bc6fa976aa3Lennart Poettering return r;
9833a66c7eba011c3740867c80133bc6fa976aa3Lennart Poettering
9833a66c7eba011c3740867c80133bc6fa976aa3Lennart Poettering r = sd_rtnl_add_match(m->rtnl, RTM_NEWLINK, manager_process_link, m);
9833a66c7eba011c3740867c80133bc6fa976aa3Lennart Poettering if (r < 0)
9833a66c7eba011c3740867c80133bc6fa976aa3Lennart Poettering return r;
9833a66c7eba011c3740867c80133bc6fa976aa3Lennart Poettering
9833a66c7eba011c3740867c80133bc6fa976aa3Lennart Poettering r = sd_rtnl_add_match(m->rtnl, RTM_DELLINK, manager_process_link, m);
9833a66c7eba011c3740867c80133bc6fa976aa3Lennart Poettering if (r < 0)
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering return r;
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering r = sd_rtnl_add_match(m->rtnl, RTM_NEWADDR, manager_process_address, m);
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering if (r < 0)
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering return r;
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering r = sd_rtnl_add_match(m->rtnl, RTM_DELADDR, manager_process_address, m);
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering if (r < 0)
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering return r;
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering /* Then, enumerate all links */
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering r = sd_rtnl_message_new_link(m->rtnl, &req, RTM_GETLINK, 0);
f131770b1465fbf423881f16ba85523a05f846feVeres Lajos if (r < 0)
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering return r;
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering r = sd_rtnl_message_request_dump(req, true);
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering if (r < 0)
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering return r;
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering r = sd_rtnl_call(m->rtnl, req, 0, &reply);
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering if (r < 0)
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering return r;
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering for (i = reply; i; i = sd_rtnl_message_next(i)) {
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering r = manager_process_link(m->rtnl, i, m);
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering if (r < 0)
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering return r;
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering }
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering req = sd_rtnl_message_unref(req);
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering reply = sd_rtnl_message_unref(reply);
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering /* Finally, enumerate all addresses, too */
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering r = sd_rtnl_message_new_addr(m->rtnl, &req, RTM_GETADDR, 0, AF_UNSPEC);
78fe420ff0bb4cd94de3c4d3f15a3021cc3e2878Lennart Poettering if (r < 0)
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering return r;
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering r = sd_rtnl_message_request_dump(req, true);
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering if (r < 0)
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering return r;
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering r = sd_rtnl_call(m->rtnl, req, 0, &reply);
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering if (r < 0)
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering return r;
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering for (i = reply; i; i = sd_rtnl_message_next(i)) {
f131770b1465fbf423881f16ba85523a05f846feVeres Lajos r = manager_process_address(m->rtnl, i, m);
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering if (r < 0)
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering return r;
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering }
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering return r;
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering}
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering
875c2e220e2611165e09051c4747971811f1de58Lennart Poetteringstatic int on_network_event(sd_event_source *s, int fd, uint32_t revents, void *userdata) {
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering Manager *m = userdata;
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering Iterator i;
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering Link *l;
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering int r;
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering assert(m);
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering sd_network_monitor_flush(m->network_monitor);
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering HASHMAP_FOREACH(l, m->links, i) {
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering r = link_update_monitor(l);
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering if (r < 0)
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering log_warning("Failed to update monitor information for %i: %s", l->ifindex, strerror(-r));
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering }
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering r = manager_write_resolv_conf(m);
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering if (r < 0)
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering log_warning("Could not update resolv.conf: %s", strerror(-r));
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering return 0;
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering}
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering
875c2e220e2611165e09051c4747971811f1de58Lennart Poetteringstatic int manager_network_monitor_listen(Manager *m) {
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering int r, fd, events;
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering assert(m);
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering r = sd_network_monitor_new(NULL, &m->network_monitor);
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering if (r < 0)
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering return r;
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering fd = sd_network_monitor_get_fd(m->network_monitor);
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering if (fd < 0)
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering return fd;
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering events = sd_network_monitor_get_events(m->network_monitor);
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering if (events < 0)
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering return events;
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering r = sd_event_add_io(m->event, &m->network_event_source, fd, events, &on_network_event, m);
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering if (r < 0)
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering return r;
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering return 0;
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering}
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering
875c2e220e2611165e09051c4747971811f1de58Lennart Poetteringstatic int parse_dns_server_string(Manager *m, const char *string) {
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering char *word, *state;
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering size_t length;
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering int r;
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering assert(m);
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering assert(string);
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering FOREACH_WORD_QUOTED(word, length, string, state) {
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering char buffer[length+1];
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering unsigned family;
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering union in_addr_union addr;
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering
23bbb0de4e3f85d9704a5c12a5afa2dfa0159e41Michal Schmidt memcpy(buffer, word, length);
23bbb0de4e3f85d9704a5c12a5afa2dfa0159e41Michal Schmidt buffer[length] = 0;
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering r = in_addr_from_string_auto(buffer, &family, &addr);
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering if (r < 0) {
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering log_warning("Ignoring invalid DNS address '%s'", buffer);
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering continue;
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering }
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering /* filter out duplicates */
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering if (manager_find_dns_server(m, family, &addr))
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering continue;
23bbb0de4e3f85d9704a5c12a5afa2dfa0159e41Michal Schmidt
23bbb0de4e3f85d9704a5c12a5afa2dfa0159e41Michal Schmidt r = dns_server_new(m, NULL, DNS_SERVER_SYSTEM, NULL, family, &addr);
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering if (r < 0)
ece174c5439021e32ebcc858842de9586072c006Lennart Poettering return r;
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering }
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering return 0;
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering}
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering
875c2e220e2611165e09051c4747971811f1de58Lennart Poetteringint config_parse_dnsv(
0b97208d8c39131f8a7cfcfccb5c40b86af44ee5Lennart Poettering const char *unit,
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering const char *filename,
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering unsigned line,
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering const char *section,
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering unsigned section_line,
8bb3626dac93c0157989fb87afe0212958d7dbb4Zbigniew Jędrzejewski-Szmek const char *lvalue,
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering int ltype,
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering const char *rvalue,
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering void *data,
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering void *userdata) {
25b3245fb483e52766867dfe33ce271011caaca9Lennart Poettering
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering Manager *m = userdata;
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering int r;
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering assert(filename);
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering assert(lvalue);
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering assert(rvalue);
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering assert(m);
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering /* Empty assignment means clear the list */
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering if (isempty(rvalue)) {
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering while (m->dns_servers)
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering dns_server_free(m->dns_servers);
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering return 0;
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering }
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering r = parse_dns_server_string(m, rvalue);
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering if (r < 0) {
1fa2f38f0f011010bf57522b42fcc168856a7003Zbigniew Jędrzejewski-Szmek log_error("Failed to parse DNS server string");
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering return r;
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering }
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering return 0;
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering}
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering
875c2e220e2611165e09051c4747971811f1de58Lennart Poetteringint manager_parse_config_file(Manager *m) {
5034c7bcdfc4493ed3c30722e9d897c8da78fedeLennart Poettering int r;
5034c7bcdfc4493ed3c30722e9d897c8da78fedeLennart Poettering
5034c7bcdfc4493ed3c30722e9d897c8da78fedeLennart Poettering assert(m);
5034c7bcdfc4493ed3c30722e9d897c8da78fedeLennart Poettering
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering r = config_parse(NULL, "/etc/systemd/resolved.conf", NULL,
cd556b6ca8aec8dd371806afedec45f852f8f724Zbigniew Jędrzejewski-Szmek "Resolve\0",
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering config_item_perf_lookup, resolved_gperf_lookup,
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering false, false, m);
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering if (r < 0)
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering log_warning("Failed to parse configuration file: %s", strerror(-r));
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering return 0;
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering}
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering
875c2e220e2611165e09051c4747971811f1de58Lennart Poetteringint manager_new(Manager **ret) {
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering _cleanup_(manager_freep) Manager *m = NULL;
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering int r;
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering assert(ret);
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering m = new0(Manager, 1);
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering if (!m)
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering return -ENOMEM;
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering
cd556b6ca8aec8dd371806afedec45f852f8f724Zbigniew Jędrzejewski-Szmek m->dns_ipv4_fd = m->dns_ipv6_fd = -1;
cd556b6ca8aec8dd371806afedec45f852f8f724Zbigniew Jędrzejewski-Szmek
cd556b6ca8aec8dd371806afedec45f852f8f724Zbigniew Jędrzejewski-Szmek r = parse_dns_server_string(m, /* "172.31.0.125 2001:4860:4860::8888 2001:4860:4860::8889" */ DNS_SERVERS);
cd556b6ca8aec8dd371806afedec45f852f8f724Zbigniew Jędrzejewski-Szmek if (r < 0)
8bb3626dac93c0157989fb87afe0212958d7dbb4Zbigniew Jędrzejewski-Szmek return r;
8bb3626dac93c0157989fb87afe0212958d7dbb4Zbigniew Jędrzejewski-Szmek
8bb3626dac93c0157989fb87afe0212958d7dbb4Zbigniew Jędrzejewski-Szmek r = sd_event_default(&m->event);
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering if (r < 0)
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering return r;
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering
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
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering sd_event_set_watchdog(m->event, true);
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering r = dns_scope_new(m, &m->unicast_scope, DNS_SCOPE_DNS);
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering if (r < 0)
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering return r;
0b97208d8c39131f8a7cfcfccb5c40b86af44ee5Lennart Poettering
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering r = manager_network_monitor_listen(m);
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering if (r < 0)
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering return r;
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering r = manager_rtnl_listen(m);
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering if (r < 0)
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering return r;
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering r = manager_connect_bus(m);
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering if (r < 0)
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering return r;
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering *ret = m;
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering m = NULL;
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering return 0;
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering}
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering
875c2e220e2611165e09051c4747971811f1de58Lennart PoetteringManager *manager_free(Manager *m) {
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering Link *l;
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering if (!m)
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering return NULL;
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering while (m->dns_queries)
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering dns_query_free(m->dns_queries);
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering hashmap_free(m->dns_query_transactions);
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering while ((l = hashmap_first(m->links)))
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering link_free(l);
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering hashmap_free(m->links);
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering dns_scope_free(m->unicast_scope);
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering while (m->dns_servers)
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering dns_server_free(m->dns_servers);
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering sd_event_source_unref(m->network_event_source);
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering sd_network_monitor_unref(m->network_monitor);
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering sd_event_source_unref(m->dns_ipv4_event_source);
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering sd_event_source_unref(m->dns_ipv6_event_source);
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering safe_close(m->dns_ipv4_fd);
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering safe_close(m->dns_ipv6_fd);
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering sd_event_source_unref(m->bus_retry_event_source);
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering sd_bus_unref(m->bus);
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering sd_event_unref(m->event);
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering free(m);
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering
0b97208d8c39131f8a7cfcfccb5c40b86af44ee5Lennart Poettering return NULL;
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering}
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering
4d9ced9956755901238fede6fc5a3d7e4e816aa6Lennart Poetteringstatic void write_resolve_conf_server(DnsServer *s, FILE *f, unsigned *count) {
4d9ced9956755901238fede6fc5a3d7e4e816aa6Lennart Poettering _cleanup_free_ char *t = NULL;
4d9ced9956755901238fede6fc5a3d7e4e816aa6Lennart Poettering int r;
4d9ced9956755901238fede6fc5a3d7e4e816aa6Lennart Poettering
4d9ced9956755901238fede6fc5a3d7e4e816aa6Lennart Poettering assert(s);
4d9ced9956755901238fede6fc5a3d7e4e816aa6Lennart Poettering assert(f);
4d9ced9956755901238fede6fc5a3d7e4e816aa6Lennart Poettering assert(count);
4d9ced9956755901238fede6fc5a3d7e4e816aa6Lennart Poettering
4d9ced9956755901238fede6fc5a3d7e4e816aa6Lennart Poettering r = in_addr_to_string(s->family, &s->address, &t);
4d9ced9956755901238fede6fc5a3d7e4e816aa6Lennart Poettering if (r < 0) {
4d9ced9956755901238fede6fc5a3d7e4e816aa6Lennart Poettering log_warning("Invalid DNS address. Ignoring.");
4d9ced9956755901238fede6fc5a3d7e4e816aa6Lennart Poettering return;
4d9ced9956755901238fede6fc5a3d7e4e816aa6Lennart Poettering }
4d9ced9956755901238fede6fc5a3d7e4e816aa6Lennart Poettering
4d9ced9956755901238fede6fc5a3d7e4e816aa6Lennart Poettering if (*count == MAXNS)
4d9ced9956755901238fede6fc5a3d7e4e816aa6Lennart Poettering fputs("# Too many DNS servers configured, the following entries may be ignored\n", f);
4d9ced9956755901238fede6fc5a3d7e4e816aa6Lennart Poettering
4d9ced9956755901238fede6fc5a3d7e4e816aa6Lennart Poettering fprintf(f, "nameserver %s\n", t);
4d9ced9956755901238fede6fc5a3d7e4e816aa6Lennart Poettering (*count) ++;
4d9ced9956755901238fede6fc5a3d7e4e816aa6Lennart Poettering}
4d9ced9956755901238fede6fc5a3d7e4e816aa6Lennart Poettering
4d9ced9956755901238fede6fc5a3d7e4e816aa6Lennart Poetteringint manager_write_resolv_conf(Manager *m) {
4d9ced9956755901238fede6fc5a3d7e4e816aa6Lennart Poettering const char *path = "/run/systemd/resolve/resolv.conf";
4d9ced9956755901238fede6fc5a3d7e4e816aa6Lennart Poettering _cleanup_free_ char *temp_path = NULL;
4d9ced9956755901238fede6fc5a3d7e4e816aa6Lennart Poettering _cleanup_fclose_ FILE *f = NULL;
4d9ced9956755901238fede6fc5a3d7e4e816aa6Lennart Poettering unsigned count = 0;
4d9ced9956755901238fede6fc5a3d7e4e816aa6Lennart Poettering DnsServer *s;
4d9ced9956755901238fede6fc5a3d7e4e816aa6Lennart Poettering Iterator i;
4d9ced9956755901238fede6fc5a3d7e4e816aa6Lennart Poettering Link *l;
4d9ced9956755901238fede6fc5a3d7e4e816aa6Lennart Poettering int r;
4d9ced9956755901238fede6fc5a3d7e4e816aa6Lennart Poettering
4d9ced9956755901238fede6fc5a3d7e4e816aa6Lennart Poettering assert(m);
4d9ced9956755901238fede6fc5a3d7e4e816aa6Lennart Poettering
4d9ced9956755901238fede6fc5a3d7e4e816aa6Lennart Poettering r = fopen_temporary(path, &f, &temp_path);
4d9ced9956755901238fede6fc5a3d7e4e816aa6Lennart Poettering if (r < 0)
4d9ced9956755901238fede6fc5a3d7e4e816aa6Lennart Poettering return r;
4d9ced9956755901238fede6fc5a3d7e4e816aa6Lennart Poettering
4d9ced9956755901238fede6fc5a3d7e4e816aa6Lennart Poettering fchmod(fileno(f), 0644);
4d9ced9956755901238fede6fc5a3d7e4e816aa6Lennart Poettering
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);
4d9ced9956755901238fede6fc5a3d7e4e816aa6Lennart Poettering
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering HASHMAP_FOREACH(l, m->links, i) {
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering LIST_FOREACH(servers, s, l->link_dns_servers)
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering write_resolve_conf_server(s, f, &count);
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering LIST_FOREACH(servers, s, l->dhcp_dns_servers)
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering write_resolve_conf_server(s, f, &count);
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering }
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering LIST_FOREACH(servers, s, m->dns_servers)
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering write_resolve_conf_server(s, f, &count);
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering r = fflush_and_check(f);
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering if (r < 0)
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering goto fail;
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering if (rename(temp_path, path) < 0) {
56f64d95763a799ba4475daf44d8e9f72a1bd474Michal Schmidt r = -errno;
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering goto fail;
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering }
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering return 0;
417a7fdc418ec76cc4c321c9a07ec15c72b3ac7dLennart Poettering
417a7fdc418ec76cc4c321c9a07ec15c72b3ac7dLennart Poetteringfail:
417a7fdc418ec76cc4c321c9a07ec15c72b3ac7dLennart Poettering unlink(path);
417a7fdc418ec76cc4c321c9a07ec15c72b3ac7dLennart Poettering unlink(temp_path);
417a7fdc418ec76cc4c321c9a07ec15c72b3ac7dLennart Poettering return r;
417a7fdc418ec76cc4c321c9a07ec15c72b3ac7dLennart Poettering}
417a7fdc418ec76cc4c321c9a07ec15c72b3ac7dLennart Poettering
417a7fdc418ec76cc4c321c9a07ec15c72b3ac7dLennart Poetteringint manager_dns_ipv4_recv(Manager *m, DnsPacket **ret) {
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering _cleanup_(dns_packet_unrefp) DnsPacket *p = NULL;
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering struct msghdr mh = {};
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering int fd, ms = 0, r;
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering struct iovec iov;
4a62c710b62a5a3c7a8a278b810b9d5b5a0c8f4fMichal Schmidt ssize_t l;
4a62c710b62a5a3c7a8a278b810b9d5b5a0c8f4fMichal Schmidt
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering assert(m);
8531ae707d4d0203e83304d4af948b8169a5fce1Lennart Poettering assert(ret);
23bbb0de4e3f85d9704a5c12a5afa2dfa0159e41Michal Schmidt
23bbb0de4e3f85d9704a5c12a5afa2dfa0159e41Michal Schmidt fd = manager_dns_ipv4_fd(m);
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering if (fd < 0)
4d9ced9956755901238fede6fc5a3d7e4e816aa6Lennart Poettering return fd;
4d9ced9956755901238fede6fc5a3d7e4e816aa6Lennart Poettering
4d9ced9956755901238fede6fc5a3d7e4e816aa6Lennart Poettering r = ioctl(fd, FIONREAD, &ms);
da927ba997d68401563b927f92e6e40e021a8e5cMichal Schmidt if (r < 0)
4d9ced9956755901238fede6fc5a3d7e4e816aa6Lennart Poettering return -errno;
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering if (ms < 0)
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering return -EIO;
r = dns_packet_new(&p, ms);
if (r < 0)
return r;
iov.iov_base = DNS_PACKET_DATA(p);
iov.iov_len = p->allocated;
mh.msg_iov = &iov;
mh.msg_iovlen = 1;
l = recvmsg(fd, &mh, 0);
if (l < 0) {
if (errno == EAGAIN || errno == EINTR)
return 0;
return -errno;
}
if (l <= 0)
return -EIO;
p->size = (size_t) l;
*ret = p;
p = NULL;
return 1;
}
int manager_dns_ipv6_recv(Manager *m, DnsPacket **ret) {
_cleanup_(dns_packet_unrefp) DnsPacket *p = NULL;
struct msghdr mh = {};
struct iovec iov;
int fd, ms = 0, r;
ssize_t l;
assert(m);
assert(ret);
fd = manager_dns_ipv6_fd(m);
if (fd < 0)
return fd;
r = ioctl(fd, FIONREAD, &ms);
if (r < 0)
return -errno;
if (ms < 0)
return -EIO;
r = dns_packet_new(&p, ms);
if (r < 0)
return r;
iov.iov_base = DNS_PACKET_DATA(p);
iov.iov_len = p->allocated;
mh.msg_iov = &iov;
mh.msg_iovlen = 1;
l = recvmsg(fd, &mh, 0);
if (l < 0) {
if (errno == EAGAIN || errno == EINTR)
return 0;
return -errno;
}
if (l <= 0)
return -EIO;
p->size = (size_t) l;
*ret = p;
p = NULL;
return 1;
}
static int on_dns_ipv4_packet(sd_event_source *s, int fd, uint32_t revents, void *userdata) {
_cleanup_(dns_packet_unrefp) DnsPacket *p = NULL;
DnsQueryTransaction *t = NULL;
Manager *m = userdata;
int r;
r = manager_dns_ipv4_recv(m, &p);
if (r <= 0)
return r;
t = hashmap_get(m->dns_query_transactions, UINT_TO_PTR(DNS_PACKET_ID(p)));
if (!t)
return 0;
dns_query_transaction_reply(t, p);
return 0;
}
static int on_dns_ipv6_packet(sd_event_source *s, int fd, uint32_t revents, void *userdata) {
_cleanup_(dns_packet_unrefp) DnsPacket *p = NULL;
DnsQueryTransaction *t = NULL;
Manager *m = userdata;
int r;
r = manager_dns_ipv6_recv(m, &p);
if (r <= 0)
return r;
t = hashmap_get(m->dns_query_transactions, UINT_TO_PTR(DNS_PACKET_ID(p)));
if (!t)
return 0;
dns_query_transaction_reply(t, p);
return 0;
}
int manager_dns_ipv4_fd(Manager *m) {
int r;
assert(m);
if (m->dns_ipv4_fd >= 0)
return m->dns_ipv4_fd;
m->dns_ipv4_fd = socket(AF_INET, SOCK_DGRAM|SOCK_CLOEXEC|SOCK_NONBLOCK, 0);
if (m->dns_ipv4_fd < 0)
return -errno;
r = sd_event_add_io(m->event, &m->dns_ipv4_event_source, m->dns_ipv4_fd, EPOLLIN, on_dns_ipv4_packet, m);
if (r < 0)
return r;
return m->dns_ipv4_fd;
}
int manager_dns_ipv6_fd(Manager *m) {
int r;
assert(m);
if (m->dns_ipv6_fd >= 0)
return m->dns_ipv6_fd;
m->dns_ipv6_fd = socket(AF_INET6, SOCK_DGRAM|SOCK_CLOEXEC|SOCK_NONBLOCK, 0);
if (m->dns_ipv6_fd < 0)
return -errno;
r = sd_event_add_io(m->event, &m->dns_ipv6_event_source, m->dns_ipv6_fd, EPOLLIN, on_dns_ipv6_packet, m);
if (r < 0)
return r;
return m->dns_ipv6_fd;
}
static int sendmsg_loop(int fd, struct msghdr *mh, int flags) {
int r;
assert(fd >= 0);
assert(mh);
for (;;) {
if (sendmsg(fd, mh, flags) >= 0)
return 0;
if (errno == EINTR)
continue;
if (errno != EAGAIN)
return -errno;
r = fd_wait_for_event(fd, POLLOUT, SEND_TIMEOUT_USEC);
if (r < 0)
return r;
if (r == 0)
return -ETIMEDOUT;
}
}
int manager_dns_ipv4_send(Manager *m, DnsServer *srv, int ifindex, DnsPacket *p) {
union sockaddr_union sa = {
.in.sin_family = AF_INET,
.in.sin_port = htobe16(53),
};
struct msghdr mh = {};
struct iovec iov;
uint8_t control[CMSG_SPACE(sizeof(struct in_pktinfo))];
int fd;
assert(m);
assert(srv);
assert(p);
fd = manager_dns_ipv4_fd(m);
if (fd < 0)
return fd;
iov.iov_base = DNS_PACKET_DATA(p);
iov.iov_len = p->size;
sa.in.sin_addr = srv->address.in;
mh.msg_iov = &iov;
mh.msg_iovlen = 1;
mh.msg_name = &sa.sa;
mh.msg_namelen = sizeof(sa.in);
if (ifindex > 0) {
struct cmsghdr *cmsg;
struct in_pktinfo *pi;
zero(control);
mh.msg_control = control;
mh.msg_controllen = CMSG_LEN(sizeof(struct in_pktinfo));
cmsg = CMSG_FIRSTHDR(&mh);
cmsg->cmsg_len = mh.msg_controllen;
cmsg->cmsg_level = IPPROTO_IP;
cmsg->cmsg_type = IP_PKTINFO;
pi = (struct in_pktinfo*) CMSG_DATA(cmsg);
pi->ipi_ifindex = ifindex;
}
return sendmsg_loop(fd, &mh, 0);
}
int manager_dns_ipv6_send(Manager *m, DnsServer *srv, int ifindex, DnsPacket *p) {
union sockaddr_union sa = {
.in6.sin6_family = AF_INET6,
.in6.sin6_port = htobe16(53),
};
struct msghdr mh = {};
struct iovec iov;
uint8_t control[CMSG_SPACE(sizeof(struct in6_pktinfo))];
int fd;
assert(m);
assert(srv);
assert(p);
fd = manager_dns_ipv6_fd(m);
if (fd < 0)
return fd;
iov.iov_base = DNS_PACKET_DATA(p);
iov.iov_len = p->size;
sa.in6.sin6_addr = srv->address.in6;
sa.in6.sin6_scope_id = ifindex;
mh.msg_iov = &iov;
mh.msg_iovlen = 1;
mh.msg_name = &sa.sa;
mh.msg_namelen = sizeof(sa.in6);
if (ifindex > 0) {
struct cmsghdr *cmsg;
struct in6_pktinfo *pi;
zero(control);
mh.msg_control = control;
mh.msg_controllen = CMSG_LEN(sizeof(struct in6_pktinfo));
cmsg = CMSG_FIRSTHDR(&mh);
cmsg->cmsg_len = mh.msg_controllen;
cmsg->cmsg_level = IPPROTO_IPV6;
cmsg->cmsg_type = IPV6_PKTINFO;
pi = (struct in6_pktinfo*) CMSG_DATA(cmsg);
pi->ipi6_ifindex = ifindex;
}
return sendmsg_loop(fd, &mh, 0);
}
DnsServer* manager_find_dns_server(Manager *m, unsigned char family, union in_addr_union *in_addr) {
DnsServer *s;
assert(m);
assert(in_addr);
LIST_FOREACH(servers, s, m->dns_servers) {
if (s->family == family &&
in_addr_equal(family, &s->address, in_addr))
return s;
}
return NULL;
}
DnsServer *manager_get_dns_server(Manager *m) {
assert(m);
if (!m->current_dns_server)
m->current_dns_server = m->dns_servers;
return m->current_dns_server;
}
void manager_next_dns_server(Manager *m) {
assert(m);
if (!m->current_dns_server) {
m->current_dns_server = m->dns_servers;
return;
}
if (!m->current_dns_server)
return;
if (m->current_dns_server->servers_next) {
m->current_dns_server = m->current_dns_server->servers_next;
return;
}
m->current_dns_server = m->dns_servers;
}