resolved-manager.c revision 3ffd4af22052963e7a29431721ee204e634bea75
091a364c802e34a58f3260c9cb5db9b75c62215cTom Gundersen/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
091a364c802e34a58f3260c9cb5db9b75c62215cTom Gundersen
091a364c802e34a58f3260c9cb5db9b75c62215cTom Gundersen/***
091a364c802e34a58f3260c9cb5db9b75c62215cTom Gundersen This file is part of systemd.
091a364c802e34a58f3260c9cb5db9b75c62215cTom Gundersen
091a364c802e34a58f3260c9cb5db9b75c62215cTom Gundersen Copyright 2014 Tom Gundersen <teg@jklm.no>
091a364c802e34a58f3260c9cb5db9b75c62215cTom Gundersen
091a364c802e34a58f3260c9cb5db9b75c62215cTom Gundersen systemd is free software; you can redistribute it and/or modify it
091a364c802e34a58f3260c9cb5db9b75c62215cTom Gundersen under the terms of the GNU Lesser General Public License as published by
091a364c802e34a58f3260c9cb5db9b75c62215cTom Gundersen the Free Software Foundation; either version 2.1 of the License, or
091a364c802e34a58f3260c9cb5db9b75c62215cTom Gundersen (at your option) any later version.
091a364c802e34a58f3260c9cb5db9b75c62215cTom Gundersen
091a364c802e34a58f3260c9cb5db9b75c62215cTom Gundersen systemd is distributed in the hope that it will be useful, but
091a364c802e34a58f3260c9cb5db9b75c62215cTom Gundersen WITHOUT ANY WARRANTY; without even the implied warranty of
091a364c802e34a58f3260c9cb5db9b75c62215cTom Gundersen MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
091a364c802e34a58f3260c9cb5db9b75c62215cTom Gundersen Lesser General Public License for more details.
091a364c802e34a58f3260c9cb5db9b75c62215cTom Gundersen
091a364c802e34a58f3260c9cb5db9b75c62215cTom Gundersen You should have received a copy of the GNU Lesser General Public License
091a364c802e34a58f3260c9cb5db9b75c62215cTom Gundersen along with systemd; If not, see <http://www.gnu.org/licenses/>.
091a364c802e34a58f3260c9cb5db9b75c62215cTom Gundersen ***/
091a364c802e34a58f3260c9cb5db9b75c62215cTom Gundersen
07630cea1f3a845c09309f197ac7c4f11edd3b62Lennart Poettering#include <netinet/in.h>
07630cea1f3a845c09309f197ac7c4f11edd3b62Lennart Poettering#include <poll.h>
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering#include <resolv.h>
091a364c802e34a58f3260c9cb5db9b75c62215cTom Gundersen#include <sys/ioctl.h>
a2a416f768e2aa7db5b975cd50eb19237cac9cceLennart Poettering
b5efdb8af40ea759a1ea584c1bc44ecc81dd00ceLennart Poettering#include "af-list.h"
07630cea1f3a845c09309f197ac7c4f11edd3b62Lennart Poettering#include "dns-domain.h"
3ffd4af22052963e7a29431721ee204e634bea75Lennart Poettering#include "fd-util.h"
a5a807e63a50314e190e9166d8a453cd8dd258e3Zbigniew Jędrzejewski-Szmek#include "fileio-label.h"
07630cea1f3a845c09309f197ac7c4f11edd3b62Lennart Poettering#include "hostname-util.h"
c004493cdefc1f43a3956ca529e8070f8d70be56Lennart Poettering#include "netlink-util.h"
07630cea1f3a845c09309f197ac7c4f11edd3b62Lennart Poettering#include "network-internal.h"
07630cea1f3a845c09309f197ac7c4f11edd3b62Lennart Poettering#include "ordered-set.h"
822db23cfa98a9fbc48f41e11caafb6f1017e052Lennart Poettering#include "random-util.h"
6bedfcbb2970e06a4d3280c8fb62083d252ede73Lennart Poettering#include "resolved-bus.h"
3df3e884ae1237ef0d4d23b0e80f4ffda95ac135Ronny Chevalier#include "resolved-conf.h"
39d8db043b599a7382f94bfc904d5e108af438bdLennart Poettering#include "resolved-llmnr.h"
07630cea1f3a845c09309f197ac7c4f11edd3b62Lennart Poettering#include "resolved-manager.h"
dd0bc0f1414cc1d0fa73a29470bd14944e4942d3Lennart Poettering#include "socket-util.h"
5f402ae84bbc08fe8de5682e371b3f66c387da52Daniel Mack#include "string-util.h"
07630cea1f3a845c09309f197ac7c4f11edd3b62Lennart Poettering#include "utf8.h"
bc7702b098b63031767174206f5df14a8ccb45cfDaniel Mack
dd0bc0f1414cc1d0fa73a29470bd14944e4942d3Lennart Poettering#define SEND_TIMEOUT_USEC (200 * USEC_PER_MSEC)
07630cea1f3a845c09309f197ac7c4f11edd3b62Lennart Poettering
8b43440b7ef4b81c69c31de7ff820dc07a780254Lennart Poetteringstatic int manager_process_link(sd_netlink *rtnl, sd_netlink_message *mm, void *userdata) {
07630cea1f3a845c09309f197ac7c4f11edd3b62Lennart Poettering Manager *m = userdata;
07630cea1f3a845c09309f197ac7c4f11edd3b62Lennart Poettering uint16_t type;
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering Link *l;
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering int ifindex, r;
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering
1c4baffc1895809bae9ac36b670af90a4cb9cd7dTom Gundersen assert(rtnl);
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering assert(m);
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering assert(mm);
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering r = sd_netlink_message_get_type(mm, &type);
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering if (r < 0)
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering goto fail;
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering r = sd_rtnl_message_link_get_ifindex(mm, &ifindex);
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering if (r < 0)
1c4baffc1895809bae9ac36b670af90a4cb9cd7dTom Gundersen goto fail;
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering l = hashmap_get(m->links, INT_TO_PTR(ifindex));
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering switch (type) {
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering case RTM_NEWLINK:{
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering bool is_new = !l;
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering if (!l) {
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering r = link_new(m, &l, ifindex);
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering if (r < 0)
a2a416f768e2aa7db5b975cd50eb19237cac9cceLennart Poettering goto fail;
a2a416f768e2aa7db5b975cd50eb19237cac9cceLennart Poettering }
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering
a2a416f768e2aa7db5b975cd50eb19237cac9cceLennart Poettering r = link_update_rtnl(l, mm);
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering if (r < 0)
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering goto fail;
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering r = link_update_monitor(l);
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering if (r < 0)
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering goto fail;
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering if (is_new)
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering log_debug("Found new link %i/%s", ifindex, l->name);
21d73c87b09ec2b8642424bc714ce9af3da4fc40Lennart Poettering
21d73c87b09ec2b8642424bc714ce9af3da4fc40Lennart Poettering break;
21d73c87b09ec2b8642424bc714ce9af3da4fc40Lennart Poettering }
21d73c87b09ec2b8642424bc714ce9af3da4fc40Lennart Poettering
a2a416f768e2aa7db5b975cd50eb19237cac9cceLennart Poettering case RTM_DELLINK:
a2a416f768e2aa7db5b975cd50eb19237cac9cceLennart Poettering if (l) {
a2a416f768e2aa7db5b975cd50eb19237cac9cceLennart Poettering log_debug("Removing link %i/%s", l->ifindex, l->name);
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering link_free(l);
a2a416f768e2aa7db5b975cd50eb19237cac9cceLennart Poettering }
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering break;
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering }
a2a416f768e2aa7db5b975cd50eb19237cac9cceLennart Poettering
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering return 0;
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poetteringfail:
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering log_warning_errno(r, "Failed to process RTNL link message: %m");
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering return 0;
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering}
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poetteringstatic int manager_process_address(sd_netlink *rtnl, sd_netlink_message *mm, void *userdata) {
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering Manager *m = userdata;
da927ba997d68401563b927f92e6e40e021a8e5cMichal Schmidt union in_addr_union address;
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering uint16_t type;
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering int r, ifindex, family;
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering LinkAddress *a;
1c4baffc1895809bae9ac36b670af90a4cb9cd7dTom Gundersen Link *l;
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering assert(rtnl);
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering assert(mm);
0dd25fb9f005d8ab7ac4bc10a609d00569f8c56aLennart Poettering assert(m);
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering r = sd_netlink_message_get_type(mm, &type);
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering if (r < 0)
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering goto fail;
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering r = sd_rtnl_message_addr_get_ifindex(mm, &ifindex);
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering if (r < 0)
1c4baffc1895809bae9ac36b670af90a4cb9cd7dTom Gundersen goto fail;
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering l = hashmap_get(m->links, INT_TO_PTR(ifindex));
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering if (!l)
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering return 0;
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering r = sd_rtnl_message_addr_get_family(mm, &family);
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering if (r < 0)
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering goto fail;
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering switch (family) {
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering case AF_INET:
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering r = sd_netlink_message_read_in_addr(mm, IFA_LOCAL, &address.in);
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering if (r < 0) {
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering r = sd_netlink_message_read_in_addr(mm, IFA_ADDRESS, &address.in);
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering if (r < 0)
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering goto fail;
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering }
1c4baffc1895809bae9ac36b670af90a4cb9cd7dTom Gundersen
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering break;
1c4baffc1895809bae9ac36b670af90a4cb9cd7dTom Gundersen
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering case AF_INET6:
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering r = sd_netlink_message_read_in6_addr(mm, IFA_LOCAL, &address.in6);
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering if (r < 0) {
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering r = sd_netlink_message_read_in6_addr(mm, IFA_ADDRESS, &address.in6);
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering if (r < 0)
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering goto fail;
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering }
1c4baffc1895809bae9ac36b670af90a4cb9cd7dTom Gundersen
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering break;
1c4baffc1895809bae9ac36b670af90a4cb9cd7dTom Gundersen
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering default:
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering return 0;
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering }
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering a = link_find_address(l, family, &address);
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering switch (type) {
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering case RTM_NEWADDR:
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering if (!a) {
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering r = link_address_new(l, &a, family, &address);
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering if (r < 0)
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering return r;
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering }
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering r = link_address_update_rtnl(a, mm);
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering if (r < 0)
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering return r;
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering break;
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering case RTM_DELADDR:
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering link_address_free(a);
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering break;
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering }
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering return 0;
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering
3e044c492e3ebe64f4e3175c94f9db8a62557b82Markus Elfringfail:
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart 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;
da927ba997d68401563b927f92e6e40e021a8e5cMichal Schmidt sd_netlink_message *i;
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering int r;
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering assert(m);
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering
4afd3348c7506dd1d36305b7bcb9feb8952b9d6bLennart Poettering /* First, subscribe to interfaces coming and going */
1c4baffc1895809bae9ac36b670af90a4cb9cd7dTom Gundersen r = sd_netlink_open(&m->rtnl);
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering if (r < 0)
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering return r;
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering r = sd_netlink_attach_event(m->rtnl, m->event, 0);
cc98b3025eeb89addb76a27390cb2baca4eab8b9Torstein Husebø if (r < 0)
1c4baffc1895809bae9ac36b670af90a4cb9cd7dTom Gundersen return r;
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering r = sd_netlink_add_match(m->rtnl, RTM_NEWLINK, manager_process_link, m);
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering if (r < 0)
2d8950384f3137aafcce22b29912b2b61e6d86fbLennart 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)
1c4baffc1895809bae9ac36b670af90a4cb9cd7dTom Gundersen return r;
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering r = sd_netlink_add_match(m->rtnl, RTM_NEWADDR, manager_process_address, m);
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering if (r < 0)
1c4baffc1895809bae9ac36b670af90a4cb9cd7dTom Gundersen return r;
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering r = sd_netlink_add_match(m->rtnl, RTM_DELADDR, manager_process_address, m);
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering if (r < 0)
1c4baffc1895809bae9ac36b670af90a4cb9cd7dTom Gundersen return r;
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering /* Then, enumerate all links */
091a364c802e34a58f3260c9cb5db9b75c62215cTom Gundersen r = sd_rtnl_message_new_link(m->rtnl, &req, RTM_GETLINK, 0);
1c4baffc1895809bae9ac36b670af90a4cb9cd7dTom Gundersen 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;
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering r = sd_netlink_call(m->rtnl, req, 0, &reply);
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering if (r < 0)
1c4baffc1895809bae9ac36b670af90a4cb9cd7dTom Gundersen return r;
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering for (i = reply; i; i = sd_netlink_message_next(i)) {
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering r = manager_process_link(m->rtnl, i, m);
1c4baffc1895809bae9ac36b670af90a4cb9cd7dTom Gundersen if (r < 0)
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering return r;
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering }
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering
1c4baffc1895809bae9ac36b670af90a4cb9cd7dTom Gundersen req = sd_netlink_message_unref(req);
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering reply = sd_netlink_message_unref(reply);
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering /* Finally, enumerate all addresses, too */
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering r = sd_rtnl_message_new_addr(m->rtnl, &req, RTM_GETADDR, 0, AF_UNSPEC);
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering if (r < 0)
1c4baffc1895809bae9ac36b670af90a4cb9cd7dTom Gundersen return r;
1c4baffc1895809bae9ac36b670af90a4cb9cd7dTom Gundersen
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering r = sd_netlink_message_request_dump(req, true);
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering if (r < 0)
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering return r;
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering r = sd_netlink_call(m->rtnl, req, 0, &reply);
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering if (r < 0)
1c4baffc1895809bae9ac36b670af90a4cb9cd7dTom Gundersen return r;
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering for (i = reply; i; i = sd_netlink_message_next(i)) {
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering r = manager_process_address(m->rtnl, i, m);
1c4baffc1895809bae9ac36b670af90a4cb9cd7dTom Gundersen if (r < 0)
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering return r;
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering }
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering
1c4baffc1895809bae9ac36b670af90a4cb9cd7dTom Gundersen return r;
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering}
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poetteringstatic int on_network_event(sd_event_source *s, int fd, uint32_t revents, void *userdata) {
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering Manager *m = userdata;
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering Iterator i;
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering Link *l;
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering int r;
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering assert(m);
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering sd_network_monitor_flush(m->network_monitor);
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering HASHMAP_FOREACH(l, m->links, i) {
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering r = link_update_monitor(l);
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering if (r < 0)
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering log_warning_errno(r, "Failed to update monitor information for %i: %m", l->ifindex);
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering }
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering r = manager_write_resolv_conf(m);
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering if (r < 0)
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering log_warning_errno(r, "Could not update resolv.conf: %m");
da927ba997d68401563b927f92e6e40e021a8e5cMichal Schmidt
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering return 0;
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering}
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poetteringstatic int manager_network_monitor_listen(Manager *m) {
da927ba997d68401563b927f92e6e40e021a8e5cMichal Schmidt int r, fd, events;
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering assert(m);
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering r = sd_network_monitor_new(&m->network_monitor, NULL);
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering if (r < 0)
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering return r;
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering fd = sd_network_monitor_get_fd(m->network_monitor);
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering if (fd < 0)
0014a4ad505d119c7ac4346d9d774c3f17f663a5Lennart Poettering return fd;
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering events = sd_network_monitor_get_events(m->network_monitor);
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering if (events < 0)
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering return events;
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering r = sd_event_add_io(m->event, &m->network_event_source, fd, events, &on_network_event, m);
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering if (r < 0)
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering return r;
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering return 0;
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering}
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poetteringstatic int determine_hostname(char **llmnr_hostname, char **mdns_hostname) {
2d8950384f3137aafcce22b29912b2b61e6d86fbLennart Poettering _cleanup_free_ char *h = NULL, *n = NULL;
2d8950384f3137aafcce22b29912b2b61e6d86fbLennart Poettering char label[DNS_LABEL_MAX];
2d8950384f3137aafcce22b29912b2b61e6d86fbLennart Poettering const char *p;
2d8950384f3137aafcce22b29912b2b61e6d86fbLennart Poettering int r, k;
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering assert(llmnr_hostname);
aa4a9deb7d3db95ffb1fd18791be66f58d06a69eLennart Poettering assert(mdns_hostname);
aa4a9deb7d3db95ffb1fd18791be66f58d06a69eLennart Poettering
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering /* Extract and normalize the first label of the locally
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering * configured hostname, and check it's not "localhost". */
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering
78c6a153c47f8d597c827bdcaf8c4e42ac87f738Lennart Poettering h = gethostname_malloc();
eb60f9cd4e93ff5016dc1b5486fd1b7e1565fd92Lennart Poettering if (!h)
78c6a153c47f8d597c827bdcaf8c4e42ac87f738Lennart Poettering return log_oom();
78c6a153c47f8d597c827bdcaf8c4e42ac87f738Lennart Poettering
78c6a153c47f8d597c827bdcaf8c4e42ac87f738Lennart Poettering p = h;
eb60f9cd4e93ff5016dc1b5486fd1b7e1565fd92Lennart Poettering r = dns_label_unescape(&p, label, sizeof(label));
78c6a153c47f8d597c827bdcaf8c4e42ac87f738Lennart Poettering if (r < 0)
78c6a153c47f8d597c827bdcaf8c4e42ac87f738Lennart Poettering return log_error_errno(r, "Failed to unescape host name: %m");
78c6a153c47f8d597c827bdcaf8c4e42ac87f738Lennart Poettering if (r == 0) {
78c6a153c47f8d597c827bdcaf8c4e42ac87f738Lennart Poettering log_error("Couldn't find a single label in hosntame.");
78c6a153c47f8d597c827bdcaf8c4e42ac87f738Lennart Poettering return -EINVAL;
eb60f9cd4e93ff5016dc1b5486fd1b7e1565fd92Lennart Poettering }
eb60f9cd4e93ff5016dc1b5486fd1b7e1565fd92Lennart Poettering
eb60f9cd4e93ff5016dc1b5486fd1b7e1565fd92Lennart Poettering k = dns_label_undo_idna(label, r, label, sizeof(label));
eb60f9cd4e93ff5016dc1b5486fd1b7e1565fd92Lennart Poettering if (k < 0)
eb60f9cd4e93ff5016dc1b5486fd1b7e1565fd92Lennart Poettering return log_error_errno(k, "Failed to undo IDNA: %m");
78c6a153c47f8d597c827bdcaf8c4e42ac87f738Lennart Poettering if (k > 0)
78c6a153c47f8d597c827bdcaf8c4e42ac87f738Lennart Poettering r = k;
78c6a153c47f8d597c827bdcaf8c4e42ac87f738Lennart Poettering
78c6a153c47f8d597c827bdcaf8c4e42ac87f738Lennart Poettering if (!utf8_is_valid(label)) {
78c6a153c47f8d597c827bdcaf8c4e42ac87f738Lennart Poettering log_error("System hostname is not UTF-8 clean.");
78c6a153c47f8d597c827bdcaf8c4e42ac87f738Lennart Poettering return -EINVAL;
78c6a153c47f8d597c827bdcaf8c4e42ac87f738Lennart Poettering }
78c6a153c47f8d597c827bdcaf8c4e42ac87f738Lennart Poettering
78c6a153c47f8d597c827bdcaf8c4e42ac87f738Lennart Poettering r = dns_label_escape(label, r, &n);
78c6a153c47f8d597c827bdcaf8c4e42ac87f738Lennart Poettering if (r < 0)
78c6a153c47f8d597c827bdcaf8c4e42ac87f738Lennart Poettering return log_error_errno(r, "Failed to escape host name: %m");
78c6a153c47f8d597c827bdcaf8c4e42ac87f738Lennart Poettering
78c6a153c47f8d597c827bdcaf8c4e42ac87f738Lennart Poettering if (is_localhost(n)) {
78c6a153c47f8d597c827bdcaf8c4e42ac87f738Lennart Poettering log_debug("System hostname is 'localhost', ignoring.");
78c6a153c47f8d597c827bdcaf8c4e42ac87f738Lennart Poettering return -EINVAL;
78c6a153c47f8d597c827bdcaf8c4e42ac87f738Lennart Poettering }
eb60f9cd4e93ff5016dc1b5486fd1b7e1565fd92Lennart Poettering
eb60f9cd4e93ff5016dc1b5486fd1b7e1565fd92Lennart Poettering r = dns_name_concat(n, "local", mdns_hostname);
eb60f9cd4e93ff5016dc1b5486fd1b7e1565fd92Lennart Poettering if (r < 0)
eb60f9cd4e93ff5016dc1b5486fd1b7e1565fd92Lennart Poettering return log_error_errno(r, "Failed to determine mDNS hostname: %m");
422baca0f230913158078fddf884e06c8c64a316Lennart Poettering
78c6a153c47f8d597c827bdcaf8c4e42ac87f738Lennart Poettering *llmnr_hostname = n;
78c6a153c47f8d597c827bdcaf8c4e42ac87f738Lennart Poettering n = NULL;
78c6a153c47f8d597c827bdcaf8c4e42ac87f738Lennart Poettering
78c6a153c47f8d597c827bdcaf8c4e42ac87f738Lennart Poettering return 0;
78c6a153c47f8d597c827bdcaf8c4e42ac87f738Lennart Poettering}
78c6a153c47f8d597c827bdcaf8c4e42ac87f738Lennart Poettering
eb60f9cd4e93ff5016dc1b5486fd1b7e1565fd92Lennart Poetteringstatic int on_hostname_change(sd_event_source *es, int fd, uint32_t revents, void *userdata) {
eb60f9cd4e93ff5016dc1b5486fd1b7e1565fd92Lennart Poettering _cleanup_free_ char *llmnr_hostname = NULL, *mdns_hostname = NULL;
78c6a153c47f8d597c827bdcaf8c4e42ac87f738Lennart Poettering Manager *m = userdata;
78c6a153c47f8d597c827bdcaf8c4e42ac87f738Lennart Poettering int r;
78c6a153c47f8d597c827bdcaf8c4e42ac87f738Lennart Poettering
78c6a153c47f8d597c827bdcaf8c4e42ac87f738Lennart Poettering assert(m);
78c6a153c47f8d597c827bdcaf8c4e42ac87f738Lennart Poettering
eb60f9cd4e93ff5016dc1b5486fd1b7e1565fd92Lennart Poettering r = determine_hostname(&llmnr_hostname, &mdns_hostname);
eb60f9cd4e93ff5016dc1b5486fd1b7e1565fd92Lennart Poettering if (r < 0)
eb60f9cd4e93ff5016dc1b5486fd1b7e1565fd92Lennart Poettering return 0; /* ignore invalid hostnames */
eb60f9cd4e93ff5016dc1b5486fd1b7e1565fd92Lennart Poettering
eb60f9cd4e93ff5016dc1b5486fd1b7e1565fd92Lennart Poettering if (streq(llmnr_hostname, m->llmnr_hostname) && streq(mdns_hostname, m->mdns_hostname))
eb60f9cd4e93ff5016dc1b5486fd1b7e1565fd92Lennart Poettering return 0;
78c6a153c47f8d597c827bdcaf8c4e42ac87f738Lennart Poettering
eb60f9cd4e93ff5016dc1b5486fd1b7e1565fd92Lennart Poettering log_info("System hostname changed to '%s'.", llmnr_hostname);
eb60f9cd4e93ff5016dc1b5486fd1b7e1565fd92Lennart Poettering
eb60f9cd4e93ff5016dc1b5486fd1b7e1565fd92Lennart Poettering free(m->llmnr_hostname);
eb60f9cd4e93ff5016dc1b5486fd1b7e1565fd92Lennart Poettering free(m->mdns_hostname);
eb60f9cd4e93ff5016dc1b5486fd1b7e1565fd92Lennart Poettering
78c6a153c47f8d597c827bdcaf8c4e42ac87f738Lennart Poettering m->llmnr_hostname = llmnr_hostname;
eb60f9cd4e93ff5016dc1b5486fd1b7e1565fd92Lennart Poettering m->mdns_hostname = mdns_hostname;
eb60f9cd4e93ff5016dc1b5486fd1b7e1565fd92Lennart Poettering
eb60f9cd4e93ff5016dc1b5486fd1b7e1565fd92Lennart Poettering llmnr_hostname = mdns_hostname = NULL;
78c6a153c47f8d597c827bdcaf8c4e42ac87f738Lennart Poettering
eb60f9cd4e93ff5016dc1b5486fd1b7e1565fd92Lennart Poettering manager_refresh_rrs(m);
eb60f9cd4e93ff5016dc1b5486fd1b7e1565fd92Lennart Poettering
78c6a153c47f8d597c827bdcaf8c4e42ac87f738Lennart Poettering return 0;
78c6a153c47f8d597c827bdcaf8c4e42ac87f738Lennart Poettering}
78c6a153c47f8d597c827bdcaf8c4e42ac87f738Lennart Poettering
78c6a153c47f8d597c827bdcaf8c4e42ac87f738Lennart Poetteringstatic int manager_watch_hostname(Manager *m) {
78c6a153c47f8d597c827bdcaf8c4e42ac87f738Lennart Poettering int r;
78c6a153c47f8d597c827bdcaf8c4e42ac87f738Lennart Poettering
78c6a153c47f8d597c827bdcaf8c4e42ac87f738Lennart Poettering assert(m);
78c6a153c47f8d597c827bdcaf8c4e42ac87f738Lennart Poettering
78c6a153c47f8d597c827bdcaf8c4e42ac87f738Lennart Poettering m->hostname_fd = open("/proc/sys/kernel/hostname", O_RDONLY|O_CLOEXEC|O_NDELAY|O_NOCTTY);
eb60f9cd4e93ff5016dc1b5486fd1b7e1565fd92Lennart Poettering if (m->hostname_fd < 0) {
eb60f9cd4e93ff5016dc1b5486fd1b7e1565fd92Lennart Poettering log_warning_errno(errno, "Failed to watch hostname: %m");
eb60f9cd4e93ff5016dc1b5486fd1b7e1565fd92Lennart Poettering return 0;
eb60f9cd4e93ff5016dc1b5486fd1b7e1565fd92Lennart Poettering }
eb60f9cd4e93ff5016dc1b5486fd1b7e1565fd92Lennart Poettering
eb60f9cd4e93ff5016dc1b5486fd1b7e1565fd92Lennart Poettering r = sd_event_add_io(m->event, &m->hostname_event_source, m->hostname_fd, 0, on_hostname_change, m);
eb60f9cd4e93ff5016dc1b5486fd1b7e1565fd92Lennart Poettering if (r < 0) {
eb60f9cd4e93ff5016dc1b5486fd1b7e1565fd92Lennart Poettering if (r == -EPERM)
eb60f9cd4e93ff5016dc1b5486fd1b7e1565fd92Lennart Poettering /* kernels prior to 3.2 don't support polling this file. Ignore the failure. */
eb60f9cd4e93ff5016dc1b5486fd1b7e1565fd92Lennart Poettering m->hostname_fd = safe_close(m->hostname_fd);
eb60f9cd4e93ff5016dc1b5486fd1b7e1565fd92Lennart Poettering else
eb60f9cd4e93ff5016dc1b5486fd1b7e1565fd92Lennart Poettering return log_error_errno(r, "Failed to add hostname event source: %m");
eb60f9cd4e93ff5016dc1b5486fd1b7e1565fd92Lennart Poettering }
56f64d95763a799ba4475daf44d8e9f72a1bd474Michal Schmidt
eb60f9cd4e93ff5016dc1b5486fd1b7e1565fd92Lennart Poettering r = determine_hostname(&m->llmnr_hostname, &m->mdns_hostname);
eb60f9cd4e93ff5016dc1b5486fd1b7e1565fd92Lennart Poettering if (r < 0) {
eb60f9cd4e93ff5016dc1b5486fd1b7e1565fd92Lennart Poettering log_info("Defaulting to hostname 'linux'.");
eb60f9cd4e93ff5016dc1b5486fd1b7e1565fd92Lennart Poettering m->llmnr_hostname = strdup("linux");
eb60f9cd4e93ff5016dc1b5486fd1b7e1565fd92Lennart Poettering if (!m->llmnr_hostname)
eb60f9cd4e93ff5016dc1b5486fd1b7e1565fd92Lennart Poettering return log_oom();
eb60f9cd4e93ff5016dc1b5486fd1b7e1565fd92Lennart Poettering
eb60f9cd4e93ff5016dc1b5486fd1b7e1565fd92Lennart Poettering m->mdns_hostname = strdup("linux.local");
8d3d7072e609ef0e0fb37e1d19a29307d58146c3Michal Schmidt if (!m->mdns_hostname)
8d3d7072e609ef0e0fb37e1d19a29307d58146c3Michal Schmidt return log_oom();
eb60f9cd4e93ff5016dc1b5486fd1b7e1565fd92Lennart Poettering } else
eb60f9cd4e93ff5016dc1b5486fd1b7e1565fd92Lennart Poettering log_info("Using system hostname '%s'.", m->llmnr_hostname);
aa4a9deb7d3db95ffb1fd18791be66f58d06a69eLennart Poettering
aa4a9deb7d3db95ffb1fd18791be66f58d06a69eLennart Poettering return 0;
78c6a153c47f8d597c827bdcaf8c4e42ac87f738Lennart Poettering}
eb60f9cd4e93ff5016dc1b5486fd1b7e1565fd92Lennart Poettering
eb60f9cd4e93ff5016dc1b5486fd1b7e1565fd92Lennart Poetteringstatic int manager_sigusr1(sd_event_source *s, const struct signalfd_siginfo *si, void *userdata) {
78c6a153c47f8d597c827bdcaf8c4e42ac87f738Lennart Poettering _cleanup_free_ char *buffer = NULL;
78c6a153c47f8d597c827bdcaf8c4e42ac87f738Lennart Poettering _cleanup_fclose_ FILE *f = NULL;
78c6a153c47f8d597c827bdcaf8c4e42ac87f738Lennart Poettering Manager *m = userdata;
78c6a153c47f8d597c827bdcaf8c4e42ac87f738Lennart Poettering size_t size = 0;
78c6a153c47f8d597c827bdcaf8c4e42ac87f738Lennart Poettering DnsScope *scope;
78c6a153c47f8d597c827bdcaf8c4e42ac87f738Lennart Poettering
eb60f9cd4e93ff5016dc1b5486fd1b7e1565fd92Lennart Poettering assert(s);
eb60f9cd4e93ff5016dc1b5486fd1b7e1565fd92Lennart Poettering assert(si);
78c6a153c47f8d597c827bdcaf8c4e42ac87f738Lennart Poettering assert(m);
eb60f9cd4e93ff5016dc1b5486fd1b7e1565fd92Lennart Poettering
eb60f9cd4e93ff5016dc1b5486fd1b7e1565fd92Lennart Poettering f = open_memstream(&buffer, &size);
eb60f9cd4e93ff5016dc1b5486fd1b7e1565fd92Lennart Poettering if (!f)
eb60f9cd4e93ff5016dc1b5486fd1b7e1565fd92Lennart Poettering return log_oom();
4d506d6bb757af3b99e0876234c465e6898c5ea4Lennart Poettering
4d506d6bb757af3b99e0876234c465e6898c5ea4Lennart Poettering LIST_FOREACH(scopes, scope, m->dns_scopes)
4d506d6bb757af3b99e0876234c465e6898c5ea4Lennart Poettering dns_scope_dump(scope, f);
4d506d6bb757af3b99e0876234c465e6898c5ea4Lennart Poettering
4d506d6bb757af3b99e0876234c465e6898c5ea4Lennart Poettering if (fflush_and_check(f) < 0)
4d506d6bb757af3b99e0876234c465e6898c5ea4Lennart Poettering return log_oom();
4d506d6bb757af3b99e0876234c465e6898c5ea4Lennart Poettering
4d506d6bb757af3b99e0876234c465e6898c5ea4Lennart Poettering log_dump(LOG_INFO, buffer);
4d506d6bb757af3b99e0876234c465e6898c5ea4Lennart Poettering return 0;
4d506d6bb757af3b99e0876234c465e6898c5ea4Lennart Poettering}
4d506d6bb757af3b99e0876234c465e6898c5ea4Lennart Poettering
4d506d6bb757af3b99e0876234c465e6898c5ea4Lennart Poetteringint manager_new(Manager **ret) {
4d506d6bb757af3b99e0876234c465e6898c5ea4Lennart Poettering _cleanup_(manager_freep) Manager *m = NULL;
4d506d6bb757af3b99e0876234c465e6898c5ea4Lennart Poettering int r;
4d506d6bb757af3b99e0876234c465e6898c5ea4Lennart Poettering
4d506d6bb757af3b99e0876234c465e6898c5ea4Lennart Poettering assert(ret);
4d506d6bb757af3b99e0876234c465e6898c5ea4Lennart Poettering
4d506d6bb757af3b99e0876234c465e6898c5ea4Lennart Poettering m = new0(Manager, 1);
4d506d6bb757af3b99e0876234c465e6898c5ea4Lennart Poettering if (!m)
4d506d6bb757af3b99e0876234c465e6898c5ea4Lennart Poettering return -ENOMEM;
4d506d6bb757af3b99e0876234c465e6898c5ea4Lennart Poettering
4d506d6bb757af3b99e0876234c465e6898c5ea4Lennart Poettering m->llmnr_ipv4_udp_fd = m->llmnr_ipv6_udp_fd = -1;
4d506d6bb757af3b99e0876234c465e6898c5ea4Lennart Poettering m->llmnr_ipv4_tcp_fd = m->llmnr_ipv6_tcp_fd = -1;
4d506d6bb757af3b99e0876234c465e6898c5ea4Lennart Poettering m->hostname_fd = -1;
4d506d6bb757af3b99e0876234c465e6898c5ea4Lennart Poettering
091a364c802e34a58f3260c9cb5db9b75c62215cTom Gundersen m->llmnr_support = SUPPORT_YES;
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering m->read_resolv_conf = true;
091a364c802e34a58f3260c9cb5db9b75c62215cTom Gundersen
091a364c802e34a58f3260c9cb5db9b75c62215cTom Gundersen r = manager_parse_dns_server(m, DNS_SERVER_FALLBACK, DNS_SERVERS);
c92e531c82a9815ec349aa1bf31236b86b2d5311Lennart Poettering if (r < 0)
c92e531c82a9815ec349aa1bf31236b86b2d5311Lennart Poettering return r;
091a364c802e34a58f3260c9cb5db9b75c62215cTom Gundersen
091a364c802e34a58f3260c9cb5db9b75c62215cTom Gundersen r = sd_event_default(&m->event);
091a364c802e34a58f3260c9cb5db9b75c62215cTom Gundersen if (r < 0)
091a364c802e34a58f3260c9cb5db9b75c62215cTom Gundersen return r;
1716f6dcf54d4c181c2e2558e3d5414f54c8d9caLennart Poettering
623a4c97b9175f95c4b1c6fc34e36c56f1e4ddbfLennart Poettering sd_event_add_signal(m->event, NULL, SIGTERM, NULL, NULL);
bc7702b098b63031767174206f5df14a8ccb45cfDaniel Mack sd_event_add_signal(m->event, NULL, SIGINT, NULL, NULL);
eb60f9cd4e93ff5016dc1b5486fd1b7e1565fd92Lennart Poettering
1716f6dcf54d4c181c2e2558e3d5414f54c8d9caLennart Poettering sd_event_set_watchdog(m->event, true);
af49ca27ffd790d78dbbb465b978266dfd5c93daLennart Poettering
ad6c04756115809d615dede330213d73edf732a8Lennart Poettering r = manager_watch_hostname(m);
ad6c04756115809d615dede330213d73edf732a8Lennart Poettering if (r < 0)
5cb36f41f01cf4b1f4395abfffd1b33116591e58Lennart Poettering return r;
00fa60ae3b2823036cb3e7734f16bce30cb7441dLennart Poettering
dd0bc0f1414cc1d0fa73a29470bd14944e4942d3Lennart Poettering r = dns_scope_new(m, &m->unicast_scope, NULL, DNS_PROTOCOL_DNS, AF_UNSPEC);
091a364c802e34a58f3260c9cb5db9b75c62215cTom Gundersen if (r < 0)
0d2cd47617b423f37d7425be7a56ae2fca8ff9f6Lennart Poettering return r;
0d2cd47617b423f37d7425be7a56ae2fca8ff9f6Lennart Poettering
0d2cd47617b423f37d7425be7a56ae2fca8ff9f6Lennart Poettering r = manager_network_monitor_listen(m);
0d2cd47617b423f37d7425be7a56ae2fca8ff9f6Lennart Poettering if (r < 0)
ad6c04756115809d615dede330213d73edf732a8Lennart Poettering return r;
ad6c04756115809d615dede330213d73edf732a8Lennart Poettering
ad6c04756115809d615dede330213d73edf732a8Lennart Poettering r = manager_rtnl_listen(m);
ad6c04756115809d615dede330213d73edf732a8Lennart Poettering if (r < 0)
091a364c802e34a58f3260c9cb5db9b75c62215cTom Gundersen return r;
091a364c802e34a58f3260c9cb5db9b75c62215cTom Gundersen
091a364c802e34a58f3260c9cb5db9b75c62215cTom Gundersen r = manager_connect_bus(m);
091a364c802e34a58f3260c9cb5db9b75c62215cTom Gundersen if (r < 0)
091a364c802e34a58f3260c9cb5db9b75c62215cTom Gundersen return r;
091a364c802e34a58f3260c9cb5db9b75c62215cTom Gundersen
091a364c802e34a58f3260c9cb5db9b75c62215cTom Gundersen (void) sd_event_add_signal(m->event, &m->sigusr1_event_source, SIGUSR1, manager_sigusr1, m);
091a364c802e34a58f3260c9cb5db9b75c62215cTom Gundersen
091a364c802e34a58f3260c9cb5db9b75c62215cTom Gundersen *ret = m;
eb60f9cd4e93ff5016dc1b5486fd1b7e1565fd92Lennart Poettering m = NULL;
eb60f9cd4e93ff5016dc1b5486fd1b7e1565fd92Lennart Poettering
eb60f9cd4e93ff5016dc1b5486fd1b7e1565fd92Lennart Poettering return 0;
eb60f9cd4e93ff5016dc1b5486fd1b7e1565fd92Lennart Poettering}
1716f6dcf54d4c181c2e2558e3d5414f54c8d9caLennart Poettering
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poetteringint manager_start(Manager *m) {
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering int r;
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering assert(m);
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering r = manager_llmnr_start(m);
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering if (r < 0)
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering return r;
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering return 0;
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering}
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart PoetteringManager *manager_free(Manager *m) {
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering Link *l;
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering
4d506d6bb757af3b99e0876234c465e6898c5ea4Lennart Poettering if (!m)
4d506d6bb757af3b99e0876234c465e6898c5ea4Lennart Poettering return NULL;
091a364c802e34a58f3260c9cb5db9b75c62215cTom Gundersen
091a364c802e34a58f3260c9cb5db9b75c62215cTom Gundersen while ((l = hashmap_first(m->links)))
091a364c802e34a58f3260c9cb5db9b75c62215cTom Gundersen link_free(l);
091a364c802e34a58f3260c9cb5db9b75c62215cTom Gundersen
091a364c802e34a58f3260c9cb5db9b75c62215cTom Gundersen while (m->dns_queries)
091a364c802e34a58f3260c9cb5db9b75c62215cTom Gundersen dns_query_free(m->dns_queries);
edc501d4674dadc304d45a7e1c5b69e207eb8cd4Lennart Poettering
edc501d4674dadc304d45a7e1c5b69e207eb8cd4Lennart Poettering manager_flush_dns_servers(m, DNS_SERVER_SYSTEM);
edc501d4674dadc304d45a7e1c5b69e207eb8cd4Lennart Poettering manager_flush_dns_servers(m, DNS_SERVER_FALLBACK);
edc501d4674dadc304d45a7e1c5b69e207eb8cd4Lennart Poettering
edc501d4674dadc304d45a7e1c5b69e207eb8cd4Lennart Poettering dns_scope_free(m->unicast_scope);
edc501d4674dadc304d45a7e1c5b69e207eb8cd4Lennart Poettering
edc501d4674dadc304d45a7e1c5b69e207eb8cd4Lennart Poettering hashmap_free(m->links);
edc501d4674dadc304d45a7e1c5b69e207eb8cd4Lennart Poettering hashmap_free(m->dns_transactions);
edc501d4674dadc304d45a7e1c5b69e207eb8cd4Lennart Poettering
bc7702b098b63031767174206f5df14a8ccb45cfDaniel Mack sd_event_source_unref(m->network_event_source);
bc7702b098b63031767174206f5df14a8ccb45cfDaniel Mack sd_network_monitor_unref(m->network_monitor);
bc7702b098b63031767174206f5df14a8ccb45cfDaniel Mack
bc7702b098b63031767174206f5df14a8ccb45cfDaniel Mack manager_llmnr_stop(m);
edc501d4674dadc304d45a7e1c5b69e207eb8cd4Lennart Poettering
edc501d4674dadc304d45a7e1c5b69e207eb8cd4Lennart Poettering sd_bus_slot_unref(m->prepare_for_sleep_slot);
edc501d4674dadc304d45a7e1c5b69e207eb8cd4Lennart Poettering sd_event_source_unref(m->bus_retry_event_source);
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering sd_bus_unref(m->bus);
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering
091a364c802e34a58f3260c9cb5db9b75c62215cTom Gundersen sd_event_source_unref(m->sigusr1_event_source);
091a364c802e34a58f3260c9cb5db9b75c62215cTom Gundersen
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering sd_event_unref(m->event);
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering
4b95f1798f22c1bb75295f448188560cb6ec9eceLennart Poettering dns_resource_key_unref(m->llmnr_host_ipv4_key);
4b95f1798f22c1bb75295f448188560cb6ec9eceLennart Poettering dns_resource_key_unref(m->llmnr_host_ipv6_key);
a51c10485af349eb15faa4d1a63b9818bcf3e589Lennart Poettering
a51c10485af349eb15faa4d1a63b9818bcf3e589Lennart Poettering sd_event_source_unref(m->hostname_event_source);
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering safe_close(m->hostname_fd);
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering free(m->llmnr_hostname);
f0e1546763304aedc90e91d70dab9eeb7c966cf8Lennart Poettering free(m->mdns_hostname);
f0e1546763304aedc90e91d70dab9eeb7c966cf8Lennart Poettering
f0e1546763304aedc90e91d70dab9eeb7c966cf8Lennart Poettering free(m);
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering
cab5b05903096e1c9cf5575ccc73f89d15c8db69Lennart Poettering return NULL;
cab5b05903096e1c9cf5575ccc73f89d15c8db69Lennart Poettering}
f0e1546763304aedc90e91d70dab9eeb7c966cf8Lennart Poettering
f0e1546763304aedc90e91d70dab9eeb7c966cf8Lennart Poetteringint manager_read_resolv_conf(Manager *m) {
f0e1546763304aedc90e91d70dab9eeb7c966cf8Lennart Poettering _cleanup_fclose_ FILE *f = NULL;
096b6773886bd7a0c8c97aa684b0b67dfae58355Lennart Poettering struct stat st, own;
096b6773886bd7a0c8c97aa684b0b67dfae58355Lennart Poettering char line[LINE_MAX];
091a364c802e34a58f3260c9cb5db9b75c62215cTom Gundersen DnsServer *s, *nx;
a564ca2fd113b2876e677beab60b38d50591e246Lennart Poettering usec_t t;
a564ca2fd113b2876e677beab60b38d50591e246Lennart Poettering int r;
a564ca2fd113b2876e677beab60b38d50591e246Lennart Poettering
edc501d4674dadc304d45a7e1c5b69e207eb8cd4Lennart Poettering assert(m);
bc7702b098b63031767174206f5df14a8ccb45cfDaniel Mack
623a4c97b9175f95c4b1c6fc34e36c56f1e4ddbfLennart Poettering /* Reads the system /etc/resolv.conf, if it exists and is not
902bb5d8abb2a7d258741828d212ca549ab16950Lennart Poettering * symlinked to our own resolv.conf instance */
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering if (!m->read_resolv_conf)
091a364c802e34a58f3260c9cb5db9b75c62215cTom Gundersen return 0;
4d506d6bb757af3b99e0876234c465e6898c5ea4Lennart Poettering
4d506d6bb757af3b99e0876234c465e6898c5ea4Lennart Poettering r = stat("/etc/resolv.conf", &st);
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering if (r < 0) {
623a4c97b9175f95c4b1c6fc34e36c56f1e4ddbfLennart Poettering if (errno != ENOENT)
78c6a153c47f8d597c827bdcaf8c4e42ac87f738Lennart Poettering log_warning_errno(errno, "Failed to open /etc/resolv.conf: %m");
78c6a153c47f8d597c827bdcaf8c4e42ac87f738Lennart Poettering r = -errno;
eb60f9cd4e93ff5016dc1b5486fd1b7e1565fd92Lennart Poettering goto clear;
eb60f9cd4e93ff5016dc1b5486fd1b7e1565fd92Lennart Poettering }
d9fcf2ba1abe81ed3a7a151d6db09139b4dc7a09Lennart Poettering
78c6a153c47f8d597c827bdcaf8c4e42ac87f738Lennart Poettering /* Have we already seen the file? */
78c6a153c47f8d597c827bdcaf8c4e42ac87f738Lennart Poettering t = timespec_load(&st.st_mtim);
eb60f9cd4e93ff5016dc1b5486fd1b7e1565fd92Lennart Poettering if (t == m->resolv_conf_mtime)
0d2cd47617b423f37d7425be7a56ae2fca8ff9f6Lennart Poettering return 0;
dd0bc0f1414cc1d0fa73a29470bd14944e4942d3Lennart Poettering
0d2cd47617b423f37d7425be7a56ae2fca8ff9f6Lennart Poettering m->resolv_conf_mtime = t;
091a364c802e34a58f3260c9cb5db9b75c62215cTom Gundersen
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering /* Is it symlinked to our own file? */
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering if (stat("/run/systemd/resolve/resolv.conf", &own) >= 0 &&
091a364c802e34a58f3260c9cb5db9b75c62215cTom Gundersen st.st_dev == own.st_dev &&
091a364c802e34a58f3260c9cb5db9b75c62215cTom Gundersen st.st_ino == own.st_ino) {
1716f6dcf54d4c181c2e2558e3d5414f54c8d9caLennart Poettering r = 0;
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering goto clear;
1716f6dcf54d4c181c2e2558e3d5414f54c8d9caLennart Poettering }
1716f6dcf54d4c181c2e2558e3d5414f54c8d9caLennart Poettering
40a1eebde6be7ac3f1885147fc24e06ad1da260cDavid Herrmann f = fopen("/etc/resolv.conf", "re");
1716f6dcf54d4c181c2e2558e3d5414f54c8d9caLennart Poettering if (!f) {
623a4c97b9175f95c4b1c6fc34e36c56f1e4ddbfLennart Poettering if (errno != ENOENT)
1716f6dcf54d4c181c2e2558e3d5414f54c8d9caLennart Poettering log_warning_errno(errno, "Failed to open /etc/resolv.conf: %m");
1716f6dcf54d4c181c2e2558e3d5414f54c8d9caLennart Poettering r = -errno;
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering goto clear;
1716f6dcf54d4c181c2e2558e3d5414f54c8d9caLennart Poettering }
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering
1716f6dcf54d4c181c2e2558e3d5414f54c8d9caLennart Poettering if (fstat(fileno(f), &st) < 0) {
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering r = log_error_errno(errno, "Failed to stat open file: %m");
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering goto clear;
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering }
1716f6dcf54d4c181c2e2558e3d5414f54c8d9caLennart Poettering
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering LIST_FOREACH(servers, s, m->dns_servers)
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering s->marked = true;
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering FOREACH_LINE(line, f, r = -errno; goto clear) {
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering union in_addr_union address;
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering int family;
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering char *l;
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering const char *a;
1716f6dcf54d4c181c2e2558e3d5414f54c8d9caLennart Poettering
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering truncate_nl(line);
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering l = strstrip(line);
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering if (*l == '#' || *l == ';')
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering continue;
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering
1716f6dcf54d4c181c2e2558e3d5414f54c8d9caLennart Poettering a = first_word(l, "nameserver");
1716f6dcf54d4c181c2e2558e3d5414f54c8d9caLennart Poettering if (!a)
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering continue;
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering
1716f6dcf54d4c181c2e2558e3d5414f54c8d9caLennart Poettering r = in_addr_from_string_auto(a, &family, &address);
1716f6dcf54d4c181c2e2558e3d5414f54c8d9caLennart Poettering if (r < 0) {
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering log_warning("Failed to parse name server %s.", a);
a38d99451f2bf8026ec51aee91662292e823c6a8Lennart Poettering continue;
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering }
ad867662936a4c7ab2c7116d804c272338801231Lennart Poettering
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering LIST_FOREACH(servers, s, m->dns_servers)
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering if (s->family == family && in_addr_equal(family, &s->address, &address) > 0)
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering break;
091a364c802e34a58f3260c9cb5db9b75c62215cTom Gundersen
091a364c802e34a58f3260c9cb5db9b75c62215cTom Gundersen if (s)
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering s->marked = false;
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering else {
091a364c802e34a58f3260c9cb5db9b75c62215cTom Gundersen r = dns_server_new(m, NULL, DNS_SERVER_SYSTEM, NULL, family, &address);
1716f6dcf54d4c181c2e2558e3d5414f54c8d9caLennart Poettering if (r < 0)
1716f6dcf54d4c181c2e2558e3d5414f54c8d9caLennart Poettering goto clear;
1716f6dcf54d4c181c2e2558e3d5414f54c8d9caLennart Poettering }
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering }
091a364c802e34a58f3260c9cb5db9b75c62215cTom Gundersen
1716f6dcf54d4c181c2e2558e3d5414f54c8d9caLennart Poettering LIST_FOREACH_SAFE(servers, s, nx, m->dns_servers)
623a4c97b9175f95c4b1c6fc34e36c56f1e4ddbfLennart Poettering if (s->marked) {
623a4c97b9175f95c4b1c6fc34e36c56f1e4ddbfLennart Poettering LIST_REMOVE(servers, m->dns_servers, s);
1716f6dcf54d4c181c2e2558e3d5414f54c8d9caLennart Poettering dns_server_unref(s);
623a4c97b9175f95c4b1c6fc34e36c56f1e4ddbfLennart Poettering }
623a4c97b9175f95c4b1c6fc34e36c56f1e4ddbfLennart Poettering
1716f6dcf54d4c181c2e2558e3d5414f54c8d9caLennart Poettering /* Whenever /etc/resolv.conf changes, start using the first
623a4c97b9175f95c4b1c6fc34e36c56f1e4ddbfLennart Poettering * DNS server of it. This is useful to deal with broken
623a4c97b9175f95c4b1c6fc34e36c56f1e4ddbfLennart Poettering * network managing implementations (like NetworkManager),
623a4c97b9175f95c4b1c6fc34e36c56f1e4ddbfLennart Poettering * that when connecting to a VPN place both the VPN DNS
1716f6dcf54d4c181c2e2558e3d5414f54c8d9caLennart Poettering * servers and the local ones in /etc/resolv.conf. Without
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering * resetting the DNS server to use back to the first entry we
2a1288ff89322a2f49c79f6d1832c8164c14a05cLennart Poettering * will continue to use the local one thus being unable to
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering * resolve VPN domains. */
1716f6dcf54d4c181c2e2558e3d5414f54c8d9caLennart Poettering manager_set_dns_server(m, m->dns_servers);
1716f6dcf54d4c181c2e2558e3d5414f54c8d9caLennart Poettering
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering return 0;
1716f6dcf54d4c181c2e2558e3d5414f54c8d9caLennart Poettering
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poetteringclear:
1716f6dcf54d4c181c2e2558e3d5414f54c8d9caLennart Poettering while (m->dns_servers) {
1716f6dcf54d4c181c2e2558e3d5414f54c8d9caLennart Poettering s = m->dns_servers;
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering
623a4c97b9175f95c4b1c6fc34e36c56f1e4ddbfLennart Poettering LIST_REMOVE(servers, m->dns_servers, s);
623a4c97b9175f95c4b1c6fc34e36c56f1e4ddbfLennart Poettering dns_server_unref(s);
623a4c97b9175f95c4b1c6fc34e36c56f1e4ddbfLennart Poettering }
1716f6dcf54d4c181c2e2558e3d5414f54c8d9caLennart Poettering
1716f6dcf54d4c181c2e2558e3d5414f54c8d9caLennart Poettering return r;
1716f6dcf54d4c181c2e2558e3d5414f54c8d9caLennart Poettering}
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering
1716f6dcf54d4c181c2e2558e3d5414f54c8d9caLennart Poetteringstatic void write_resolv_conf_server(DnsServer *s, FILE *f, unsigned *count) {
1716f6dcf54d4c181c2e2558e3d5414f54c8d9caLennart Poettering _cleanup_free_ char *t = NULL;
1716f6dcf54d4c181c2e2558e3d5414f54c8d9caLennart Poettering int r;
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering
1716f6dcf54d4c181c2e2558e3d5414f54c8d9caLennart Poettering assert(s);
1716f6dcf54d4c181c2e2558e3d5414f54c8d9caLennart Poettering assert(f);
1716f6dcf54d4c181c2e2558e3d5414f54c8d9caLennart Poettering assert(count);
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering
1716f6dcf54d4c181c2e2558e3d5414f54c8d9caLennart Poettering r = in_addr_to_string(s->family, &s->address, &t);
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering if (r < 0) {
1716f6dcf54d4c181c2e2558e3d5414f54c8d9caLennart Poettering log_warning_errno(r, "Invalid DNS address. Ignoring: %m");
1716f6dcf54d4c181c2e2558e3d5414f54c8d9caLennart Poettering return;
091a364c802e34a58f3260c9cb5db9b75c62215cTom Gundersen }
623a4c97b9175f95c4b1c6fc34e36c56f1e4ddbfLennart Poettering
623a4c97b9175f95c4b1c6fc34e36c56f1e4ddbfLennart Poettering if (*count == MAXNS)
623a4c97b9175f95c4b1c6fc34e36c56f1e4ddbfLennart Poettering fputs("# Too many DNS servers configured, the following entries may be ignored.\n", f);
1716f6dcf54d4c181c2e2558e3d5414f54c8d9caLennart Poettering
1716f6dcf54d4c181c2e2558e3d5414f54c8d9caLennart Poettering fprintf(f, "nameserver %s\n", t);
1716f6dcf54d4c181c2e2558e3d5414f54c8d9caLennart Poettering (*count) ++;
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering}
623a4c97b9175f95c4b1c6fc34e36c56f1e4ddbfLennart Poettering
1716f6dcf54d4c181c2e2558e3d5414f54c8d9caLennart Poetteringstatic void write_resolv_conf_search(
1716f6dcf54d4c181c2e2558e3d5414f54c8d9caLennart Poettering const char *domain, FILE *f,
1716f6dcf54d4c181c2e2558e3d5414f54c8d9caLennart Poettering unsigned *count,
1716f6dcf54d4c181c2e2558e3d5414f54c8d9caLennart Poettering unsigned *length) {
1716f6dcf54d4c181c2e2558e3d5414f54c8d9caLennart Poettering
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering assert(domain);
623a4c97b9175f95c4b1c6fc34e36c56f1e4ddbfLennart Poettering assert(f);
623a4c97b9175f95c4b1c6fc34e36c56f1e4ddbfLennart Poettering assert(length);
623a4c97b9175f95c4b1c6fc34e36c56f1e4ddbfLennart Poettering
623a4c97b9175f95c4b1c6fc34e36c56f1e4ddbfLennart Poettering if (*count >= MAXDNSRCH ||
a5f035960006556beab51c42e6948985635e261aLennart Poettering *length + strlen(domain) > 256) {
623a4c97b9175f95c4b1c6fc34e36c56f1e4ddbfLennart Poettering if (*count == MAXDNSRCH)
623a4c97b9175f95c4b1c6fc34e36c56f1e4ddbfLennart Poettering fputs(" # Too many search domains configured, remaining ones ignored.", f);
86ad4cd709ced8daf2b75ab564dece1ce82ffed9Tom Gundersen if (*length <= 256)
86ad4cd709ced8daf2b75ab564dece1ce82ffed9Tom Gundersen fputs(" # Total length of all search domains is too long, remaining ones ignored.", f);
86ad4cd709ced8daf2b75ab564dece1ce82ffed9Tom Gundersen
86ad4cd709ced8daf2b75ab564dece1ce82ffed9Tom Gundersen return;
86ad4cd709ced8daf2b75ab564dece1ce82ffed9Tom Gundersen }
86ad4cd709ced8daf2b75ab564dece1ce82ffed9Tom Gundersen
623a4c97b9175f95c4b1c6fc34e36c56f1e4ddbfLennart Poettering fprintf(f, " %s", domain);
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering (*length) += strlen(domain);
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering (*count) ++;
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering}
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poetteringstatic int write_resolv_conf_contents(FILE *f, OrderedSet *dns, OrderedSet *domains) {
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering Iterator i;
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering fputs("# This file is managed by systemd-resolved(8). Do not edit.\n#\n"
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering "# Third party programs must not access this file directly, but\n"
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering "# only through the symlink at /etc/resolv.conf. To manage\n"
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering "# resolv.conf(5) in a different way, replace the symlink by a\n"
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering "# static file or a different symlink.\n\n", f);
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering if (ordered_set_isempty(dns))
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering fputs("# No DNS servers known.\n", f);
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering else {
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering DnsServer *s;
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering unsigned count = 0;
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering ORDERED_SET_FOREACH(s, dns, i)
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering write_resolv_conf_server(s, f, &count);
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering }
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering if (!ordered_set_isempty(domains)) {
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering unsigned length = 0, count = 0;
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering char *domain;
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering fputs("search", f);
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering ORDERED_SET_FOREACH(domain, domains, i)
72290734be81e83e6ef9520c07692f68095eb5b2Tom Gundersen write_resolv_conf_search(domain, f, &count, &length);
72290734be81e83e6ef9520c07692f68095eb5b2Tom Gundersen fputs("\n", f);
72290734be81e83e6ef9520c07692f68095eb5b2Tom Gundersen }
72290734be81e83e6ef9520c07692f68095eb5b2Tom Gundersen
72290734be81e83e6ef9520c07692f68095eb5b2Tom Gundersen return fflush_and_check(f);
72290734be81e83e6ef9520c07692f68095eb5b2Tom Gundersen}
72290734be81e83e6ef9520c07692f68095eb5b2Tom Gundersen
72290734be81e83e6ef9520c07692f68095eb5b2Tom Gundersenint manager_write_resolv_conf(Manager *m) {
72290734be81e83e6ef9520c07692f68095eb5b2Tom Gundersen static const char path[] = "/run/systemd/resolve/resolv.conf";
72290734be81e83e6ef9520c07692f68095eb5b2Tom Gundersen _cleanup_free_ char *temp_path = NULL;
72290734be81e83e6ef9520c07692f68095eb5b2Tom Gundersen _cleanup_fclose_ FILE *f = NULL;
72290734be81e83e6ef9520c07692f68095eb5b2Tom Gundersen _cleanup_ordered_set_free_ OrderedSet *dns = NULL, *domains = NULL;
72290734be81e83e6ef9520c07692f68095eb5b2Tom Gundersen DnsServer *s;
72290734be81e83e6ef9520c07692f68095eb5b2Tom Gundersen Iterator i;
72290734be81e83e6ef9520c07692f68095eb5b2Tom Gundersen Link *l;
72290734be81e83e6ef9520c07692f68095eb5b2Tom Gundersen int r;
72290734be81e83e6ef9520c07692f68095eb5b2Tom Gundersen
72290734be81e83e6ef9520c07692f68095eb5b2Tom Gundersen assert(m);
72290734be81e83e6ef9520c07692f68095eb5b2Tom Gundersen
72290734be81e83e6ef9520c07692f68095eb5b2Tom Gundersen /* Read the system /etc/resolv.conf first */
72290734be81e83e6ef9520c07692f68095eb5b2Tom Gundersen manager_read_resolv_conf(m);
72290734be81e83e6ef9520c07692f68095eb5b2Tom Gundersen
72290734be81e83e6ef9520c07692f68095eb5b2Tom Gundersen /* Add the full list to a set, to filter out duplicates */
72290734be81e83e6ef9520c07692f68095eb5b2Tom Gundersen dns = ordered_set_new(&dns_server_hash_ops);
72290734be81e83e6ef9520c07692f68095eb5b2Tom Gundersen if (!dns)
72290734be81e83e6ef9520c07692f68095eb5b2Tom Gundersen return -ENOMEM;
72290734be81e83e6ef9520c07692f68095eb5b2Tom Gundersen
deb3f3d335d64601bb2d8a7520d8303f99d8a071Lennart Poettering domains = ordered_set_new(&dns_name_hash_ops);
72290734be81e83e6ef9520c07692f68095eb5b2Tom Gundersen if (!domains)
72290734be81e83e6ef9520c07692f68095eb5b2Tom Gundersen return -ENOMEM;
72290734be81e83e6ef9520c07692f68095eb5b2Tom Gundersen
72290734be81e83e6ef9520c07692f68095eb5b2Tom Gundersen /* First add the system-wide servers */
72290734be81e83e6ef9520c07692f68095eb5b2Tom Gundersen LIST_FOREACH(servers, s, m->dns_servers) {
72290734be81e83e6ef9520c07692f68095eb5b2Tom Gundersen r = ordered_set_put(dns, s);
72290734be81e83e6ef9520c07692f68095eb5b2Tom Gundersen if (r == -EEXIST)
72290734be81e83e6ef9520c07692f68095eb5b2Tom Gundersen continue;
623a4c97b9175f95c4b1c6fc34e36c56f1e4ddbfLennart Poettering if (r < 0)
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering return r;
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering }
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering
1716f6dcf54d4c181c2e2558e3d5414f54c8d9caLennart Poettering /* Then, add the per-link servers and domains */
1716f6dcf54d4c181c2e2558e3d5414f54c8d9caLennart Poettering HASHMAP_FOREACH(l, m->links, i) {
1716f6dcf54d4c181c2e2558e3d5414f54c8d9caLennart Poettering char **domain;
1716f6dcf54d4c181c2e2558e3d5414f54c8d9caLennart Poettering
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering LIST_FOREACH(servers, s, l->dns_servers) {
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering r = ordered_set_put(dns, s);
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering if (r == -EEXIST)
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering continue;
1716f6dcf54d4c181c2e2558e3d5414f54c8d9caLennart Poettering if (r < 0)
1716f6dcf54d4c181c2e2558e3d5414f54c8d9caLennart Poettering return r;
1716f6dcf54d4c181c2e2558e3d5414f54c8d9caLennart Poettering }
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering if (!l->unicast_scope)
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering continue;
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering
091a364c802e34a58f3260c9cb5db9b75c62215cTom Gundersen STRV_FOREACH(domain, l->unicast_scope->domains) {
1716f6dcf54d4c181c2e2558e3d5414f54c8d9caLennart Poettering r = ordered_set_put(domains, *domain);
1716f6dcf54d4c181c2e2558e3d5414f54c8d9caLennart Poettering if (r == -EEXIST)
091a364c802e34a58f3260c9cb5db9b75c62215cTom Gundersen continue;
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering if (r < 0)
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering return r;
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering }
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering }
091a364c802e34a58f3260c9cb5db9b75c62215cTom Gundersen
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering /* If we found nothing, add the fallback servers */
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering if (ordered_set_isempty(dns)) {
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering LIST_FOREACH(servers, s, m->fallback_dns_servers) {
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering r = ordered_set_put(dns, s);
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering if (r == -EEXIST)
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering continue;
1716f6dcf54d4c181c2e2558e3d5414f54c8d9caLennart Poettering if (r < 0)
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering return r;
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering }
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering }
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering r = fopen_temporary_label(path, path, &f, &temp_path);
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering if (r < 0)
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering return r;
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering fchmod(fileno(f), 0644);
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering r = write_resolv_conf_contents(f, dns, domains);
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering if (r < 0)
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering goto fail;
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering
623a4c97b9175f95c4b1c6fc34e36c56f1e4ddbfLennart Poettering if (rename(temp_path, path) < 0) {
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering r = -errno;
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering goto fail;
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering }
1716f6dcf54d4c181c2e2558e3d5414f54c8d9caLennart Poettering
1716f6dcf54d4c181c2e2558e3d5414f54c8d9caLennart Poettering return 0;
1716f6dcf54d4c181c2e2558e3d5414f54c8d9caLennart Poettering
1716f6dcf54d4c181c2e2558e3d5414f54c8d9caLennart Poetteringfail:
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering (void) unlink(path);
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering (void) unlink(temp_path);
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering return r;
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering}
1716f6dcf54d4c181c2e2558e3d5414f54c8d9caLennart Poettering
1716f6dcf54d4c181c2e2558e3d5414f54c8d9caLennart Poetteringint manager_recv(Manager *m, int fd, DnsProtocol protocol, DnsPacket **ret) {
1716f6dcf54d4c181c2e2558e3d5414f54c8d9caLennart Poettering _cleanup_(dns_packet_unrefp) DnsPacket *p = NULL;
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering union {
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering struct cmsghdr header; /* For alignment */
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering uint8_t buffer[CMSG_SPACE(MAXSIZE(struct in_pktinfo, struct in6_pktinfo))
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering + CMSG_SPACE(int) /* ttl/hoplimit */
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering + EXTRA_CMSG_SPACE /* kernel appears to require extra buffer space */];
1716f6dcf54d4c181c2e2558e3d5414f54c8d9caLennart Poettering } control;
1716f6dcf54d4c181c2e2558e3d5414f54c8d9caLennart Poettering union sockaddr_union sa;
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering struct msghdr mh = {};
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering struct cmsghdr *cmsg;
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering struct iovec iov;
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering int ms = 0, r;
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering ssize_t l;
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering assert(m);
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering assert(fd >= 0);
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering assert(ret);
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering r = ioctl(fd, FIONREAD, &ms);
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering if (r < 0)
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering return -errno;
1716f6dcf54d4c181c2e2558e3d5414f54c8d9caLennart Poettering if (ms < 0)
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering return -EIO;
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering r = dns_packet_new(&p, protocol, ms);
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering if (r < 0)
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering return r;
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering iov.iov_base = DNS_PACKET_DATA(p);
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering iov.iov_len = p->allocated;
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering mh.msg_name = &sa.sa;
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering mh.msg_namelen = sizeof(sa);
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering mh.msg_iov = &iov;
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering mh.msg_iovlen = 1;
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering mh.msg_control = &control;
623a4c97b9175f95c4b1c6fc34e36c56f1e4ddbfLennart Poettering mh.msg_controllen = sizeof(control);
1716f6dcf54d4c181c2e2558e3d5414f54c8d9caLennart Poettering
1716f6dcf54d4c181c2e2558e3d5414f54c8d9caLennart Poettering l = recvmsg(fd, &mh, 0);
1716f6dcf54d4c181c2e2558e3d5414f54c8d9caLennart Poettering if (l < 0) {
1716f6dcf54d4c181c2e2558e3d5414f54c8d9caLennart Poettering if (errno == EAGAIN || errno == EINTR)
1716f6dcf54d4c181c2e2558e3d5414f54c8d9caLennart Poettering return 0;
1716f6dcf54d4c181c2e2558e3d5414f54c8d9caLennart Poettering
deb3f3d335d64601bb2d8a7520d8303f99d8a071Lennart Poettering return -errno;
a2a416f768e2aa7db5b975cd50eb19237cac9cceLennart Poettering }
1716f6dcf54d4c181c2e2558e3d5414f54c8d9caLennart Poettering
1716f6dcf54d4c181c2e2558e3d5414f54c8d9caLennart Poettering if (l <= 0)
1716f6dcf54d4c181c2e2558e3d5414f54c8d9caLennart Poettering return -EIO;
1716f6dcf54d4c181c2e2558e3d5414f54c8d9caLennart Poettering
1716f6dcf54d4c181c2e2558e3d5414f54c8d9caLennart Poettering assert(!(mh.msg_flags & MSG_CTRUNC));
1716f6dcf54d4c181c2e2558e3d5414f54c8d9caLennart Poettering assert(!(mh.msg_flags & MSG_TRUNC));
1716f6dcf54d4c181c2e2558e3d5414f54c8d9caLennart Poettering
1716f6dcf54d4c181c2e2558e3d5414f54c8d9caLennart Poettering p->size = (size_t) l;
e1c959948c0e31d6997bcdfbabfbd077784b2baeLennart Poettering
e1c959948c0e31d6997bcdfbabfbd077784b2baeLennart Poettering p->family = sa.sa.sa_family;
e1c959948c0e31d6997bcdfbabfbd077784b2baeLennart Poettering p->ipproto = IPPROTO_UDP;
e1c959948c0e31d6997bcdfbabfbd077784b2baeLennart Poettering if (p->family == AF_INET) {
e1c959948c0e31d6997bcdfbabfbd077784b2baeLennart Poettering p->sender.in = sa.in.sin_addr;
e1c959948c0e31d6997bcdfbabfbd077784b2baeLennart Poettering p->sender_port = be16toh(sa.in.sin_port);
e1c959948c0e31d6997bcdfbabfbd077784b2baeLennart Poettering } else if (p->family == AF_INET6) {
e1c959948c0e31d6997bcdfbabfbd077784b2baeLennart Poettering p->sender.in6 = sa.in6.sin6_addr;
e1c959948c0e31d6997bcdfbabfbd077784b2baeLennart Poettering p->sender_port = be16toh(sa.in6.sin6_port);
e1c959948c0e31d6997bcdfbabfbd077784b2baeLennart Poettering p->ifindex = sa.in6.sin6_scope_id;
e1c959948c0e31d6997bcdfbabfbd077784b2baeLennart Poettering } else
e1c959948c0e31d6997bcdfbabfbd077784b2baeLennart Poettering return -EAFNOSUPPORT;
e1c959948c0e31d6997bcdfbabfbd077784b2baeLennart Poettering
e1c959948c0e31d6997bcdfbabfbd077784b2baeLennart Poettering CMSG_FOREACH(cmsg, &mh) {
e1c959948c0e31d6997bcdfbabfbd077784b2baeLennart Poettering
e1c959948c0e31d6997bcdfbabfbd077784b2baeLennart Poettering if (cmsg->cmsg_level == IPPROTO_IPV6) {
e1c959948c0e31d6997bcdfbabfbd077784b2baeLennart Poettering assert(p->family == AF_INET6);
e1c959948c0e31d6997bcdfbabfbd077784b2baeLennart Poettering
e1c959948c0e31d6997bcdfbabfbd077784b2baeLennart Poettering switch (cmsg->cmsg_type) {
1716f6dcf54d4c181c2e2558e3d5414f54c8d9caLennart Poettering
623a4c97b9175f95c4b1c6fc34e36c56f1e4ddbfLennart Poettering case IPV6_PKTINFO: {
ec2c5e4398f9d65e5dfe61530f2556224733d1e6Lennart Poettering struct in6_pktinfo *i = (struct in6_pktinfo*) CMSG_DATA(cmsg);
ec2c5e4398f9d65e5dfe61530f2556224733d1e6Lennart Poettering
ec2c5e4398f9d65e5dfe61530f2556224733d1e6Lennart Poettering if (p->ifindex <= 0)
ec2c5e4398f9d65e5dfe61530f2556224733d1e6Lennart Poettering p->ifindex = i->ipi6_ifindex;
4e945a6f7971fd7d1f6b2c62ee3afdaff3c95ce4Lennart Poettering
ec2c5e4398f9d65e5dfe61530f2556224733d1e6Lennart Poettering p->destination.in6 = i->ipi6_addr;
ec2c5e4398f9d65e5dfe61530f2556224733d1e6Lennart Poettering break;
ec2c5e4398f9d65e5dfe61530f2556224733d1e6Lennart Poettering }
ec2c5e4398f9d65e5dfe61530f2556224733d1e6Lennart Poettering
ec2c5e4398f9d65e5dfe61530f2556224733d1e6Lennart Poettering case IPV6_HOPLIMIT:
ec2c5e4398f9d65e5dfe61530f2556224733d1e6Lennart Poettering p->ttl = *(int *) CMSG_DATA(cmsg);
eb60f9cd4e93ff5016dc1b5486fd1b7e1565fd92Lennart Poettering break;
eb60f9cd4e93ff5016dc1b5486fd1b7e1565fd92Lennart Poettering
eb60f9cd4e93ff5016dc1b5486fd1b7e1565fd92Lennart Poettering }
eb60f9cd4e93ff5016dc1b5486fd1b7e1565fd92Lennart Poettering } else if (cmsg->cmsg_level == IPPROTO_IP) {
eb60f9cd4e93ff5016dc1b5486fd1b7e1565fd92Lennart Poettering assert(p->family == AF_INET);
eb60f9cd4e93ff5016dc1b5486fd1b7e1565fd92Lennart Poettering
78c6a153c47f8d597c827bdcaf8c4e42ac87f738Lennart Poettering switch (cmsg->cmsg_type) {
78c6a153c47f8d597c827bdcaf8c4e42ac87f738Lennart Poettering
eb60f9cd4e93ff5016dc1b5486fd1b7e1565fd92Lennart Poettering case IP_PKTINFO: {
eb60f9cd4e93ff5016dc1b5486fd1b7e1565fd92Lennart Poettering struct in_pktinfo *i = (struct in_pktinfo*) CMSG_DATA(cmsg);
eb60f9cd4e93ff5016dc1b5486fd1b7e1565fd92Lennart Poettering
eb60f9cd4e93ff5016dc1b5486fd1b7e1565fd92Lennart Poettering if (p->ifindex <= 0)
eb60f9cd4e93ff5016dc1b5486fd1b7e1565fd92Lennart Poettering p->ifindex = i->ipi_ifindex;
eb60f9cd4e93ff5016dc1b5486fd1b7e1565fd92Lennart Poettering
eb60f9cd4e93ff5016dc1b5486fd1b7e1565fd92Lennart Poettering p->destination.in = i->ipi_addr;
ec2c5e4398f9d65e5dfe61530f2556224733d1e6Lennart Poettering break;
ec2c5e4398f9d65e5dfe61530f2556224733d1e6Lennart Poettering }
556a22945fcc88ca27ae7ecc46c9bb2727e37895Lennart Poettering
78c6a153c47f8d597c827bdcaf8c4e42ac87f738Lennart Poettering case IP_TTL:
78c6a153c47f8d597c827bdcaf8c4e42ac87f738Lennart Poettering p->ttl = *(int *) CMSG_DATA(cmsg);
623a4c97b9175f95c4b1c6fc34e36c56f1e4ddbfLennart Poettering break;
623a4c97b9175f95c4b1c6fc34e36c56f1e4ddbfLennart Poettering }
623a4c97b9175f95c4b1c6fc34e36c56f1e4ddbfLennart Poettering }
78c6a153c47f8d597c827bdcaf8c4e42ac87f738Lennart Poettering }
ec2c5e4398f9d65e5dfe61530f2556224733d1e6Lennart Poettering
ec2c5e4398f9d65e5dfe61530f2556224733d1e6Lennart Poettering /* The Linux kernel sets the interface index to the loopback
78c6a153c47f8d597c827bdcaf8c4e42ac87f738Lennart Poettering * device if the packet came from the local host since it
ec2c5e4398f9d65e5dfe61530f2556224733d1e6Lennart Poettering * avoids the routing table in such a case. Let's unset the
ec2c5e4398f9d65e5dfe61530f2556224733d1e6Lennart Poettering * interface index in such a case. */
ec2c5e4398f9d65e5dfe61530f2556224733d1e6Lennart Poettering if (p->ifindex == LOOPBACK_IFINDEX)
ec2c5e4398f9d65e5dfe61530f2556224733d1e6Lennart Poettering p->ifindex = 0;
ec2c5e4398f9d65e5dfe61530f2556224733d1e6Lennart Poettering
ec2c5e4398f9d65e5dfe61530f2556224733d1e6Lennart Poettering if (protocol != DNS_PROTOCOL_DNS) {
ec2c5e4398f9d65e5dfe61530f2556224733d1e6Lennart Poettering /* If we don't know the interface index still, we look for the
ec2c5e4398f9d65e5dfe61530f2556224733d1e6Lennart Poettering * first local interface with a matching address. Yuck! */
ec2c5e4398f9d65e5dfe61530f2556224733d1e6Lennart Poettering if (p->ifindex <= 0)
556a22945fcc88ca27ae7ecc46c9bb2727e37895Lennart Poettering p->ifindex = manager_find_ifindex(m, p->family, &p->destination);
556a22945fcc88ca27ae7ecc46c9bb2727e37895Lennart Poettering }
556a22945fcc88ca27ae7ecc46c9bb2727e37895Lennart Poettering
556a22945fcc88ca27ae7ecc46c9bb2727e37895Lennart Poettering *ret = p;
556a22945fcc88ca27ae7ecc46c9bb2727e37895Lennart Poettering p = NULL;
556a22945fcc88ca27ae7ecc46c9bb2727e37895Lennart Poettering
556a22945fcc88ca27ae7ecc46c9bb2727e37895Lennart Poettering return 1;
556a22945fcc88ca27ae7ecc46c9bb2727e37895Lennart Poettering}
556a22945fcc88ca27ae7ecc46c9bb2727e37895Lennart Poettering
ec2c5e4398f9d65e5dfe61530f2556224733d1e6Lennart Poetteringstatic int sendmsg_loop(int fd, struct msghdr *mh, int flags) {
78c6a153c47f8d597c827bdcaf8c4e42ac87f738Lennart Poettering int r;
ec2c5e4398f9d65e5dfe61530f2556224733d1e6Lennart Poettering
ec2c5e4398f9d65e5dfe61530f2556224733d1e6Lennart Poettering assert(fd >= 0);
78c6a153c47f8d597c827bdcaf8c4e42ac87f738Lennart Poettering assert(mh);
78c6a153c47f8d597c827bdcaf8c4e42ac87f738Lennart Poettering
78c6a153c47f8d597c827bdcaf8c4e42ac87f738Lennart Poettering for (;;) {
78c6a153c47f8d597c827bdcaf8c4e42ac87f738Lennart Poettering if (sendmsg(fd, mh, flags) >= 0)
78c6a153c47f8d597c827bdcaf8c4e42ac87f738Lennart Poettering return 0;
78c6a153c47f8d597c827bdcaf8c4e42ac87f738Lennart Poettering
78c6a153c47f8d597c827bdcaf8c4e42ac87f738Lennart Poettering if (errno == EINTR)
78c6a153c47f8d597c827bdcaf8c4e42ac87f738Lennart Poettering continue;
78c6a153c47f8d597c827bdcaf8c4e42ac87f738Lennart Poettering
78c6a153c47f8d597c827bdcaf8c4e42ac87f738Lennart Poettering if (errno != EAGAIN)
ec2c5e4398f9d65e5dfe61530f2556224733d1e6Lennart Poettering return -errno;
78c6a153c47f8d597c827bdcaf8c4e42ac87f738Lennart Poettering
78c6a153c47f8d597c827bdcaf8c4e42ac87f738Lennart Poettering r = fd_wait_for_event(fd, POLLOUT, SEND_TIMEOUT_USEC);
ec2c5e4398f9d65e5dfe61530f2556224733d1e6Lennart Poettering if (r < 0)
eb60f9cd4e93ff5016dc1b5486fd1b7e1565fd92Lennart Poettering return r;
623a4c97b9175f95c4b1c6fc34e36c56f1e4ddbfLennart Poettering if (r == 0)
623a4c97b9175f95c4b1c6fc34e36c56f1e4ddbfLennart Poettering return -ETIMEDOUT;
623a4c97b9175f95c4b1c6fc34e36c56f1e4ddbfLennart Poettering }
ec2c5e4398f9d65e5dfe61530f2556224733d1e6Lennart Poettering}
4e945a6f7971fd7d1f6b2c62ee3afdaff3c95ce4Lennart Poettering
ec2c5e4398f9d65e5dfe61530f2556224733d1e6Lennart Poetteringstatic int write_loop(int fd, void *message, size_t length) {
ec2c5e4398f9d65e5dfe61530f2556224733d1e6Lennart Poettering int r;
ec2c5e4398f9d65e5dfe61530f2556224733d1e6Lennart Poettering
ec2c5e4398f9d65e5dfe61530f2556224733d1e6Lennart Poettering assert(fd >= 0);
ec2c5e4398f9d65e5dfe61530f2556224733d1e6Lennart Poettering assert(message);
ec2c5e4398f9d65e5dfe61530f2556224733d1e6Lennart Poettering
ec2c5e4398f9d65e5dfe61530f2556224733d1e6Lennart Poettering for (;;) {
ec2c5e4398f9d65e5dfe61530f2556224733d1e6Lennart Poettering if (write(fd, message, length) >= 0)
ec2c5e4398f9d65e5dfe61530f2556224733d1e6Lennart Poettering return 0;
ec2c5e4398f9d65e5dfe61530f2556224733d1e6Lennart Poettering
ec2c5e4398f9d65e5dfe61530f2556224733d1e6Lennart Poettering if (errno == EINTR)
ec2c5e4398f9d65e5dfe61530f2556224733d1e6Lennart Poettering continue;
ec2c5e4398f9d65e5dfe61530f2556224733d1e6Lennart Poettering
ec2c5e4398f9d65e5dfe61530f2556224733d1e6Lennart Poettering if (errno != EAGAIN)
ec2c5e4398f9d65e5dfe61530f2556224733d1e6Lennart Poettering return -errno;
ec2c5e4398f9d65e5dfe61530f2556224733d1e6Lennart Poettering
a407657425a3e47fd2b559cd3bc800f791303f63Lennart Poettering r = fd_wait_for_event(fd, POLLOUT, SEND_TIMEOUT_USEC);
ec2c5e4398f9d65e5dfe61530f2556224733d1e6Lennart Poettering if (r < 0)
ec2c5e4398f9d65e5dfe61530f2556224733d1e6Lennart Poettering return r;
ec2c5e4398f9d65e5dfe61530f2556224733d1e6Lennart Poettering if (r == 0)
4e945a6f7971fd7d1f6b2c62ee3afdaff3c95ce4Lennart Poettering return -ETIMEDOUT;
ec2c5e4398f9d65e5dfe61530f2556224733d1e6Lennart Poettering }
4e945a6f7971fd7d1f6b2c62ee3afdaff3c95ce4Lennart Poettering}
a407657425a3e47fd2b559cd3bc800f791303f63Lennart Poettering
a407657425a3e47fd2b559cd3bc800f791303f63Lennart Poetteringint manager_write(Manager *m, int fd, DnsPacket *p) {
a407657425a3e47fd2b559cd3bc800f791303f63Lennart Poettering int r;
a407657425a3e47fd2b559cd3bc800f791303f63Lennart Poettering
a407657425a3e47fd2b559cd3bc800f791303f63Lennart Poettering log_debug("Sending %s packet with id %u", DNS_PACKET_QR(p) ? "response" : "query", DNS_PACKET_ID(p));
a407657425a3e47fd2b559cd3bc800f791303f63Lennart Poettering
a407657425a3e47fd2b559cd3bc800f791303f63Lennart Poettering r = write_loop(fd, DNS_PACKET_DATA(p), p->size);
a407657425a3e47fd2b559cd3bc800f791303f63Lennart Poettering if (r < 0)
a407657425a3e47fd2b559cd3bc800f791303f63Lennart Poettering return r;
a407657425a3e47fd2b559cd3bc800f791303f63Lennart Poettering
b4f1862df2e45aba90386887d685b8bf3c840e10Daniel Mack return 0;
b4f1862df2e45aba90386887d685b8bf3c840e10Daniel Mack}
a407657425a3e47fd2b559cd3bc800f791303f63Lennart Poettering
a407657425a3e47fd2b559cd3bc800f791303f63Lennart Poetteringstatic int manager_ipv4_send(Manager *m, int fd, int ifindex, const struct in_addr *addr, uint16_t port, DnsPacket *p) {
a407657425a3e47fd2b559cd3bc800f791303f63Lennart Poettering union sockaddr_union sa = {
a407657425a3e47fd2b559cd3bc800f791303f63Lennart Poettering .in.sin_family = AF_INET,
b4f1862df2e45aba90386887d685b8bf3c840e10Daniel Mack };
b4f1862df2e45aba90386887d685b8bf3c840e10Daniel Mack union {
b4f1862df2e45aba90386887d685b8bf3c840e10Daniel Mack struct cmsghdr header; /* For alignment */
b4f1862df2e45aba90386887d685b8bf3c840e10Daniel Mack uint8_t buffer[CMSG_SPACE(sizeof(struct in_pktinfo))];
b4f1862df2e45aba90386887d685b8bf3c840e10Daniel Mack } control;
b4f1862df2e45aba90386887d685b8bf3c840e10Daniel Mack struct msghdr mh = {};
b4f1862df2e45aba90386887d685b8bf3c840e10Daniel Mack struct iovec iov;
b4f1862df2e45aba90386887d685b8bf3c840e10Daniel Mack
b4f1862df2e45aba90386887d685b8bf3c840e10Daniel Mack assert(m);
b4f1862df2e45aba90386887d685b8bf3c840e10Daniel Mack assert(fd >= 0);
b4f1862df2e45aba90386887d685b8bf3c840e10Daniel Mack assert(addr);
b4f1862df2e45aba90386887d685b8bf3c840e10Daniel Mack assert(port > 0);
b4f1862df2e45aba90386887d685b8bf3c840e10Daniel Mack assert(p);
a407657425a3e47fd2b559cd3bc800f791303f63Lennart Poettering
a407657425a3e47fd2b559cd3bc800f791303f63Lennart Poettering iov.iov_base = DNS_PACKET_DATA(p);
a407657425a3e47fd2b559cd3bc800f791303f63Lennart Poettering iov.iov_len = p->size;
a407657425a3e47fd2b559cd3bc800f791303f63Lennart Poettering
a407657425a3e47fd2b559cd3bc800f791303f63Lennart Poettering sa.in.sin_addr = *addr;
902bb5d8abb2a7d258741828d212ca549ab16950Lennart Poettering sa.in.sin_port = htobe16(port),
902bb5d8abb2a7d258741828d212ca549ab16950Lennart Poettering
902bb5d8abb2a7d258741828d212ca549ab16950Lennart Poettering mh.msg_iov = &iov;
902bb5d8abb2a7d258741828d212ca549ab16950Lennart Poettering mh.msg_iovlen = 1;
902bb5d8abb2a7d258741828d212ca549ab16950Lennart Poettering mh.msg_name = &sa.sa;
902bb5d8abb2a7d258741828d212ca549ab16950Lennart Poettering mh.msg_namelen = sizeof(sa.in);
902bb5d8abb2a7d258741828d212ca549ab16950Lennart Poettering
902bb5d8abb2a7d258741828d212ca549ab16950Lennart Poettering if (ifindex > 0) {
902bb5d8abb2a7d258741828d212ca549ab16950Lennart Poettering struct cmsghdr *cmsg;
78c6a153c47f8d597c827bdcaf8c4e42ac87f738Lennart Poettering struct in_pktinfo *pi;
78c6a153c47f8d597c827bdcaf8c4e42ac87f738Lennart Poettering
78c6a153c47f8d597c827bdcaf8c4e42ac87f738Lennart Poettering zero(control);
78c6a153c47f8d597c827bdcaf8c4e42ac87f738Lennart Poettering
78c6a153c47f8d597c827bdcaf8c4e42ac87f738Lennart Poettering mh.msg_control = &control;
78c6a153c47f8d597c827bdcaf8c4e42ac87f738Lennart Poettering mh.msg_controllen = CMSG_LEN(sizeof(struct in_pktinfo));
78c6a153c47f8d597c827bdcaf8c4e42ac87f738Lennart Poettering
78c6a153c47f8d597c827bdcaf8c4e42ac87f738Lennart Poettering cmsg = CMSG_FIRSTHDR(&mh);
78c6a153c47f8d597c827bdcaf8c4e42ac87f738Lennart Poettering cmsg->cmsg_len = mh.msg_controllen;
78c6a153c47f8d597c827bdcaf8c4e42ac87f738Lennart Poettering cmsg->cmsg_level = IPPROTO_IP;
78c6a153c47f8d597c827bdcaf8c4e42ac87f738Lennart Poettering cmsg->cmsg_type = IP_PKTINFO;
78c6a153c47f8d597c827bdcaf8c4e42ac87f738Lennart Poettering
78c6a153c47f8d597c827bdcaf8c4e42ac87f738Lennart Poettering pi = (struct in_pktinfo*) CMSG_DATA(cmsg);
78c6a153c47f8d597c827bdcaf8c4e42ac87f738Lennart Poettering pi->ipi_ifindex = ifindex;
78c6a153c47f8d597c827bdcaf8c4e42ac87f738Lennart Poettering }
78c6a153c47f8d597c827bdcaf8c4e42ac87f738Lennart Poettering
78c6a153c47f8d597c827bdcaf8c4e42ac87f738Lennart Poettering return sendmsg_loop(fd, &mh, 0);
78c6a153c47f8d597c827bdcaf8c4e42ac87f738Lennart Poettering}
9176a57c101d51b4a7fb4141240b5ce03abac57dLennart Poettering
9176a57c101d51b4a7fb4141240b5ce03abac57dLennart Poetteringstatic int manager_ipv6_send(Manager *m, int fd, int ifindex, const struct in6_addr *addr, uint16_t port, DnsPacket *p) {
9176a57c101d51b4a7fb4141240b5ce03abac57dLennart Poettering union sockaddr_union sa = {
9176a57c101d51b4a7fb4141240b5ce03abac57dLennart Poettering .in6.sin6_family = AF_INET6,
9176a57c101d51b4a7fb4141240b5ce03abac57dLennart Poettering };
9176a57c101d51b4a7fb4141240b5ce03abac57dLennart Poettering union {
9176a57c101d51b4a7fb4141240b5ce03abac57dLennart Poettering struct cmsghdr header; /* For alignment */
9176a57c101d51b4a7fb4141240b5ce03abac57dLennart Poettering uint8_t buffer[CMSG_SPACE(sizeof(struct in6_pktinfo))];
9176a57c101d51b4a7fb4141240b5ce03abac57dLennart Poettering } control;
9176a57c101d51b4a7fb4141240b5ce03abac57dLennart Poettering struct msghdr mh = {};
9176a57c101d51b4a7fb4141240b5ce03abac57dLennart Poettering struct iovec iov;
9176a57c101d51b4a7fb4141240b5ce03abac57dLennart Poettering
9176a57c101d51b4a7fb4141240b5ce03abac57dLennart Poettering assert(m);
9176a57c101d51b4a7fb4141240b5ce03abac57dLennart Poettering assert(fd >= 0);
9176a57c101d51b4a7fb4141240b5ce03abac57dLennart Poettering assert(addr);
9176a57c101d51b4a7fb4141240b5ce03abac57dLennart Poettering assert(port > 0);
9176a57c101d51b4a7fb4141240b5ce03abac57dLennart Poettering assert(p);
9176a57c101d51b4a7fb4141240b5ce03abac57dLennart Poettering
9176a57c101d51b4a7fb4141240b5ce03abac57dLennart Poettering iov.iov_base = DNS_PACKET_DATA(p);
9176a57c101d51b4a7fb4141240b5ce03abac57dLennart Poettering iov.iov_len = p->size;
9176a57c101d51b4a7fb4141240b5ce03abac57dLennart Poettering
9176a57c101d51b4a7fb4141240b5ce03abac57dLennart Poettering sa.in6.sin6_addr = *addr;
9176a57c101d51b4a7fb4141240b5ce03abac57dLennart Poettering sa.in6.sin6_port = htobe16(port),
9176a57c101d51b4a7fb4141240b5ce03abac57dLennart Poettering sa.in6.sin6_scope_id = ifindex;
9176a57c101d51b4a7fb4141240b5ce03abac57dLennart Poettering
9176a57c101d51b4a7fb4141240b5ce03abac57dLennart Poettering mh.msg_iov = &iov;
9176a57c101d51b4a7fb4141240b5ce03abac57dLennart Poettering mh.msg_iovlen = 1;
9176a57c101d51b4a7fb4141240b5ce03abac57dLennart Poettering mh.msg_name = &sa.sa;
9176a57c101d51b4a7fb4141240b5ce03abac57dLennart Poettering mh.msg_namelen = sizeof(sa.in6);
9176a57c101d51b4a7fb4141240b5ce03abac57dLennart Poettering
9176a57c101d51b4a7fb4141240b5ce03abac57dLennart Poettering if (ifindex > 0) {
9176a57c101d51b4a7fb4141240b5ce03abac57dLennart Poettering struct cmsghdr *cmsg;
9176a57c101d51b4a7fb4141240b5ce03abac57dLennart Poettering struct in6_pktinfo *pi;
9176a57c101d51b4a7fb4141240b5ce03abac57dLennart Poettering
9176a57c101d51b4a7fb4141240b5ce03abac57dLennart Poettering zero(control);
9176a57c101d51b4a7fb4141240b5ce03abac57dLennart Poettering
9176a57c101d51b4a7fb4141240b5ce03abac57dLennart Poettering mh.msg_control = &control;
9176a57c101d51b4a7fb4141240b5ce03abac57dLennart Poettering mh.msg_controllen = CMSG_LEN(sizeof(struct in6_pktinfo));
9176a57c101d51b4a7fb4141240b5ce03abac57dLennart Poettering
9176a57c101d51b4a7fb4141240b5ce03abac57dLennart Poettering cmsg = CMSG_FIRSTHDR(&mh);
9176a57c101d51b4a7fb4141240b5ce03abac57dLennart Poettering cmsg->cmsg_len = mh.msg_controllen;
9176a57c101d51b4a7fb4141240b5ce03abac57dLennart Poettering cmsg->cmsg_level = IPPROTO_IPV6;
9176a57c101d51b4a7fb4141240b5ce03abac57dLennart Poettering cmsg->cmsg_type = IPV6_PKTINFO;
9176a57c101d51b4a7fb4141240b5ce03abac57dLennart Poettering
9176a57c101d51b4a7fb4141240b5ce03abac57dLennart Poettering pi = (struct in6_pktinfo*) CMSG_DATA(cmsg);
9176a57c101d51b4a7fb4141240b5ce03abac57dLennart Poettering pi->ipi6_ifindex = ifindex;
9176a57c101d51b4a7fb4141240b5ce03abac57dLennart Poettering }
9176a57c101d51b4a7fb4141240b5ce03abac57dLennart Poettering
9176a57c101d51b4a7fb4141240b5ce03abac57dLennart Poettering return sendmsg_loop(fd, &mh, 0);
9176a57c101d51b4a7fb4141240b5ce03abac57dLennart Poettering}
9176a57c101d51b4a7fb4141240b5ce03abac57dLennart Poettering
9176a57c101d51b4a7fb4141240b5ce03abac57dLennart Poetteringint manager_send(Manager *m, int fd, int ifindex, int family, const union in_addr_union *addr, uint16_t port, DnsPacket *p) {
9176a57c101d51b4a7fb4141240b5ce03abac57dLennart Poettering assert(m);
9176a57c101d51b4a7fb4141240b5ce03abac57dLennart Poettering assert(fd >= 0);
9176a57c101d51b4a7fb4141240b5ce03abac57dLennart Poettering assert(addr);
9176a57c101d51b4a7fb4141240b5ce03abac57dLennart Poettering assert(port > 0);
9176a57c101d51b4a7fb4141240b5ce03abac57dLennart Poettering assert(p);
9176a57c101d51b4a7fb4141240b5ce03abac57dLennart Poettering
9176a57c101d51b4a7fb4141240b5ce03abac57dLennart Poettering 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));
9176a57c101d51b4a7fb4141240b5ce03abac57dLennart Poettering
9176a57c101d51b4a7fb4141240b5ce03abac57dLennart Poettering if (family == AF_INET)
9176a57c101d51b4a7fb4141240b5ce03abac57dLennart Poettering return manager_ipv4_send(m, fd, ifindex, &addr->in, port, p);
9176a57c101d51b4a7fb4141240b5ce03abac57dLennart Poettering else if (family == AF_INET6)
9176a57c101d51b4a7fb4141240b5ce03abac57dLennart Poettering return manager_ipv6_send(m, fd, ifindex, &addr->in6, port, p);
9176a57c101d51b4a7fb4141240b5ce03abac57dLennart Poettering
9176a57c101d51b4a7fb4141240b5ce03abac57dLennart Poettering return -EAFNOSUPPORT;
9176a57c101d51b4a7fb4141240b5ce03abac57dLennart Poettering}
9176a57c101d51b4a7fb4141240b5ce03abac57dLennart Poettering
9176a57c101d51b4a7fb4141240b5ce03abac57dLennart PoetteringDnsServer* manager_find_dns_server(Manager *m, int family, const union in_addr_union *in_addr) {
9176a57c101d51b4a7fb4141240b5ce03abac57dLennart Poettering DnsServer *s;
9176a57c101d51b4a7fb4141240b5ce03abac57dLennart Poettering
9176a57c101d51b4a7fb4141240b5ce03abac57dLennart Poettering assert(m);
9176a57c101d51b4a7fb4141240b5ce03abac57dLennart Poettering assert(in_addr);
9176a57c101d51b4a7fb4141240b5ce03abac57dLennart Poettering
9176a57c101d51b4a7fb4141240b5ce03abac57dLennart Poettering LIST_FOREACH(servers, s, m->dns_servers)
9176a57c101d51b4a7fb4141240b5ce03abac57dLennart Poettering if (s->family == family && in_addr_equal(family, &s->address, in_addr) > 0)
9176a57c101d51b4a7fb4141240b5ce03abac57dLennart Poettering return s;
9176a57c101d51b4a7fb4141240b5ce03abac57dLennart Poettering
9176a57c101d51b4a7fb4141240b5ce03abac57dLennart Poettering LIST_FOREACH(servers, s, m->fallback_dns_servers)
9176a57c101d51b4a7fb4141240b5ce03abac57dLennart Poettering if (s->family == family && in_addr_equal(family, &s->address, in_addr) > 0)
9176a57c101d51b4a7fb4141240b5ce03abac57dLennart Poettering return s;
c69fa7e3c44240bedc0ee1bd89fecf954783ac85Lennart Poettering
c69fa7e3c44240bedc0ee1bd89fecf954783ac85Lennart Poettering return NULL;
c69fa7e3c44240bedc0ee1bd89fecf954783ac85Lennart Poettering}
c69fa7e3c44240bedc0ee1bd89fecf954783ac85Lennart Poettering
c69fa7e3c44240bedc0ee1bd89fecf954783ac85Lennart PoetteringDnsServer *manager_set_dns_server(Manager *m, DnsServer *s) {
c69fa7e3c44240bedc0ee1bd89fecf954783ac85Lennart Poettering assert(m);
c69fa7e3c44240bedc0ee1bd89fecf954783ac85Lennart Poettering
c69fa7e3c44240bedc0ee1bd89fecf954783ac85Lennart Poettering if (m->current_dns_server == s)
c69fa7e3c44240bedc0ee1bd89fecf954783ac85Lennart Poettering return s;
c69fa7e3c44240bedc0ee1bd89fecf954783ac85Lennart Poettering
c69fa7e3c44240bedc0ee1bd89fecf954783ac85Lennart Poettering if (s) {
c69fa7e3c44240bedc0ee1bd89fecf954783ac85Lennart Poettering _cleanup_free_ char *ip = NULL;
c69fa7e3c44240bedc0ee1bd89fecf954783ac85Lennart Poettering
c69fa7e3c44240bedc0ee1bd89fecf954783ac85Lennart Poettering in_addr_to_string(s->family, &s->address, &ip);
c69fa7e3c44240bedc0ee1bd89fecf954783ac85Lennart Poettering log_info("Switching to system DNS server %s.", strna(ip));
c69fa7e3c44240bedc0ee1bd89fecf954783ac85Lennart Poettering }
c69fa7e3c44240bedc0ee1bd89fecf954783ac85Lennart Poettering
c69fa7e3c44240bedc0ee1bd89fecf954783ac85Lennart Poettering m->current_dns_server = s;
c69fa7e3c44240bedc0ee1bd89fecf954783ac85Lennart Poettering
c69fa7e3c44240bedc0ee1bd89fecf954783ac85Lennart Poettering if (m->unicast_scope)
c69fa7e3c44240bedc0ee1bd89fecf954783ac85Lennart Poettering dns_cache_flush(&m->unicast_scope->cache);
c69fa7e3c44240bedc0ee1bd89fecf954783ac85Lennart Poettering
c69fa7e3c44240bedc0ee1bd89fecf954783ac85Lennart Poettering return s;
c69fa7e3c44240bedc0ee1bd89fecf954783ac85Lennart Poettering}
c69fa7e3c44240bedc0ee1bd89fecf954783ac85Lennart Poettering
c69fa7e3c44240bedc0ee1bd89fecf954783ac85Lennart PoetteringDnsServer *manager_get_dns_server(Manager *m) {
c69fa7e3c44240bedc0ee1bd89fecf954783ac85Lennart Poettering Link *l;
c69fa7e3c44240bedc0ee1bd89fecf954783ac85Lennart Poettering assert(m);
c69fa7e3c44240bedc0ee1bd89fecf954783ac85Lennart Poettering
c69fa7e3c44240bedc0ee1bd89fecf954783ac85Lennart Poettering /* Try to read updates resolv.conf */
59c5b5974d106c5ebad080739b41d0e92ab74d29Lennart Poettering manager_read_resolv_conf(m);
59c5b5974d106c5ebad080739b41d0e92ab74d29Lennart Poettering
59c5b5974d106c5ebad080739b41d0e92ab74d29Lennart Poettering if (!m->current_dns_server)
59c5b5974d106c5ebad080739b41d0e92ab74d29Lennart Poettering manager_set_dns_server(m, m->dns_servers);
59c5b5974d106c5ebad080739b41d0e92ab74d29Lennart Poettering
59c5b5974d106c5ebad080739b41d0e92ab74d29Lennart Poettering if (!m->current_dns_server) {
59c5b5974d106c5ebad080739b41d0e92ab74d29Lennart Poettering bool found = false;
59c5b5974d106c5ebad080739b41d0e92ab74d29Lennart Poettering Iterator i;
59c5b5974d106c5ebad080739b41d0e92ab74d29Lennart Poettering
59c5b5974d106c5ebad080739b41d0e92ab74d29Lennart Poettering /* No DNS servers configured, let's see if there are
59c5b5974d106c5ebad080739b41d0e92ab74d29Lennart Poettering * any on any links. If not, we use the fallback
59c5b5974d106c5ebad080739b41d0e92ab74d29Lennart Poettering * servers */
59c5b5974d106c5ebad080739b41d0e92ab74d29Lennart Poettering
59c5b5974d106c5ebad080739b41d0e92ab74d29Lennart Poettering HASHMAP_FOREACH(l, m->links, i)
59c5b5974d106c5ebad080739b41d0e92ab74d29Lennart Poettering if (l->dns_servers) {
59c5b5974d106c5ebad080739b41d0e92ab74d29Lennart Poettering found = true;
break;
}
if (!found)
manager_set_dns_server(m, m->fallback_dns_servers);
}
return m->current_dns_server;
}
void manager_next_dns_server(Manager *m) {
assert(m);
/* If there's currently no DNS server set, then the next
* manager_get_dns_server() will find one */
if (!m->current_dns_server)
return;
/* Change to the next one */
if (m->current_dns_server->servers_next) {
manager_set_dns_server(m, m->current_dns_server->servers_next);
return;
}
/* If there was no next one, then start from the beginning of
* the list */
if (m->current_dns_server->type == DNS_SERVER_FALLBACK)
manager_set_dns_server(m, m->fallback_dns_servers);
else
manager_set_dns_server(m, m->dns_servers);
}
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);
}
void manager_flush_dns_servers(Manager *m, DnsServerType t) {
DnsServer *s;
assert(m);
if (t == DNS_SERVER_SYSTEM)
while (m->dns_servers) {
s = m->dns_servers;
LIST_REMOVE(servers, m->dns_servers, s);
dns_server_unref(s);
}
if (t == DNS_SERVER_FALLBACK)
while (m->fallback_dns_servers) {
s = m->fallback_dns_servers;
LIST_REMOVE(servers, m->fallback_dns_servers, s);
dns_server_unref(s);
}
}
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;
}
static const char* const support_table[_SUPPORT_MAX] = {
[SUPPORT_NO] = "no",
[SUPPORT_YES] = "yes",
[SUPPORT_RESOLVE] = "resolve",
};
DEFINE_STRING_TABLE_LOOKUP(support, Support);