resolved-manager.c revision 9176a57c101d51b4a7fb4141240b5ce03abac57d
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering/***
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering This file is part of systemd.
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering Copyright 2014 Tom Gundersen <teg@jklm.no>
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering systemd is free software; you can redistribute it and/or modify it
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering under the terms of the GNU Lesser General Public License as published by
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering the Free Software Foundation; either version 2.1 of the License, or
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering (at your option) any later version.
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering systemd is distributed in the hope that it will be useful, but
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering WITHOUT ANY WARRANTY; without even the implied warranty of
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering Lesser General Public License for more details.
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering You should have received a copy of the GNU Lesser General Public License
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering along with systemd; If not, see <http://www.gnu.org/licenses/>.
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering ***/
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering
0dae31d468b1a0e22d98921f7b0dbd92fd217167Zbigniew Jędrzejewski-Szmek#include <netinet/in.h>
0dae31d468b1a0e22d98921f7b0dbd92fd217167Zbigniew Jędrzejewski-Szmek#include <poll.h>
2e276efc7b0398a3086629a52970bdd4ab7252f9Zbigniew Jędrzejewski-Szmek#include <sys/ioctl.h>
2e276efc7b0398a3086629a52970bdd4ab7252f9Zbigniew Jędrzejewski-Szmek
322345fdb9865ef2477fba8e4bdde0e1183ef505Lennart Poettering#include "af-list.h"
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering#include "alloc-util.h"
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering#include "dns-domain.h"
faa133f3aa7a18f26563dc5d6b95898cb315c37aLennart Poettering#include "fd-util.h"
faa133f3aa7a18f26563dc5d6b95898cb315c37aLennart Poettering#include "fileio-label.h"
faa133f3aa7a18f26563dc5d6b95898cb315c37aLennart Poettering#include "hostname-util.h"
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering#include "io-util.h"
faa133f3aa7a18f26563dc5d6b95898cb315c37aLennart Poettering#include "netlink-util.h"
faa133f3aa7a18f26563dc5d6b95898cb315c37aLennart Poettering#include "network-internal.h"
faa133f3aa7a18f26563dc5d6b95898cb315c37aLennart Poettering#include "ordered-set.h"
faa133f3aa7a18f26563dc5d6b95898cb315c37aLennart Poettering#include "parse-util.h"
faa133f3aa7a18f26563dc5d6b95898cb315c37aLennart Poettering#include "random-util.h"
faa133f3aa7a18f26563dc5d6b95898cb315c37aLennart Poettering#include "resolved-bus.h"
faa133f3aa7a18f26563dc5d6b95898cb315c37aLennart Poettering#include "resolved-conf.h"
faa133f3aa7a18f26563dc5d6b95898cb315c37aLennart Poettering#include "resolved-llmnr.h"
faa133f3aa7a18f26563dc5d6b95898cb315c37aLennart Poettering#include "resolved-manager.h"
faa133f3aa7a18f26563dc5d6b95898cb315c37aLennart Poettering#include "resolved-resolv-conf.h"
faa133f3aa7a18f26563dc5d6b95898cb315c37aLennart Poettering#include "socket-util.h"
faa133f3aa7a18f26563dc5d6b95898cb315c37aLennart Poettering#include "string-table.h"
faa133f3aa7a18f26563dc5d6b95898cb315c37aLennart Poettering#include "string-util.h"
faa133f3aa7a18f26563dc5d6b95898cb315c37aLennart Poettering#include "utf8.h"
faa133f3aa7a18f26563dc5d6b95898cb315c37aLennart Poettering
faa133f3aa7a18f26563dc5d6b95898cb315c37aLennart Poettering#define SEND_TIMEOUT_USEC (200 * USEC_PER_MSEC)
faa133f3aa7a18f26563dc5d6b95898cb315c37aLennart Poettering
faa133f3aa7a18f26563dc5d6b95898cb315c37aLennart Poetteringstatic int manager_process_link(sd_netlink *rtnl, sd_netlink_message *mm, void *userdata) {
faa133f3aa7a18f26563dc5d6b95898cb315c37aLennart Poettering Manager *m = userdata;
faa133f3aa7a18f26563dc5d6b95898cb315c37aLennart Poettering uint16_t type;
faa133f3aa7a18f26563dc5d6b95898cb315c37aLennart Poettering Link *l;
faa133f3aa7a18f26563dc5d6b95898cb315c37aLennart Poettering int ifindex, r;
faa133f3aa7a18f26563dc5d6b95898cb315c37aLennart Poettering
faa133f3aa7a18f26563dc5d6b95898cb315c37aLennart Poettering assert(rtnl);
faa133f3aa7a18f26563dc5d6b95898cb315c37aLennart Poettering assert(m);
faa133f3aa7a18f26563dc5d6b95898cb315c37aLennart Poettering assert(mm);
faa133f3aa7a18f26563dc5d6b95898cb315c37aLennart Poettering
faa133f3aa7a18f26563dc5d6b95898cb315c37aLennart Poettering r = sd_netlink_message_get_type(mm, &type);
faa133f3aa7a18f26563dc5d6b95898cb315c37aLennart Poettering if (r < 0)
faa133f3aa7a18f26563dc5d6b95898cb315c37aLennart Poettering goto fail;
faa133f3aa7a18f26563dc5d6b95898cb315c37aLennart Poettering
faa133f3aa7a18f26563dc5d6b95898cb315c37aLennart Poettering r = sd_rtnl_message_link_get_ifindex(mm, &ifindex);
faa133f3aa7a18f26563dc5d6b95898cb315c37aLennart Poettering if (r < 0)
faa133f3aa7a18f26563dc5d6b95898cb315c37aLennart Poettering goto fail;
faa133f3aa7a18f26563dc5d6b95898cb315c37aLennart Poettering
faa133f3aa7a18f26563dc5d6b95898cb315c37aLennart Poettering l = hashmap_get(m->links, INT_TO_PTR(ifindex));
faa133f3aa7a18f26563dc5d6b95898cb315c37aLennart Poettering
faa133f3aa7a18f26563dc5d6b95898cb315c37aLennart Poettering switch (type) {
faa133f3aa7a18f26563dc5d6b95898cb315c37aLennart Poettering
faa133f3aa7a18f26563dc5d6b95898cb315c37aLennart Poettering case RTM_NEWLINK:{
faa133f3aa7a18f26563dc5d6b95898cb315c37aLennart Poettering bool is_new = !l;
faa133f3aa7a18f26563dc5d6b95898cb315c37aLennart Poettering
faa133f3aa7a18f26563dc5d6b95898cb315c37aLennart Poettering if (!l) {
faa133f3aa7a18f26563dc5d6b95898cb315c37aLennart Poettering r = link_new(m, &l, ifindex);
faa133f3aa7a18f26563dc5d6b95898cb315c37aLennart Poettering if (r < 0)
faa133f3aa7a18f26563dc5d6b95898cb315c37aLennart Poettering goto fail;
faa133f3aa7a18f26563dc5d6b95898cb315c37aLennart Poettering }
faa133f3aa7a18f26563dc5d6b95898cb315c37aLennart Poettering
faa133f3aa7a18f26563dc5d6b95898cb315c37aLennart Poettering r = link_update_rtnl(l, mm);
faa133f3aa7a18f26563dc5d6b95898cb315c37aLennart Poettering if (r < 0)
faa133f3aa7a18f26563dc5d6b95898cb315c37aLennart Poettering goto fail;
faa133f3aa7a18f26563dc5d6b95898cb315c37aLennart Poettering
faa133f3aa7a18f26563dc5d6b95898cb315c37aLennart Poettering r = link_update_monitor(l);
faa133f3aa7a18f26563dc5d6b95898cb315c37aLennart Poettering if (r < 0)
faa133f3aa7a18f26563dc5d6b95898cb315c37aLennart Poettering goto fail;
faa133f3aa7a18f26563dc5d6b95898cb315c37aLennart Poettering
faa133f3aa7a18f26563dc5d6b95898cb315c37aLennart Poettering if (is_new)
faa133f3aa7a18f26563dc5d6b95898cb315c37aLennart Poettering log_debug("Found new link %i/%s", ifindex, l->name);
faa133f3aa7a18f26563dc5d6b95898cb315c37aLennart Poettering
faa133f3aa7a18f26563dc5d6b95898cb315c37aLennart Poettering break;
faa133f3aa7a18f26563dc5d6b95898cb315c37aLennart Poettering }
faa133f3aa7a18f26563dc5d6b95898cb315c37aLennart Poettering
faa133f3aa7a18f26563dc5d6b95898cb315c37aLennart Poettering case RTM_DELLINK:
faa133f3aa7a18f26563dc5d6b95898cb315c37aLennart Poettering if (l) {
faa133f3aa7a18f26563dc5d6b95898cb315c37aLennart Poettering log_debug("Removing link %i/%s", l->ifindex, l->name);
faa133f3aa7a18f26563dc5d6b95898cb315c37aLennart Poettering link_free(l);
faa133f3aa7a18f26563dc5d6b95898cb315c37aLennart Poettering }
faa133f3aa7a18f26563dc5d6b95898cb315c37aLennart Poettering
faa133f3aa7a18f26563dc5d6b95898cb315c37aLennart Poettering break;
faa133f3aa7a18f26563dc5d6b95898cb315c37aLennart Poettering }
faa133f3aa7a18f26563dc5d6b95898cb315c37aLennart Poettering
faa133f3aa7a18f26563dc5d6b95898cb315c37aLennart Poettering return 0;
faa133f3aa7a18f26563dc5d6b95898cb315c37aLennart Poettering
faa133f3aa7a18f26563dc5d6b95898cb315c37aLennart Poetteringfail:
faa133f3aa7a18f26563dc5d6b95898cb315c37aLennart Poettering log_warning_errno(r, "Failed to process RTNL link message: %m");
faa133f3aa7a18f26563dc5d6b95898cb315c37aLennart Poettering return 0;
faa133f3aa7a18f26563dc5d6b95898cb315c37aLennart Poettering}
faa133f3aa7a18f26563dc5d6b95898cb315c37aLennart Poettering
faa133f3aa7a18f26563dc5d6b95898cb315c37aLennart Poetteringstatic int manager_process_address(sd_netlink *rtnl, sd_netlink_message *mm, void *userdata) {
faa133f3aa7a18f26563dc5d6b95898cb315c37aLennart Poettering Manager *m = userdata;
faa133f3aa7a18f26563dc5d6b95898cb315c37aLennart Poettering union in_addr_union address;
faa133f3aa7a18f26563dc5d6b95898cb315c37aLennart Poettering uint16_t type;
faa133f3aa7a18f26563dc5d6b95898cb315c37aLennart Poettering int r, ifindex, family;
faa133f3aa7a18f26563dc5d6b95898cb315c37aLennart Poettering LinkAddress *a;
faa133f3aa7a18f26563dc5d6b95898cb315c37aLennart Poettering Link *l;
faa133f3aa7a18f26563dc5d6b95898cb315c37aLennart Poettering
faa133f3aa7a18f26563dc5d6b95898cb315c37aLennart Poettering assert(rtnl);
faa133f3aa7a18f26563dc5d6b95898cb315c37aLennart Poettering assert(mm);
faa133f3aa7a18f26563dc5d6b95898cb315c37aLennart Poettering assert(m);
faa133f3aa7a18f26563dc5d6b95898cb315c37aLennart Poettering
faa133f3aa7a18f26563dc5d6b95898cb315c37aLennart Poettering r = sd_netlink_message_get_type(mm, &type);
faa133f3aa7a18f26563dc5d6b95898cb315c37aLennart Poettering if (r < 0)
faa133f3aa7a18f26563dc5d6b95898cb315c37aLennart Poettering goto fail;
faa133f3aa7a18f26563dc5d6b95898cb315c37aLennart Poettering
faa133f3aa7a18f26563dc5d6b95898cb315c37aLennart Poettering r = sd_rtnl_message_addr_get_ifindex(mm, &ifindex);
faa133f3aa7a18f26563dc5d6b95898cb315c37aLennart Poettering if (r < 0)
faa133f3aa7a18f26563dc5d6b95898cb315c37aLennart Poettering goto fail;
faa133f3aa7a18f26563dc5d6b95898cb315c37aLennart Poettering
faa133f3aa7a18f26563dc5d6b95898cb315c37aLennart Poettering l = hashmap_get(m->links, INT_TO_PTR(ifindex));
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering if (!l)
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering return 0;
322345fdb9865ef2477fba8e4bdde0e1183ef505Lennart Poettering
322345fdb9865ef2477fba8e4bdde0e1183ef505Lennart Poettering r = sd_rtnl_message_addr_get_family(mm, &family);
322345fdb9865ef2477fba8e4bdde0e1183ef505Lennart Poettering if (r < 0)
322345fdb9865ef2477fba8e4bdde0e1183ef505Lennart Poettering goto fail;
faa133f3aa7a18f26563dc5d6b95898cb315c37aLennart Poettering
322345fdb9865ef2477fba8e4bdde0e1183ef505Lennart Poettering switch (family) {
322345fdb9865ef2477fba8e4bdde0e1183ef505Lennart Poettering
322345fdb9865ef2477fba8e4bdde0e1183ef505Lennart Poettering case AF_INET:
322345fdb9865ef2477fba8e4bdde0e1183ef505Lennart Poettering r = sd_netlink_message_read_in_addr(mm, IFA_LOCAL, &address.in);
322345fdb9865ef2477fba8e4bdde0e1183ef505Lennart Poettering if (r < 0) {
322345fdb9865ef2477fba8e4bdde0e1183ef505Lennart Poettering r = sd_netlink_message_read_in_addr(mm, IFA_ADDRESS, &address.in);
322345fdb9865ef2477fba8e4bdde0e1183ef505Lennart Poettering if (r < 0)
322345fdb9865ef2477fba8e4bdde0e1183ef505Lennart Poettering goto fail;
322345fdb9865ef2477fba8e4bdde0e1183ef505Lennart Poettering }
322345fdb9865ef2477fba8e4bdde0e1183ef505Lennart Poettering
faa133f3aa7a18f26563dc5d6b95898cb315c37aLennart Poettering break;
322345fdb9865ef2477fba8e4bdde0e1183ef505Lennart Poettering
322345fdb9865ef2477fba8e4bdde0e1183ef505Lennart Poettering case AF_INET6:
322345fdb9865ef2477fba8e4bdde0e1183ef505Lennart Poettering r = sd_netlink_message_read_in6_addr(mm, IFA_LOCAL, &address.in6);
322345fdb9865ef2477fba8e4bdde0e1183ef505Lennart Poettering if (r < 0) {
322345fdb9865ef2477fba8e4bdde0e1183ef505Lennart Poettering r = sd_netlink_message_read_in6_addr(mm, IFA_ADDRESS, &address.in6);
322345fdb9865ef2477fba8e4bdde0e1183ef505Lennart Poettering if (r < 0)
322345fdb9865ef2477fba8e4bdde0e1183ef505Lennart Poettering goto fail;
322345fdb9865ef2477fba8e4bdde0e1183ef505Lennart Poettering }
322345fdb9865ef2477fba8e4bdde0e1183ef505Lennart Poettering
322345fdb9865ef2477fba8e4bdde0e1183ef505Lennart Poettering break;
322345fdb9865ef2477fba8e4bdde0e1183ef505Lennart Poettering
322345fdb9865ef2477fba8e4bdde0e1183ef505Lennart Poettering default:
322345fdb9865ef2477fba8e4bdde0e1183ef505Lennart Poettering return 0;
322345fdb9865ef2477fba8e4bdde0e1183ef505Lennart Poettering }
322345fdb9865ef2477fba8e4bdde0e1183ef505Lennart Poettering
322345fdb9865ef2477fba8e4bdde0e1183ef505Lennart Poettering a = link_find_address(l, family, &address);
2d4c5cbc0ed3ccb09dc086a040088b454c22c644Lennart Poettering
2d4c5cbc0ed3ccb09dc086a040088b454c22c644Lennart Poettering switch (type) {
2d4c5cbc0ed3ccb09dc086a040088b454c22c644Lennart Poettering
2d4c5cbc0ed3ccb09dc086a040088b454c22c644Lennart Poettering case RTM_NEWADDR:
2d4c5cbc0ed3ccb09dc086a040088b454c22c644Lennart Poettering
2d4c5cbc0ed3ccb09dc086a040088b454c22c644Lennart Poettering if (!a) {
2d4c5cbc0ed3ccb09dc086a040088b454c22c644Lennart Poettering r = link_address_new(l, &a, family, &address);
2d4c5cbc0ed3ccb09dc086a040088b454c22c644Lennart Poettering if (r < 0)
2d4c5cbc0ed3ccb09dc086a040088b454c22c644Lennart Poettering return r;
2d4c5cbc0ed3ccb09dc086a040088b454c22c644Lennart Poettering }
2d4c5cbc0ed3ccb09dc086a040088b454c22c644Lennart Poettering
2d4c5cbc0ed3ccb09dc086a040088b454c22c644Lennart Poettering r = link_address_update_rtnl(a, mm);
2d4c5cbc0ed3ccb09dc086a040088b454c22c644Lennart Poettering if (r < 0)
2d4c5cbc0ed3ccb09dc086a040088b454c22c644Lennart Poettering return r;
2d4c5cbc0ed3ccb09dc086a040088b454c22c644Lennart Poettering
2d4c5cbc0ed3ccb09dc086a040088b454c22c644Lennart Poettering break;
2d4c5cbc0ed3ccb09dc086a040088b454c22c644Lennart Poettering
2d4c5cbc0ed3ccb09dc086a040088b454c22c644Lennart Poettering case RTM_DELADDR:
2d4c5cbc0ed3ccb09dc086a040088b454c22c644Lennart Poettering link_address_free(a);
2d4c5cbc0ed3ccb09dc086a040088b454c22c644Lennart Poettering break;
2d4c5cbc0ed3ccb09dc086a040088b454c22c644Lennart Poettering }
2d4c5cbc0ed3ccb09dc086a040088b454c22c644Lennart Poettering
2d4c5cbc0ed3ccb09dc086a040088b454c22c644Lennart Poettering return 0;
2d4c5cbc0ed3ccb09dc086a040088b454c22c644Lennart Poettering
2d4c5cbc0ed3ccb09dc086a040088b454c22c644Lennart Poetteringfail:
faa133f3aa7a18f26563dc5d6b95898cb315c37aLennart Poettering log_warning_errno(r, "Failed to process RTNL address message: %m");
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering return 0;
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering}
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poetteringstatic int manager_rtnl_listen(Manager *m) {
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering _cleanup_netlink_message_unref_ sd_netlink_message *req = NULL, *reply = NULL;
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering sd_netlink_message *i;
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering int r;
faa133f3aa7a18f26563dc5d6b95898cb315c37aLennart Poettering
faa133f3aa7a18f26563dc5d6b95898cb315c37aLennart Poettering assert(m);
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering /* First, subscribe to interfaces coming and going */
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering r = sd_netlink_open(&m->rtnl);
8bf52d3d17d364438191077d0750b8b80b5dc53aLennart Poettering if (r < 0)
8bf52d3d17d364438191077d0750b8b80b5dc53aLennart Poettering return r;
8bf52d3d17d364438191077d0750b8b80b5dc53aLennart Poettering
8bf52d3d17d364438191077d0750b8b80b5dc53aLennart Poettering r = sd_netlink_attach_event(m->rtnl, m->event, 0);
8bf52d3d17d364438191077d0750b8b80b5dc53aLennart Poettering if (r < 0)
8bf52d3d17d364438191077d0750b8b80b5dc53aLennart Poettering return r;
8bf52d3d17d364438191077d0750b8b80b5dc53aLennart Poettering
8bf52d3d17d364438191077d0750b8b80b5dc53aLennart Poettering r = sd_netlink_add_match(m->rtnl, RTM_NEWLINK, manager_process_link, m);
8bf52d3d17d364438191077d0750b8b80b5dc53aLennart Poettering if (r < 0)
8bf52d3d17d364438191077d0750b8b80b5dc53aLennart Poettering return r;
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering r = sd_netlink_add_match(m->rtnl, RTM_DELLINK, manager_process_link, m);
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering if (r < 0)
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering return r;
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering r = sd_netlink_add_match(m->rtnl, RTM_NEWADDR, manager_process_address, m);
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering if (r < 0)
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering return r;
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering r = sd_netlink_add_match(m->rtnl, RTM_DELADDR, manager_process_address, m);
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering if (r < 0)
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering return r;
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering /* Then, enumerate all links */
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering r = sd_rtnl_message_new_link(m->rtnl, &req, RTM_GETLINK, 0);
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering if (r < 0)
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering return r;
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering r = sd_netlink_message_request_dump(req, true);
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering if (r < 0)
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering return r;
faa133f3aa7a18f26563dc5d6b95898cb315c37aLennart Poettering
9de3e3294065e8697ff10130b53f274319cdcf6fZbigniew Jędrzejewski-Szmek r = sd_netlink_call(m->rtnl, req, 0, &reply);
9c92ce6d67f88beb31dd6555d12ae3f632218a39Lennart Poettering if (r < 0)
9c92ce6d67f88beb31dd6555d12ae3f632218a39Lennart Poettering return r;
9c92ce6d67f88beb31dd6555d12ae3f632218a39Lennart Poettering
9c92ce6d67f88beb31dd6555d12ae3f632218a39Lennart Poettering for (i = reply; i; i = sd_netlink_message_next(i)) {
9c92ce6d67f88beb31dd6555d12ae3f632218a39Lennart Poettering r = manager_process_link(m->rtnl, i, m);
9de3e3294065e8697ff10130b53f274319cdcf6fZbigniew Jędrzejewski-Szmek if (r < 0)
9de3e3294065e8697ff10130b53f274319cdcf6fZbigniew Jędrzejewski-Szmek return r;
9de3e3294065e8697ff10130b53f274319cdcf6fZbigniew Jędrzejewski-Szmek }
8ac4e9e1e54397f6d1745c2a7a806132418c7da2Lennart Poettering
faa133f3aa7a18f26563dc5d6b95898cb315c37aLennart Poettering req = sd_netlink_message_unref(req);
9de3e3294065e8697ff10130b53f274319cdcf6fZbigniew Jędrzejewski-Szmek reply = sd_netlink_message_unref(reply);
9c92ce6d67f88beb31dd6555d12ae3f632218a39Lennart Poettering
9de3e3294065e8697ff10130b53f274319cdcf6fZbigniew Jędrzejewski-Szmek /* Finally, enumerate all addresses, too */
faa133f3aa7a18f26563dc5d6b95898cb315c37aLennart Poettering r = sd_rtnl_message_new_addr(m->rtnl, &req, RTM_GETADDR, 0, AF_UNSPEC);
faa133f3aa7a18f26563dc5d6b95898cb315c37aLennart Poettering if (r < 0)
9de3e3294065e8697ff10130b53f274319cdcf6fZbigniew Jędrzejewski-Szmek return r;
9c92ce6d67f88beb31dd6555d12ae3f632218a39Lennart Poettering
9de3e3294065e8697ff10130b53f274319cdcf6fZbigniew Jędrzejewski-Szmek r = sd_netlink_message_request_dump(req, true);
9c92ce6d67f88beb31dd6555d12ae3f632218a39Lennart Poettering if (r < 0)
2e276efc7b0398a3086629a52970bdd4ab7252f9Zbigniew Jędrzejewski-Szmek return r;
9de3e3294065e8697ff10130b53f274319cdcf6fZbigniew Jędrzejewski-Szmek
9c92ce6d67f88beb31dd6555d12ae3f632218a39Lennart Poettering r = sd_netlink_call(m->rtnl, req, 0, &reply);
9de3e3294065e8697ff10130b53f274319cdcf6fZbigniew Jędrzejewski-Szmek if (r < 0)
7e8e0422aeb16f2a09a40546c61df753d10029b6Lennart Poettering return r;
7e8e0422aeb16f2a09a40546c61df753d10029b6Lennart Poettering
9de3e3294065e8697ff10130b53f274319cdcf6fZbigniew Jędrzejewski-Szmek for (i = reply; i; i = sd_netlink_message_next(i)) {
9c92ce6d67f88beb31dd6555d12ae3f632218a39Lennart Poettering r = manager_process_address(m->rtnl, i, m);
9de3e3294065e8697ff10130b53f274319cdcf6fZbigniew Jędrzejewski-Szmek if (r < 0)
946c70944ebdf428ffeb9991a7449edbd4011461Zbigniew Jędrzejewski-Szmek return r;
9de3e3294065e8697ff10130b53f274319cdcf6fZbigniew Jędrzejewski-Szmek }
9c92ce6d67f88beb31dd6555d12ae3f632218a39Lennart Poettering
42cc2eebb01056beb7acd3ecfe8e533558237f84Lennart Poettering return r;
42cc2eebb01056beb7acd3ecfe8e533558237f84Lennart Poettering}
42cc2eebb01056beb7acd3ecfe8e533558237f84Lennart Poettering
42cc2eebb01056beb7acd3ecfe8e533558237f84Lennart Poetteringstatic int on_network_event(sd_event_source *s, int fd, uint32_t revents, void *userdata) {
0dae31d468b1a0e22d98921f7b0dbd92fd217167Zbigniew Jędrzejewski-Szmek Manager *m = userdata;
9de3e3294065e8697ff10130b53f274319cdcf6fZbigniew Jędrzejewski-Szmek Iterator i;
9de3e3294065e8697ff10130b53f274319cdcf6fZbigniew Jędrzejewski-Szmek Link *l;
9de3e3294065e8697ff10130b53f274319cdcf6fZbigniew Jędrzejewski-Szmek int r;
9c92ce6d67f88beb31dd6555d12ae3f632218a39Lennart Poettering
9de3e3294065e8697ff10130b53f274319cdcf6fZbigniew Jędrzejewski-Szmek assert(m);
faa133f3aa7a18f26563dc5d6b95898cb315c37aLennart Poettering
9de3e3294065e8697ff10130b53f274319cdcf6fZbigniew Jędrzejewski-Szmek sd_network_monitor_flush(m->network_monitor);
322345fdb9865ef2477fba8e4bdde0e1183ef505Lennart Poettering
faa133f3aa7a18f26563dc5d6b95898cb315c37aLennart Poettering HASHMAP_FOREACH(l, m->links, i) {
faa133f3aa7a18f26563dc5d6b95898cb315c37aLennart Poettering r = link_update_monitor(l);
322345fdb9865ef2477fba8e4bdde0e1183ef505Lennart Poettering if (r < 0)
faa133f3aa7a18f26563dc5d6b95898cb315c37aLennart Poettering log_warning_errno(r, "Failed to update monitor information for %i: %m", l->ifindex);
322345fdb9865ef2477fba8e4bdde0e1183ef505Lennart Poettering }
322345fdb9865ef2477fba8e4bdde0e1183ef505Lennart Poettering
322345fdb9865ef2477fba8e4bdde0e1183ef505Lennart Poettering r = manager_write_resolv_conf(m);
322345fdb9865ef2477fba8e4bdde0e1183ef505Lennart Poettering if (r < 0)
623a4c97b9175f95c4b1c6fc34e36c56f1e4ddbfLennart Poettering log_warning_errno(r, "Could not update resolv.conf: %m");
623a4c97b9175f95c4b1c6fc34e36c56f1e4ddbfLennart Poettering
623a4c97b9175f95c4b1c6fc34e36c56f1e4ddbfLennart Poettering return 0;
623a4c97b9175f95c4b1c6fc34e36c56f1e4ddbfLennart Poettering}
623a4c97b9175f95c4b1c6fc34e36c56f1e4ddbfLennart Poettering
623a4c97b9175f95c4b1c6fc34e36c56f1e4ddbfLennart Poetteringstatic int manager_network_monitor_listen(Manager *m) {
623a4c97b9175f95c4b1c6fc34e36c56f1e4ddbfLennart Poettering int r, fd, events;
623a4c97b9175f95c4b1c6fc34e36c56f1e4ddbfLennart Poettering
623a4c97b9175f95c4b1c6fc34e36c56f1e4ddbfLennart Poettering assert(m);
623a4c97b9175f95c4b1c6fc34e36c56f1e4ddbfLennart Poettering
623a4c97b9175f95c4b1c6fc34e36c56f1e4ddbfLennart Poettering r = sd_network_monitor_new(&m->network_monitor, NULL);
623a4c97b9175f95c4b1c6fc34e36c56f1e4ddbfLennart Poettering if (r < 0)
623a4c97b9175f95c4b1c6fc34e36c56f1e4ddbfLennart Poettering return r;
623a4c97b9175f95c4b1c6fc34e36c56f1e4ddbfLennart Poettering
623a4c97b9175f95c4b1c6fc34e36c56f1e4ddbfLennart Poettering fd = sd_network_monitor_get_fd(m->network_monitor);
623a4c97b9175f95c4b1c6fc34e36c56f1e4ddbfLennart Poettering if (fd < 0)
623a4c97b9175f95c4b1c6fc34e36c56f1e4ddbfLennart Poettering return fd;
623a4c97b9175f95c4b1c6fc34e36c56f1e4ddbfLennart Poettering
623a4c97b9175f95c4b1c6fc34e36c56f1e4ddbfLennart Poettering events = sd_network_monitor_get_events(m->network_monitor);
623a4c97b9175f95c4b1c6fc34e36c56f1e4ddbfLennart Poettering if (events < 0)
623a4c97b9175f95c4b1c6fc34e36c56f1e4ddbfLennart Poettering return events;
623a4c97b9175f95c4b1c6fc34e36c56f1e4ddbfLennart Poettering
623a4c97b9175f95c4b1c6fc34e36c56f1e4ddbfLennart Poettering r = sd_event_add_io(m->event, &m->network_event_source, fd, events, &on_network_event, m);
623a4c97b9175f95c4b1c6fc34e36c56f1e4ddbfLennart Poettering if (r < 0)
623a4c97b9175f95c4b1c6fc34e36c56f1e4ddbfLennart Poettering return r;
623a4c97b9175f95c4b1c6fc34e36c56f1e4ddbfLennart Poettering
623a4c97b9175f95c4b1c6fc34e36c56f1e4ddbfLennart Poettering return 0;
623a4c97b9175f95c4b1c6fc34e36c56f1e4ddbfLennart Poettering}
623a4c97b9175f95c4b1c6fc34e36c56f1e4ddbfLennart Poettering
623a4c97b9175f95c4b1c6fc34e36c56f1e4ddbfLennart Poetteringstatic int determine_hostname(char **llmnr_hostname, char **mdns_hostname) {
623a4c97b9175f95c4b1c6fc34e36c56f1e4ddbfLennart Poettering _cleanup_free_ char *h = NULL, *n = NULL;
623a4c97b9175f95c4b1c6fc34e36c56f1e4ddbfLennart Poettering char label[DNS_LABEL_MAX];
623a4c97b9175f95c4b1c6fc34e36c56f1e4ddbfLennart Poettering const char *p;
623a4c97b9175f95c4b1c6fc34e36c56f1e4ddbfLennart Poettering int r, k;
322345fdb9865ef2477fba8e4bdde0e1183ef505Lennart Poettering
322345fdb9865ef2477fba8e4bdde0e1183ef505Lennart Poettering assert(llmnr_hostname);
322345fdb9865ef2477fba8e4bdde0e1183ef505Lennart Poettering assert(mdns_hostname);
322345fdb9865ef2477fba8e4bdde0e1183ef505Lennart Poettering
322345fdb9865ef2477fba8e4bdde0e1183ef505Lennart Poettering /* Extract and normalize the first label of the locally
322345fdb9865ef2477fba8e4bdde0e1183ef505Lennart Poettering * configured hostname, and check it's not "localhost". */
faa133f3aa7a18f26563dc5d6b95898cb315c37aLennart Poettering
322345fdb9865ef2477fba8e4bdde0e1183ef505Lennart Poettering h = gethostname_malloc();
322345fdb9865ef2477fba8e4bdde0e1183ef505Lennart Poettering if (!h)
322345fdb9865ef2477fba8e4bdde0e1183ef505Lennart Poettering return log_oom();
fd0b4602f6332c3f1660eb208c8f5c719709a009Lennart Poettering
fd0b4602f6332c3f1660eb208c8f5c719709a009Lennart Poettering p = h;
fd0b4602f6332c3f1660eb208c8f5c719709a009Lennart Poettering r = dns_label_unescape(&p, label, sizeof(label));
fd0b4602f6332c3f1660eb208c8f5c719709a009Lennart Poettering if (r < 0)
2d4c5cbc0ed3ccb09dc086a040088b454c22c644Lennart Poettering return log_error_errno(r, "Failed to unescape host name: %m");
9c92ce6d67f88beb31dd6555d12ae3f632218a39Lennart Poettering if (r == 0) {
9c92ce6d67f88beb31dd6555d12ae3f632218a39Lennart Poettering log_error("Couldn't find a single label in hosntame.");
9c92ce6d67f88beb31dd6555d12ae3f632218a39Lennart Poettering return -EINVAL;
9c92ce6d67f88beb31dd6555d12ae3f632218a39Lennart Poettering }
9c92ce6d67f88beb31dd6555d12ae3f632218a39Lennart Poettering
9c92ce6d67f88beb31dd6555d12ae3f632218a39Lennart Poettering k = dns_label_undo_idna(label, r, label, sizeof(label));
9c92ce6d67f88beb31dd6555d12ae3f632218a39Lennart Poettering if (k < 0)
9c92ce6d67f88beb31dd6555d12ae3f632218a39Lennart Poettering return log_error_errno(k, "Failed to undo IDNA: %m");
9c92ce6d67f88beb31dd6555d12ae3f632218a39Lennart Poettering if (k > 0)
2d4c5cbc0ed3ccb09dc086a040088b454c22c644Lennart Poettering r = k;
2d4c5cbc0ed3ccb09dc086a040088b454c22c644Lennart Poettering
2d4c5cbc0ed3ccb09dc086a040088b454c22c644Lennart Poettering if (!utf8_is_valid(label)) {
8ac4e9e1e54397f6d1745c2a7a806132418c7da2Lennart Poettering log_error("System hostname is not UTF-8 clean.");
322345fdb9865ef2477fba8e4bdde0e1183ef505Lennart Poettering return -EINVAL;
2d4c5cbc0ed3ccb09dc086a040088b454c22c644Lennart Poettering }
2d4c5cbc0ed3ccb09dc086a040088b454c22c644Lennart Poettering
2d4c5cbc0ed3ccb09dc086a040088b454c22c644Lennart Poettering r = dns_label_escape(label, r, &n);
2d4c5cbc0ed3ccb09dc086a040088b454c22c644Lennart Poettering if (r < 0)
2d4c5cbc0ed3ccb09dc086a040088b454c22c644Lennart Poettering return log_error_errno(r, "Failed to escape host name: %m");
9de3e3294065e8697ff10130b53f274319cdcf6fZbigniew Jędrzejewski-Szmek
2e276efc7b0398a3086629a52970bdd4ab7252f9Zbigniew Jędrzejewski-Szmek if (is_localhost(n)) {
2e276efc7b0398a3086629a52970bdd4ab7252f9Zbigniew Jędrzejewski-Szmek log_debug("System hostname is 'localhost', ignoring.");
2e276efc7b0398a3086629a52970bdd4ab7252f9Zbigniew Jędrzejewski-Szmek return -EINVAL;
2e276efc7b0398a3086629a52970bdd4ab7252f9Zbigniew Jędrzejewski-Szmek }
2e276efc7b0398a3086629a52970bdd4ab7252f9Zbigniew Jędrzejewski-Szmek
2e276efc7b0398a3086629a52970bdd4ab7252f9Zbigniew Jędrzejewski-Szmek r = dns_name_concat(n, "local", mdns_hostname);
2e276efc7b0398a3086629a52970bdd4ab7252f9Zbigniew Jędrzejewski-Szmek if (r < 0)
2e276efc7b0398a3086629a52970bdd4ab7252f9Zbigniew Jędrzejewski-Szmek return log_error_errno(r, "Failed to determine mDNS hostname: %m");
2e276efc7b0398a3086629a52970bdd4ab7252f9Zbigniew Jędrzejewski-Szmek
2d4c5cbc0ed3ccb09dc086a040088b454c22c644Lennart Poettering *llmnr_hostname = n;
322345fdb9865ef2477fba8e4bdde0e1183ef505Lennart Poettering n = NULL;
2d4c5cbc0ed3ccb09dc086a040088b454c22c644Lennart Poettering
2d4c5cbc0ed3ccb09dc086a040088b454c22c644Lennart Poettering return 0;
322345fdb9865ef2477fba8e4bdde0e1183ef505Lennart Poettering}
2d4c5cbc0ed3ccb09dc086a040088b454c22c644Lennart Poettering
2d4c5cbc0ed3ccb09dc086a040088b454c22c644Lennart Poetteringstatic int on_hostname_change(sd_event_source *es, int fd, uint32_t revents, void *userdata) {
7e8e0422aeb16f2a09a40546c61df753d10029b6Lennart Poettering _cleanup_free_ char *llmnr_hostname = NULL, *mdns_hostname = NULL;
7e8e0422aeb16f2a09a40546c61df753d10029b6Lennart Poettering Manager *m = userdata;
7e8e0422aeb16f2a09a40546c61df753d10029b6Lennart Poettering int r;
7e8e0422aeb16f2a09a40546c61df753d10029b6Lennart Poettering
7e8e0422aeb16f2a09a40546c61df753d10029b6Lennart Poettering assert(m);
7e8e0422aeb16f2a09a40546c61df753d10029b6Lennart Poettering
7e8e0422aeb16f2a09a40546c61df753d10029b6Lennart Poettering r = determine_hostname(&llmnr_hostname, &mdns_hostname);
7e8e0422aeb16f2a09a40546c61df753d10029b6Lennart Poettering if (r < 0)
7e8e0422aeb16f2a09a40546c61df753d10029b6Lennart Poettering return 0; /* ignore invalid hostnames */
7e8e0422aeb16f2a09a40546c61df753d10029b6Lennart Poettering
7e8e0422aeb16f2a09a40546c61df753d10029b6Lennart Poettering if (streq(llmnr_hostname, m->llmnr_hostname) && streq(mdns_hostname, m->mdns_hostname))
7e8e0422aeb16f2a09a40546c61df753d10029b6Lennart Poettering return 0;
9c92ce6d67f88beb31dd6555d12ae3f632218a39Lennart Poettering
946c70944ebdf428ffeb9991a7449edbd4011461Zbigniew Jędrzejewski-Szmek log_info("System hostname changed to '%s'.", llmnr_hostname);
946c70944ebdf428ffeb9991a7449edbd4011461Zbigniew Jędrzejewski-Szmek
946c70944ebdf428ffeb9991a7449edbd4011461Zbigniew Jędrzejewski-Szmek free(m->llmnr_hostname);
946c70944ebdf428ffeb9991a7449edbd4011461Zbigniew Jędrzejewski-Szmek free(m->mdns_hostname);
946c70944ebdf428ffeb9991a7449edbd4011461Zbigniew Jędrzejewski-Szmek
946c70944ebdf428ffeb9991a7449edbd4011461Zbigniew Jędrzejewski-Szmek m->llmnr_hostname = llmnr_hostname;
0dae31d468b1a0e22d98921f7b0dbd92fd217167Zbigniew Jędrzejewski-Szmek m->mdns_hostname = mdns_hostname;
0dae31d468b1a0e22d98921f7b0dbd92fd217167Zbigniew Jędrzejewski-Szmek
0dae31d468b1a0e22d98921f7b0dbd92fd217167Zbigniew Jędrzejewski-Szmek llmnr_hostname = mdns_hostname = NULL;
0dae31d468b1a0e22d98921f7b0dbd92fd217167Zbigniew Jędrzejewski-Szmek
0dae31d468b1a0e22d98921f7b0dbd92fd217167Zbigniew Jędrzejewski-Szmek manager_refresh_rrs(m);
0dae31d468b1a0e22d98921f7b0dbd92fd217167Zbigniew Jędrzejewski-Szmek
0dae31d468b1a0e22d98921f7b0dbd92fd217167Zbigniew Jędrzejewski-Szmek return 0;
0dae31d468b1a0e22d98921f7b0dbd92fd217167Zbigniew Jędrzejewski-Szmek}
0dae31d468b1a0e22d98921f7b0dbd92fd217167Zbigniew Jędrzejewski-Szmek
0dae31d468b1a0e22d98921f7b0dbd92fd217167Zbigniew Jędrzejewski-Szmekstatic int manager_watch_hostname(Manager *m) {
42cc2eebb01056beb7acd3ecfe8e533558237f84Lennart Poettering int r;
42cc2eebb01056beb7acd3ecfe8e533558237f84Lennart Poettering
42cc2eebb01056beb7acd3ecfe8e533558237f84Lennart Poettering assert(m);
42cc2eebb01056beb7acd3ecfe8e533558237f84Lennart Poettering
42cc2eebb01056beb7acd3ecfe8e533558237f84Lennart Poettering m->hostname_fd = open("/proc/sys/kernel/hostname", O_RDONLY|O_CLOEXEC|O_NDELAY|O_NOCTTY);
42cc2eebb01056beb7acd3ecfe8e533558237f84Lennart Poettering if (m->hostname_fd < 0) {
2d4c5cbc0ed3ccb09dc086a040088b454c22c644Lennart Poettering log_warning_errno(errno, "Failed to watch hostname: %m");
322345fdb9865ef2477fba8e4bdde0e1183ef505Lennart Poettering return 0;
322345fdb9865ef2477fba8e4bdde0e1183ef505Lennart Poettering }
2d4c5cbc0ed3ccb09dc086a040088b454c22c644Lennart Poettering
322345fdb9865ef2477fba8e4bdde0e1183ef505Lennart Poettering r = sd_event_add_io(m->event, &m->hostname_event_source, m->hostname_fd, 0, on_hostname_change, m);
322345fdb9865ef2477fba8e4bdde0e1183ef505Lennart Poettering if (r < 0) {
0dae31d468b1a0e22d98921f7b0dbd92fd217167Zbigniew Jędrzejewski-Szmek if (r == -EPERM)
0dae31d468b1a0e22d98921f7b0dbd92fd217167Zbigniew Jędrzejewski-Szmek /* kernels prior to 3.2 don't support polling this file. Ignore the failure. */
0dae31d468b1a0e22d98921f7b0dbd92fd217167Zbigniew Jędrzejewski-Szmek m->hostname_fd = safe_close(m->hostname_fd);
0dae31d468b1a0e22d98921f7b0dbd92fd217167Zbigniew Jędrzejewski-Szmek else
0dae31d468b1a0e22d98921f7b0dbd92fd217167Zbigniew Jędrzejewski-Szmek return log_error_errno(r, "Failed to add hostname event source: %m");
0dae31d468b1a0e22d98921f7b0dbd92fd217167Zbigniew Jędrzejewski-Szmek }
0dae31d468b1a0e22d98921f7b0dbd92fd217167Zbigniew Jędrzejewski-Szmek
0dae31d468b1a0e22d98921f7b0dbd92fd217167Zbigniew Jędrzejewski-Szmek r = determine_hostname(&m->llmnr_hostname, &m->mdns_hostname);
0dae31d468b1a0e22d98921f7b0dbd92fd217167Zbigniew Jędrzejewski-Szmek if (r < 0) {
0dae31d468b1a0e22d98921f7b0dbd92fd217167Zbigniew Jędrzejewski-Szmek log_info("Defaulting to hostname 'linux'.");
0dae31d468b1a0e22d98921f7b0dbd92fd217167Zbigniew Jędrzejewski-Szmek m->llmnr_hostname = strdup("linux");
0dae31d468b1a0e22d98921f7b0dbd92fd217167Zbigniew Jędrzejewski-Szmek if (!m->llmnr_hostname)
0dae31d468b1a0e22d98921f7b0dbd92fd217167Zbigniew Jędrzejewski-Szmek return log_oom();
0dae31d468b1a0e22d98921f7b0dbd92fd217167Zbigniew Jędrzejewski-Szmek
0dae31d468b1a0e22d98921f7b0dbd92fd217167Zbigniew Jędrzejewski-Szmek m->mdns_hostname = strdup("linux.local");
0dae31d468b1a0e22d98921f7b0dbd92fd217167Zbigniew Jędrzejewski-Szmek if (!m->mdns_hostname)
0dae31d468b1a0e22d98921f7b0dbd92fd217167Zbigniew Jędrzejewski-Szmek return log_oom();
0dae31d468b1a0e22d98921f7b0dbd92fd217167Zbigniew Jędrzejewski-Szmek } else
0dae31d468b1a0e22d98921f7b0dbd92fd217167Zbigniew Jędrzejewski-Szmek log_info("Using system hostname '%s'.", m->llmnr_hostname);
0dae31d468b1a0e22d98921f7b0dbd92fd217167Zbigniew Jędrzejewski-Szmek
0dae31d468b1a0e22d98921f7b0dbd92fd217167Zbigniew Jędrzejewski-Szmek return 0;
0dae31d468b1a0e22d98921f7b0dbd92fd217167Zbigniew Jędrzejewski-Szmek}
0dae31d468b1a0e22d98921f7b0dbd92fd217167Zbigniew Jędrzejewski-Szmek
0dae31d468b1a0e22d98921f7b0dbd92fd217167Zbigniew Jędrzejewski-Szmekstatic int manager_sigusr1(sd_event_source *s, const struct signalfd_siginfo *si, void *userdata) {
0dae31d468b1a0e22d98921f7b0dbd92fd217167Zbigniew Jędrzejewski-Szmek _cleanup_free_ char *buffer = NULL;
0dae31d468b1a0e22d98921f7b0dbd92fd217167Zbigniew Jędrzejewski-Szmek _cleanup_fclose_ FILE *f = NULL;
0dae31d468b1a0e22d98921f7b0dbd92fd217167Zbigniew Jędrzejewski-Szmek Manager *m = userdata;
0dae31d468b1a0e22d98921f7b0dbd92fd217167Zbigniew Jędrzejewski-Szmek size_t size = 0;
0dae31d468b1a0e22d98921f7b0dbd92fd217167Zbigniew Jędrzejewski-Szmek DnsScope *scope;
0dae31d468b1a0e22d98921f7b0dbd92fd217167Zbigniew Jędrzejewski-Szmek
0dae31d468b1a0e22d98921f7b0dbd92fd217167Zbigniew Jędrzejewski-Szmek assert(s);
2d4c5cbc0ed3ccb09dc086a040088b454c22c644Lennart Poettering assert(si);
2d4c5cbc0ed3ccb09dc086a040088b454c22c644Lennart Poettering assert(m);
2d4c5cbc0ed3ccb09dc086a040088b454c22c644Lennart Poettering
2d4c5cbc0ed3ccb09dc086a040088b454c22c644Lennart Poettering f = open_memstream(&buffer, &size);
322345fdb9865ef2477fba8e4bdde0e1183ef505Lennart Poettering if (!f)
2d4c5cbc0ed3ccb09dc086a040088b454c22c644Lennart Poettering return log_oom();
322345fdb9865ef2477fba8e4bdde0e1183ef505Lennart Poettering
2d4c5cbc0ed3ccb09dc086a040088b454c22c644Lennart Poettering LIST_FOREACH(scopes, scope, m->dns_scopes)
2d4c5cbc0ed3ccb09dc086a040088b454c22c644Lennart Poettering dns_scope_dump(scope, f);
2d4c5cbc0ed3ccb09dc086a040088b454c22c644Lennart Poettering
322345fdb9865ef2477fba8e4bdde0e1183ef505Lennart Poettering if (fflush_and_check(f) < 0)
0dae31d468b1a0e22d98921f7b0dbd92fd217167Zbigniew Jędrzejewski-Szmek return log_oom();
322345fdb9865ef2477fba8e4bdde0e1183ef505Lennart Poettering
9c92ce6d67f88beb31dd6555d12ae3f632218a39Lennart Poettering log_dump(LOG_INFO, buffer);
9c92ce6d67f88beb31dd6555d12ae3f632218a39Lennart Poettering return 0;
9c92ce6d67f88beb31dd6555d12ae3f632218a39Lennart Poettering}
9c92ce6d67f88beb31dd6555d12ae3f632218a39Lennart Poettering
9c92ce6d67f88beb31dd6555d12ae3f632218a39Lennart Poetteringint manager_new(Manager **ret) {
9c92ce6d67f88beb31dd6555d12ae3f632218a39Lennart Poettering _cleanup_(manager_freep) Manager *m = NULL;
9c92ce6d67f88beb31dd6555d12ae3f632218a39Lennart Poettering int r;
9c92ce6d67f88beb31dd6555d12ae3f632218a39Lennart Poettering
9c92ce6d67f88beb31dd6555d12ae3f632218a39Lennart Poettering assert(ret);
9c92ce6d67f88beb31dd6555d12ae3f632218a39Lennart Poettering
9c92ce6d67f88beb31dd6555d12ae3f632218a39Lennart Poettering m = new0(Manager, 1);
2d4c5cbc0ed3ccb09dc086a040088b454c22c644Lennart Poettering if (!m)
2d4c5cbc0ed3ccb09dc086a040088b454c22c644Lennart Poettering return -ENOMEM;
2d4c5cbc0ed3ccb09dc086a040088b454c22c644Lennart Poettering
8ac4e9e1e54397f6d1745c2a7a806132418c7da2Lennart Poettering m->llmnr_ipv4_udp_fd = m->llmnr_ipv6_udp_fd = -1;
2d4c5cbc0ed3ccb09dc086a040088b454c22c644Lennart Poettering m->llmnr_ipv4_tcp_fd = m->llmnr_ipv6_tcp_fd = -1;
2d4c5cbc0ed3ccb09dc086a040088b454c22c644Lennart Poettering m->hostname_fd = -1;
2d4c5cbc0ed3ccb09dc086a040088b454c22c644Lennart Poettering
322345fdb9865ef2477fba8e4bdde0e1183ef505Lennart Poettering m->llmnr_support = SUPPORT_YES;
2d4c5cbc0ed3ccb09dc086a040088b454c22c644Lennart Poettering m->read_resolv_conf = true;
322345fdb9865ef2477fba8e4bdde0e1183ef505Lennart Poettering m->need_builtin_fallbacks = true;
2d4c5cbc0ed3ccb09dc086a040088b454c22c644Lennart Poettering
2d4c5cbc0ed3ccb09dc086a040088b454c22c644Lennart Poettering r = sd_event_default(&m->event);
2d4c5cbc0ed3ccb09dc086a040088b454c22c644Lennart Poettering if (r < 0)
2d4c5cbc0ed3ccb09dc086a040088b454c22c644Lennart Poettering return r;
2d4c5cbc0ed3ccb09dc086a040088b454c22c644Lennart Poettering
322345fdb9865ef2477fba8e4bdde0e1183ef505Lennart Poettering sd_event_add_signal(m->event, NULL, SIGTERM, NULL, NULL);
9de3e3294065e8697ff10130b53f274319cdcf6fZbigniew Jędrzejewski-Szmek sd_event_add_signal(m->event, NULL, SIGINT, NULL, NULL);
2e276efc7b0398a3086629a52970bdd4ab7252f9Zbigniew Jędrzejewski-Szmek
2e276efc7b0398a3086629a52970bdd4ab7252f9Zbigniew Jędrzejewski-Szmek sd_event_set_watchdog(m->event, true);
2e276efc7b0398a3086629a52970bdd4ab7252f9Zbigniew Jędrzejewski-Szmek
2e276efc7b0398a3086629a52970bdd4ab7252f9Zbigniew Jędrzejewski-Szmek r = manager_watch_hostname(m);
2e276efc7b0398a3086629a52970bdd4ab7252f9Zbigniew Jędrzejewski-Szmek if (r < 0)
2e276efc7b0398a3086629a52970bdd4ab7252f9Zbigniew Jędrzejewski-Szmek return r;
2e276efc7b0398a3086629a52970bdd4ab7252f9Zbigniew Jędrzejewski-Szmek
2e276efc7b0398a3086629a52970bdd4ab7252f9Zbigniew Jędrzejewski-Szmek r = dns_scope_new(m, &m->unicast_scope, NULL, DNS_PROTOCOL_DNS, AF_UNSPEC);
2e276efc7b0398a3086629a52970bdd4ab7252f9Zbigniew Jędrzejewski-Szmek if (r < 0)
2e276efc7b0398a3086629a52970bdd4ab7252f9Zbigniew Jędrzejewski-Szmek return r;
2e276efc7b0398a3086629a52970bdd4ab7252f9Zbigniew Jędrzejewski-Szmek
2e276efc7b0398a3086629a52970bdd4ab7252f9Zbigniew Jędrzejewski-Szmek r = manager_network_monitor_listen(m);
2e276efc7b0398a3086629a52970bdd4ab7252f9Zbigniew Jędrzejewski-Szmek if (r < 0)
2e276efc7b0398a3086629a52970bdd4ab7252f9Zbigniew Jędrzejewski-Szmek return r;
2d4c5cbc0ed3ccb09dc086a040088b454c22c644Lennart Poettering
2d4c5cbc0ed3ccb09dc086a040088b454c22c644Lennart Poettering r = manager_rtnl_listen(m);
322345fdb9865ef2477fba8e4bdde0e1183ef505Lennart Poettering if (r < 0)
2d4c5cbc0ed3ccb09dc086a040088b454c22c644Lennart Poettering return r;
2d4c5cbc0ed3ccb09dc086a040088b454c22c644Lennart Poettering
2d4c5cbc0ed3ccb09dc086a040088b454c22c644Lennart Poettering r = manager_connect_bus(m);
322345fdb9865ef2477fba8e4bdde0e1183ef505Lennart Poettering if (r < 0)
2d4c5cbc0ed3ccb09dc086a040088b454c22c644Lennart Poettering return r;
2d4c5cbc0ed3ccb09dc086a040088b454c22c644Lennart Poettering
2d4c5cbc0ed3ccb09dc086a040088b454c22c644Lennart Poettering (void) sd_event_add_signal(m->event, &m->sigusr1_event_source, SIGUSR1, manager_sigusr1, m);
2d4c5cbc0ed3ccb09dc086a040088b454c22c644Lennart Poettering
2d4c5cbc0ed3ccb09dc086a040088b454c22c644Lennart Poettering *ret = m;
322345fdb9865ef2477fba8e4bdde0e1183ef505Lennart Poettering m = NULL;
2d4c5cbc0ed3ccb09dc086a040088b454c22c644Lennart Poettering
2d4c5cbc0ed3ccb09dc086a040088b454c22c644Lennart Poettering return 0;
322345fdb9865ef2477fba8e4bdde0e1183ef505Lennart Poettering}
2d4c5cbc0ed3ccb09dc086a040088b454c22c644Lennart Poettering
2d4c5cbc0ed3ccb09dc086a040088b454c22c644Lennart Poetteringint manager_start(Manager *m) {
2d4c5cbc0ed3ccb09dc086a040088b454c22c644Lennart Poettering int r;
322345fdb9865ef2477fba8e4bdde0e1183ef505Lennart Poettering
2d4c5cbc0ed3ccb09dc086a040088b454c22c644Lennart Poettering assert(m);
2d4c5cbc0ed3ccb09dc086a040088b454c22c644Lennart Poettering
2d4c5cbc0ed3ccb09dc086a040088b454c22c644Lennart Poettering r = manager_llmnr_start(m);
2d4c5cbc0ed3ccb09dc086a040088b454c22c644Lennart Poettering if (r < 0)
2d4c5cbc0ed3ccb09dc086a040088b454c22c644Lennart Poettering return r;
322345fdb9865ef2477fba8e4bdde0e1183ef505Lennart Poettering
2d4c5cbc0ed3ccb09dc086a040088b454c22c644Lennart Poettering return 0;
2d4c5cbc0ed3ccb09dc086a040088b454c22c644Lennart Poettering}
2d4c5cbc0ed3ccb09dc086a040088b454c22c644Lennart Poettering
2d4c5cbc0ed3ccb09dc086a040088b454c22c644Lennart PoetteringManager *manager_free(Manager *m) {
2d4c5cbc0ed3ccb09dc086a040088b454c22c644Lennart Poettering Link *l;
2d4c5cbc0ed3ccb09dc086a040088b454c22c644Lennart Poettering
2d4c5cbc0ed3ccb09dc086a040088b454c22c644Lennart Poettering if (!m)
2d4c5cbc0ed3ccb09dc086a040088b454c22c644Lennart Poettering return NULL;
2d4c5cbc0ed3ccb09dc086a040088b454c22c644Lennart Poettering
2d4c5cbc0ed3ccb09dc086a040088b454c22c644Lennart Poettering dns_server_unlink_all(m->dns_servers);
2d4c5cbc0ed3ccb09dc086a040088b454c22c644Lennart Poettering dns_server_unlink_all(m->fallback_dns_servers);
2d4c5cbc0ed3ccb09dc086a040088b454c22c644Lennart Poettering dns_search_domain_unlink_all(m->search_domains);
2d4c5cbc0ed3ccb09dc086a040088b454c22c644Lennart Poettering
2d4c5cbc0ed3ccb09dc086a040088b454c22c644Lennart Poettering while ((l = hashmap_first(m->links)))
946c70944ebdf428ffeb9991a7449edbd4011461Zbigniew Jędrzejewski-Szmek link_free(l);
946c70944ebdf428ffeb9991a7449edbd4011461Zbigniew Jędrzejewski-Szmek
946c70944ebdf428ffeb9991a7449edbd4011461Zbigniew Jędrzejewski-Szmek while (m->dns_queries)
946c70944ebdf428ffeb9991a7449edbd4011461Zbigniew Jędrzejewski-Szmek dns_query_free(m->dns_queries);
946c70944ebdf428ffeb9991a7449edbd4011461Zbigniew Jędrzejewski-Szmek
946c70944ebdf428ffeb9991a7449edbd4011461Zbigniew Jędrzejewski-Szmek dns_scope_free(m->unicast_scope);
946c70944ebdf428ffeb9991a7449edbd4011461Zbigniew Jędrzejewski-Szmek
946c70944ebdf428ffeb9991a7449edbd4011461Zbigniew Jędrzejewski-Szmek hashmap_free(m->links);
946c70944ebdf428ffeb9991a7449edbd4011461Zbigniew Jędrzejewski-Szmek hashmap_free(m->dns_transactions);
0dae31d468b1a0e22d98921f7b0dbd92fd217167Zbigniew Jędrzejewski-Szmek
0dae31d468b1a0e22d98921f7b0dbd92fd217167Zbigniew Jędrzejewski-Szmek sd_event_source_unref(m->network_event_source);
0dae31d468b1a0e22d98921f7b0dbd92fd217167Zbigniew Jędrzejewski-Szmek sd_network_monitor_unref(m->network_monitor);
0dae31d468b1a0e22d98921f7b0dbd92fd217167Zbigniew Jędrzejewski-Szmek
0dae31d468b1a0e22d98921f7b0dbd92fd217167Zbigniew Jędrzejewski-Szmek sd_netlink_unref(m->rtnl);
0dae31d468b1a0e22d98921f7b0dbd92fd217167Zbigniew Jędrzejewski-Szmek sd_event_source_unref(m->rtnl_event_source);
0dae31d468b1a0e22d98921f7b0dbd92fd217167Zbigniew Jędrzejewski-Szmek
0dae31d468b1a0e22d98921f7b0dbd92fd217167Zbigniew Jędrzejewski-Szmek manager_llmnr_stop(m);
0dae31d468b1a0e22d98921f7b0dbd92fd217167Zbigniew Jędrzejewski-Szmek
0dae31d468b1a0e22d98921f7b0dbd92fd217167Zbigniew Jędrzejewski-Szmek sd_bus_slot_unref(m->prepare_for_sleep_slot);
0dae31d468b1a0e22d98921f7b0dbd92fd217167Zbigniew Jędrzejewski-Szmek sd_event_source_unref(m->bus_retry_event_source);
0dae31d468b1a0e22d98921f7b0dbd92fd217167Zbigniew Jędrzejewski-Szmek sd_bus_unref(m->bus);
0dae31d468b1a0e22d98921f7b0dbd92fd217167Zbigniew Jędrzejewski-Szmek
0dae31d468b1a0e22d98921f7b0dbd92fd217167Zbigniew Jędrzejewski-Szmek sd_event_source_unref(m->sigusr1_event_source);
0dae31d468b1a0e22d98921f7b0dbd92fd217167Zbigniew Jędrzejewski-Szmek
0dae31d468b1a0e22d98921f7b0dbd92fd217167Zbigniew Jędrzejewski-Szmek sd_event_unref(m->event);
0dae31d468b1a0e22d98921f7b0dbd92fd217167Zbigniew Jędrzejewski-Szmek
0dae31d468b1a0e22d98921f7b0dbd92fd217167Zbigniew Jędrzejewski-Szmek dns_resource_key_unref(m->llmnr_host_ipv4_key);
0dae31d468b1a0e22d98921f7b0dbd92fd217167Zbigniew Jędrzejewski-Szmek dns_resource_key_unref(m->llmnr_host_ipv6_key);
0dae31d468b1a0e22d98921f7b0dbd92fd217167Zbigniew Jędrzejewski-Szmek
42cc2eebb01056beb7acd3ecfe8e533558237f84Lennart Poettering sd_event_source_unref(m->hostname_event_source);
42cc2eebb01056beb7acd3ecfe8e533558237f84Lennart Poettering safe_close(m->hostname_fd);
42cc2eebb01056beb7acd3ecfe8e533558237f84Lennart Poettering free(m->llmnr_hostname);
42cc2eebb01056beb7acd3ecfe8e533558237f84Lennart Poettering free(m->mdns_hostname);
42cc2eebb01056beb7acd3ecfe8e533558237f84Lennart Poettering
42cc2eebb01056beb7acd3ecfe8e533558237f84Lennart Poettering free(m);
42cc2eebb01056beb7acd3ecfe8e533558237f84Lennart Poettering
42cc2eebb01056beb7acd3ecfe8e533558237f84Lennart Poettering return NULL;
42cc2eebb01056beb7acd3ecfe8e533558237f84Lennart Poettering}
42cc2eebb01056beb7acd3ecfe8e533558237f84Lennart Poettering
42cc2eebb01056beb7acd3ecfe8e533558237f84Lennart Poetteringint manager_recv(Manager *m, int fd, DnsProtocol protocol, DnsPacket **ret) {
42cc2eebb01056beb7acd3ecfe8e533558237f84Lennart Poettering _cleanup_(dns_packet_unrefp) DnsPacket *p = NULL;
42cc2eebb01056beb7acd3ecfe8e533558237f84Lennart Poettering union {
42cc2eebb01056beb7acd3ecfe8e533558237f84Lennart Poettering struct cmsghdr header; /* For alignment */
42cc2eebb01056beb7acd3ecfe8e533558237f84Lennart Poettering uint8_t buffer[CMSG_SPACE(MAXSIZE(struct in_pktinfo, struct in6_pktinfo))
42cc2eebb01056beb7acd3ecfe8e533558237f84Lennart Poettering + CMSG_SPACE(int) /* ttl/hoplimit */
42cc2eebb01056beb7acd3ecfe8e533558237f84Lennart Poettering + EXTRA_CMSG_SPACE /* kernel appears to require extra buffer space */];
2d4c5cbc0ed3ccb09dc086a040088b454c22c644Lennart Poettering } control;
2d4c5cbc0ed3ccb09dc086a040088b454c22c644Lennart Poettering union sockaddr_union sa;
2d4c5cbc0ed3ccb09dc086a040088b454c22c644Lennart Poettering struct msghdr mh = {};
2d4c5cbc0ed3ccb09dc086a040088b454c22c644Lennart Poettering struct cmsghdr *cmsg;
2d4c5cbc0ed3ccb09dc086a040088b454c22c644Lennart Poettering struct iovec iov;
2d4c5cbc0ed3ccb09dc086a040088b454c22c644Lennart Poettering int ms = 0, r;
2d4c5cbc0ed3ccb09dc086a040088b454c22c644Lennart Poettering ssize_t l;
2d4c5cbc0ed3ccb09dc086a040088b454c22c644Lennart Poettering
2d4c5cbc0ed3ccb09dc086a040088b454c22c644Lennart Poettering assert(m);
2d4c5cbc0ed3ccb09dc086a040088b454c22c644Lennart Poettering assert(fd >= 0);
2d4c5cbc0ed3ccb09dc086a040088b454c22c644Lennart Poettering assert(ret);
2d4c5cbc0ed3ccb09dc086a040088b454c22c644Lennart Poettering
2d4c5cbc0ed3ccb09dc086a040088b454c22c644Lennart Poettering r = ioctl(fd, FIONREAD, &ms);
2d4c5cbc0ed3ccb09dc086a040088b454c22c644Lennart Poettering if (r < 0)
2d4c5cbc0ed3ccb09dc086a040088b454c22c644Lennart Poettering return -errno;
2d4c5cbc0ed3ccb09dc086a040088b454c22c644Lennart Poettering if (ms < 0)
322345fdb9865ef2477fba8e4bdde0e1183ef505Lennart Poettering return -EIO;
2d4c5cbc0ed3ccb09dc086a040088b454c22c644Lennart Poettering
322345fdb9865ef2477fba8e4bdde0e1183ef505Lennart Poettering r = dns_packet_new(&p, protocol, ms);
2d4c5cbc0ed3ccb09dc086a040088b454c22c644Lennart Poettering if (r < 0)
322345fdb9865ef2477fba8e4bdde0e1183ef505Lennart Poettering return r;
2d4c5cbc0ed3ccb09dc086a040088b454c22c644Lennart Poettering
2d4c5cbc0ed3ccb09dc086a040088b454c22c644Lennart Poettering iov.iov_base = DNS_PACKET_DATA(p);
322345fdb9865ef2477fba8e4bdde0e1183ef505Lennart Poettering iov.iov_len = p->allocated;
2d4c5cbc0ed3ccb09dc086a040088b454c22c644Lennart Poettering
2d4c5cbc0ed3ccb09dc086a040088b454c22c644Lennart Poettering mh.msg_name = &sa.sa;
2d4c5cbc0ed3ccb09dc086a040088b454c22c644Lennart Poettering mh.msg_namelen = sizeof(sa);
322345fdb9865ef2477fba8e4bdde0e1183ef505Lennart Poettering mh.msg_iov = &iov;
2d4c5cbc0ed3ccb09dc086a040088b454c22c644Lennart Poettering mh.msg_iovlen = 1;
2d4c5cbc0ed3ccb09dc086a040088b454c22c644Lennart Poettering mh.msg_control = &control;
322345fdb9865ef2477fba8e4bdde0e1183ef505Lennart Poettering mh.msg_controllen = sizeof(control);
2d4c5cbc0ed3ccb09dc086a040088b454c22c644Lennart Poettering
2d4c5cbc0ed3ccb09dc086a040088b454c22c644Lennart Poettering l = recvmsg(fd, &mh, 0);
2d4c5cbc0ed3ccb09dc086a040088b454c22c644Lennart Poettering if (l < 0) {
2d4c5cbc0ed3ccb09dc086a040088b454c22c644Lennart Poettering if (errno == EAGAIN || errno == EINTR)
2d4c5cbc0ed3ccb09dc086a040088b454c22c644Lennart Poettering return 0;
2d4c5cbc0ed3ccb09dc086a040088b454c22c644Lennart Poettering
2d4c5cbc0ed3ccb09dc086a040088b454c22c644Lennart Poettering return -errno;
2d4c5cbc0ed3ccb09dc086a040088b454c22c644Lennart Poettering }
2d4c5cbc0ed3ccb09dc086a040088b454c22c644Lennart Poettering
2d4c5cbc0ed3ccb09dc086a040088b454c22c644Lennart Poettering if (l <= 0)
322345fdb9865ef2477fba8e4bdde0e1183ef505Lennart Poettering return -EIO;
2d4c5cbc0ed3ccb09dc086a040088b454c22c644Lennart Poettering
2d4c5cbc0ed3ccb09dc086a040088b454c22c644Lennart Poettering assert(!(mh.msg_flags & MSG_CTRUNC));
322345fdb9865ef2477fba8e4bdde0e1183ef505Lennart Poettering assert(!(mh.msg_flags & MSG_TRUNC));
2d4c5cbc0ed3ccb09dc086a040088b454c22c644Lennart Poettering
2d4c5cbc0ed3ccb09dc086a040088b454c22c644Lennart Poettering p->size = (size_t) l;
2d4c5cbc0ed3ccb09dc086a040088b454c22c644Lennart Poettering
2d4c5cbc0ed3ccb09dc086a040088b454c22c644Lennart Poettering p->family = sa.sa.sa_family;
2d4c5cbc0ed3ccb09dc086a040088b454c22c644Lennart Poettering p->ipproto = IPPROTO_UDP;
2d4c5cbc0ed3ccb09dc086a040088b454c22c644Lennart Poettering if (p->family == AF_INET) {
2d4c5cbc0ed3ccb09dc086a040088b454c22c644Lennart Poettering p->sender.in = sa.in.sin_addr;
2d4c5cbc0ed3ccb09dc086a040088b454c22c644Lennart Poettering p->sender_port = be16toh(sa.in.sin_port);
2d4c5cbc0ed3ccb09dc086a040088b454c22c644Lennart Poettering } else if (p->family == AF_INET6) {
2d4c5cbc0ed3ccb09dc086a040088b454c22c644Lennart Poettering p->sender.in6 = sa.in6.sin6_addr;
2d4c5cbc0ed3ccb09dc086a040088b454c22c644Lennart Poettering p->sender_port = be16toh(sa.in6.sin6_port);
2d4c5cbc0ed3ccb09dc086a040088b454c22c644Lennart Poettering p->ifindex = sa.in6.sin6_scope_id;
2d4c5cbc0ed3ccb09dc086a040088b454c22c644Lennart Poettering } else
0dae31d468b1a0e22d98921f7b0dbd92fd217167Zbigniew Jędrzejewski-Szmek return -EAFNOSUPPORT;
2d4c5cbc0ed3ccb09dc086a040088b454c22c644Lennart Poettering
2d4c5cbc0ed3ccb09dc086a040088b454c22c644Lennart Poettering CMSG_FOREACH(cmsg, &mh) {
9de3e3294065e8697ff10130b53f274319cdcf6fZbigniew Jędrzejewski-Szmek
2d4c5cbc0ed3ccb09dc086a040088b454c22c644Lennart Poettering if (cmsg->cmsg_level == IPPROTO_IPV6) {
2d4c5cbc0ed3ccb09dc086a040088b454c22c644Lennart Poettering assert(p->family == AF_INET6);
2d4c5cbc0ed3ccb09dc086a040088b454c22c644Lennart Poettering
2d4c5cbc0ed3ccb09dc086a040088b454c22c644Lennart Poettering switch (cmsg->cmsg_type) {
2d4c5cbc0ed3ccb09dc086a040088b454c22c644Lennart Poettering
2d4c5cbc0ed3ccb09dc086a040088b454c22c644Lennart Poettering case IPV6_PKTINFO: {
2d4c5cbc0ed3ccb09dc086a040088b454c22c644Lennart Poettering struct in6_pktinfo *i = (struct in6_pktinfo*) CMSG_DATA(cmsg);
2d4c5cbc0ed3ccb09dc086a040088b454c22c644Lennart Poettering
322345fdb9865ef2477fba8e4bdde0e1183ef505Lennart Poettering if (p->ifindex <= 0)
2d4c5cbc0ed3ccb09dc086a040088b454c22c644Lennart Poettering p->ifindex = i->ipi6_ifindex;
2d4c5cbc0ed3ccb09dc086a040088b454c22c644Lennart Poettering
322345fdb9865ef2477fba8e4bdde0e1183ef505Lennart Poettering p->destination.in6 = i->ipi6_addr;
2d4c5cbc0ed3ccb09dc086a040088b454c22c644Lennart Poettering break;
2d4c5cbc0ed3ccb09dc086a040088b454c22c644Lennart Poettering }
2d4c5cbc0ed3ccb09dc086a040088b454c22c644Lennart Poettering
322345fdb9865ef2477fba8e4bdde0e1183ef505Lennart Poettering case IPV6_HOPLIMIT:
322345fdb9865ef2477fba8e4bdde0e1183ef505Lennart Poettering p->ttl = *(int *) CMSG_DATA(cmsg);
322345fdb9865ef2477fba8e4bdde0e1183ef505Lennart Poettering break;
2d4c5cbc0ed3ccb09dc086a040088b454c22c644Lennart Poettering
2d4c5cbc0ed3ccb09dc086a040088b454c22c644Lennart Poettering }
2d4c5cbc0ed3ccb09dc086a040088b454c22c644Lennart Poettering } else if (cmsg->cmsg_level == IPPROTO_IP) {
2d4c5cbc0ed3ccb09dc086a040088b454c22c644Lennart Poettering assert(p->family == AF_INET);
2d4c5cbc0ed3ccb09dc086a040088b454c22c644Lennart Poettering
2d4c5cbc0ed3ccb09dc086a040088b454c22c644Lennart Poettering switch (cmsg->cmsg_type) {
2d4c5cbc0ed3ccb09dc086a040088b454c22c644Lennart Poettering
2d4c5cbc0ed3ccb09dc086a040088b454c22c644Lennart Poettering case IP_PKTINFO: {
2d4c5cbc0ed3ccb09dc086a040088b454c22c644Lennart Poettering struct in_pktinfo *i = (struct in_pktinfo*) CMSG_DATA(cmsg);
2d4c5cbc0ed3ccb09dc086a040088b454c22c644Lennart Poettering
2d4c5cbc0ed3ccb09dc086a040088b454c22c644Lennart Poettering if (p->ifindex <= 0)
2d4c5cbc0ed3ccb09dc086a040088b454c22c644Lennart Poettering p->ifindex = i->ipi_ifindex;
2d4c5cbc0ed3ccb09dc086a040088b454c22c644Lennart Poettering
2d4c5cbc0ed3ccb09dc086a040088b454c22c644Lennart Poettering p->destination.in = i->ipi_addr;
2d4c5cbc0ed3ccb09dc086a040088b454c22c644Lennart Poettering break;
}
case IP_TTL:
p->ttl = *(int *) CMSG_DATA(cmsg);
break;
}
}
}
/* The Linux kernel sets the interface index to the loopback
* device if the packet came from the local host since it
* avoids the routing table in such a case. Let's unset the
* interface index in such a case. */
if (p->ifindex == LOOPBACK_IFINDEX)
p->ifindex = 0;
if (protocol != DNS_PROTOCOL_DNS) {
/* If we don't know the interface index still, we look for the
* first local interface with a matching address. Yuck! */
if (p->ifindex <= 0)
p->ifindex = manager_find_ifindex(m, p->family, &p->destination);
}
*ret = p;
p = NULL;
return 1;
}
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;
}
}
static int write_loop(int fd, void *message, size_t length) {
int r;
assert(fd >= 0);
assert(message);
for (;;) {
if (write(fd, message, length) >= 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_write(Manager *m, int fd, DnsPacket *p) {
int r;
log_debug("Sending %s packet with id %u", DNS_PACKET_QR(p) ? "response" : "query", DNS_PACKET_ID(p));
r = write_loop(fd, DNS_PACKET_DATA(p), p->size);
if (r < 0)
return r;
return 0;
}
static int manager_ipv4_send(Manager *m, int fd, int ifindex, const struct in_addr *addr, uint16_t port, DnsPacket *p) {
union sockaddr_union sa = {
.in.sin_family = AF_INET,
};
union {
struct cmsghdr header; /* For alignment */
uint8_t buffer[CMSG_SPACE(sizeof(struct in_pktinfo))];
} control;
struct msghdr mh = {};
struct iovec iov;
assert(m);
assert(fd >= 0);
assert(addr);
assert(port > 0);
assert(p);
iov.iov_base = DNS_PACKET_DATA(p);
iov.iov_len = p->size;
sa.in.sin_addr = *addr;
sa.in.sin_port = htobe16(port),
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);
}
static int manager_ipv6_send(Manager *m, int fd, int ifindex, const struct in6_addr *addr, uint16_t port, DnsPacket *p) {
union sockaddr_union sa = {
.in6.sin6_family = AF_INET6,
};
union {
struct cmsghdr header; /* For alignment */
uint8_t buffer[CMSG_SPACE(sizeof(struct in6_pktinfo))];
} control;
struct msghdr mh = {};
struct iovec iov;
assert(m);
assert(fd >= 0);
assert(addr);
assert(port > 0);
assert(p);
iov.iov_base = DNS_PACKET_DATA(p);
iov.iov_len = p->size;
sa.in6.sin6_addr = *addr;
sa.in6.sin6_port = htobe16(port),
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);
}
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(fd >= 0);
assert(addr);
assert(port > 0);
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));
if (family == AF_INET)
return manager_ipv4_send(m, fd, ifindex, &addr->in, port, p);
else if (family == AF_INET6)
return manager_ipv6_send(m, fd, ifindex, &addr->in6, port, p);
return -EAFNOSUPPORT;
}
uint32_t manager_find_mtu(Manager *m) {
uint32_t mtu = 0;
Link *l;
Iterator i;
/* If we don't know on which link a DNS packet would be
* delivered, let's find the largest MTU that works on all
* interfaces we know of */
HASHMAP_FOREACH(l, m->links, i) {
if (l->mtu <= 0)
continue;
if (mtu <= 0 || l->mtu < mtu)
mtu = l->mtu;
}
return mtu;
}
int manager_find_ifindex(Manager *m, int family, const union in_addr_union *in_addr) {
LinkAddress *a;
assert(m);
a = manager_find_link_address(m, family, in_addr);
if (a)
return a->link->ifindex;
return 0;
}
void manager_refresh_rrs(Manager *m) {
Iterator i;
Link *l;
assert(m);
m->llmnr_host_ipv4_key = dns_resource_key_unref(m->llmnr_host_ipv4_key);
m->llmnr_host_ipv6_key = dns_resource_key_unref(m->llmnr_host_ipv6_key);
HASHMAP_FOREACH(l, m->links, i) {
link_add_rrs(l, true);
link_add_rrs(l, false);
}
}
int manager_next_hostname(Manager *m) {
const char *p;
uint64_t u, a;
char *h, *k;
int r;
assert(m);
p = strchr(m->llmnr_hostname, 0);
assert(p);
while (p > m->llmnr_hostname) {
if (!strchr("0123456789", p[-1]))
break;
p--;
}
if (*p == 0 || safe_atou64(p, &u) < 0 || u <= 0)
u = 1;
/* Add a random number to the old value. This way we can avoid
* that two hosts pick the same hostname, win on IPv4 and lose
* on IPv6 (or vice versa), and pick the same hostname
* replacement hostname, ad infinitum. We still want the
* numbers to go up monotonically, hence we just add a random
* value 1..10 */
random_bytes(&a, sizeof(a));
u += 1 + a % 10;
if (asprintf(&h, "%.*s%" PRIu64, (int) (p - m->llmnr_hostname), m->llmnr_hostname, u) < 0)
return -ENOMEM;
r = dns_name_concat(h, "local", &k);
if (r < 0) {
free(h);
return r;
}
log_info("Hostname conflict, changing published hostname from '%s' to '%s'.", m->llmnr_hostname, h);
free(m->llmnr_hostname);
m->llmnr_hostname = h;
free(m->mdns_hostname);
m->mdns_hostname = k;
manager_refresh_rrs(m);
return 0;
}
LinkAddress* manager_find_link_address(Manager *m, int family, const union in_addr_union *in_addr) {
Iterator i;
Link *l;
assert(m);
HASHMAP_FOREACH(l, m->links, i) {
LinkAddress *a;
a = link_find_address(l, family, in_addr);
if (a)
return a;
}
return NULL;
}
bool manager_our_packet(Manager *m, DnsPacket *p) {
assert(m);
assert(p);
return !!manager_find_link_address(m, p->family, &p->sender);
}
DnsScope* manager_find_scope(Manager *m, DnsPacket *p) {
Link *l;
assert(m);
assert(p);
l = hashmap_get(m->links, INT_TO_PTR(p->ifindex));
if (!l)
return NULL;
if (p->protocol == DNS_PROTOCOL_LLMNR) {
if (p->family == AF_INET)
return l->llmnr_ipv4_scope;
else if (p->family == AF_INET6)
return l->llmnr_ipv6_scope;
}
return NULL;
}
void manager_verify_all(Manager *m) {
DnsScope *s;
assert(m);
LIST_FOREACH(scopes, s, m->dns_scopes)
dns_zone_verify_all(&s->zone);
}
int manager_is_own_hostname(Manager *m, const char *name) {
int r;
assert(m);
assert(name);
if (m->llmnr_hostname) {
r = dns_name_equal(name, m->llmnr_hostname);
if (r != 0)
return r;
}
if (m->mdns_hostname)
return dns_name_equal(name, m->mdns_hostname);
return 0;
}
int manager_compile_dns_servers(Manager *m, OrderedSet **dns) {
DnsServer *s;
Iterator i;
Link *l;
int r;
assert(m);
assert(dns);
r = ordered_set_ensure_allocated(dns, &dns_server_hash_ops);
if (r < 0)
return r;
/* First add the system-wide servers and domains */
LIST_FOREACH(servers, s, m->dns_servers) {
r = ordered_set_put(*dns, s);
if (r == -EEXIST)
continue;
if (r < 0)
return r;
}
/* Then, add the per-link servers */
HASHMAP_FOREACH(l, m->links, i) {
LIST_FOREACH(servers, s, l->dns_servers) {
r = ordered_set_put(*dns, s);
if (r == -EEXIST)
continue;
if (r < 0)
return r;
}
}
/* If we found nothing, add the fallback servers */
if (ordered_set_isempty(*dns)) {
LIST_FOREACH(servers, s, m->fallback_dns_servers) {
r = ordered_set_put(*dns, s);
if (r == -EEXIST)
continue;
if (r < 0)
return r;
}
}
return 0;
}
int manager_compile_search_domains(Manager *m, OrderedSet **domains) {
DnsSearchDomain *d;
Iterator i;
Link *l;
int r;
assert(m);
assert(domains);
r = ordered_set_ensure_allocated(domains, &dns_name_hash_ops);
if (r < 0)
return r;
LIST_FOREACH(domains, d, m->search_domains) {
r = ordered_set_put(*domains, d->name);
if (r == -EEXIST)
continue;
if (r < 0)
return r;
}
HASHMAP_FOREACH(l, m->links, i) {
LIST_FOREACH(domains, d, l->search_domains) {
r = ordered_set_put(*domains, d->name);
if (r == -EEXIST)
continue;
if (r < 0)
return r;
}
}
return 0;
}
static const char* const support_table[_SUPPORT_MAX] = {
[SUPPORT_NO] = "no",
[SUPPORT_YES] = "yes",
[SUPPORT_RESOLVE] = "resolve",
};
DEFINE_STRING_TABLE_LOOKUP(support, Support);