resolved-manager.c revision f0e1546763304aedc90e91d70dab9eeb7c966cf8
139b011ab81ccea1d51f09e0261a1c390115c6ffPatrik Flykt/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
139b011ab81ccea1d51f09e0261a1c390115c6ffPatrik Flykt
139b011ab81ccea1d51f09e0261a1c390115c6ffPatrik Flykt/***
139b011ab81ccea1d51f09e0261a1c390115c6ffPatrik Flykt This file is part of systemd.
139b011ab81ccea1d51f09e0261a1c390115c6ffPatrik Flykt
7bd8e95d44977833d0de3fc4e893eb3bc84351d6Patrik Flykt Copyright 2014 Tom Gundersen <teg@jklm.no>
139b011ab81ccea1d51f09e0261a1c390115c6ffPatrik Flykt
139b011ab81ccea1d51f09e0261a1c390115c6ffPatrik Flykt systemd is free software; you can redistribute it and/or modify it
139b011ab81ccea1d51f09e0261a1c390115c6ffPatrik Flykt under the terms of the GNU Lesser General Public License as published by
139b011ab81ccea1d51f09e0261a1c390115c6ffPatrik Flykt the Free Software Foundation; either version 2.1 of the License, or
139b011ab81ccea1d51f09e0261a1c390115c6ffPatrik Flykt (at your option) any later version.
139b011ab81ccea1d51f09e0261a1c390115c6ffPatrik Flykt
139b011ab81ccea1d51f09e0261a1c390115c6ffPatrik Flykt systemd is distributed in the hope that it will be useful, but
139b011ab81ccea1d51f09e0261a1c390115c6ffPatrik Flykt WITHOUT ANY WARRANTY; without even the implied warranty of
139b011ab81ccea1d51f09e0261a1c390115c6ffPatrik Flykt MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
139b011ab81ccea1d51f09e0261a1c390115c6ffPatrik Flykt Lesser General Public License for more details.
139b011ab81ccea1d51f09e0261a1c390115c6ffPatrik Flykt
139b011ab81ccea1d51f09e0261a1c390115c6ffPatrik Flykt You should have received a copy of the GNU Lesser General Public License
139b011ab81ccea1d51f09e0261a1c390115c6ffPatrik Flykt along with systemd; If not, see <http://www.gnu.org/licenses/>.
139b011ab81ccea1d51f09e0261a1c390115c6ffPatrik Flykt ***/
139b011ab81ccea1d51f09e0261a1c390115c6ffPatrik Flykt
139b011ab81ccea1d51f09e0261a1c390115c6ffPatrik Flykt#include <arpa/inet.h>
139b011ab81ccea1d51f09e0261a1c390115c6ffPatrik Flykt#include <resolv.h>
631bbe71298ec892f77f44f94feb612646fe6853Patrik Flykt#include <net/if.h>
76253e73f9c9c24fec755e485516f3b55d0707b4Dan Williams#include <sys/ioctl.h>
139b011ab81ccea1d51f09e0261a1c390115c6ffPatrik Flykt#include <sys/poll.h>
f12abb48fc510b8b349c05e35ba048134debaf25Patrik Flykt#include <netinet/in.h>
f12abb48fc510b8b349c05e35ba048134debaf25Patrik Flykt
139b011ab81ccea1d51f09e0261a1c390115c6ffPatrik Flykt#include "rtnl-util.h"
139b011ab81ccea1d51f09e0261a1c390115c6ffPatrik Flykt#include "event-util.h"
3df3e884ae1237ef0d4d23b0e80f4ffda95ac135Ronny Chevalier#include "network-util.h"
139b011ab81ccea1d51f09e0261a1c390115c6ffPatrik Flykt#include "network-internal.h"
f12abb48fc510b8b349c05e35ba048134debaf25Patrik Flykt#include "conf-parser.h"
139b011ab81ccea1d51f09e0261a1c390115c6ffPatrik Flykt#include "socket-util.h"
139b011ab81ccea1d51f09e0261a1c390115c6ffPatrik Flykt#include "af-list.h"
f12abb48fc510b8b349c05e35ba048134debaf25Patrik Flykt#include "utf8.h"
631bbe71298ec892f77f44f94feb612646fe6853Patrik Flykt
764aad6258eec3bd4ae62ea341ea507bd69ce628Tom Gundersen#include "resolved-dns-domain.h"
139b011ab81ccea1d51f09e0261a1c390115c6ffPatrik Flykt#include "resolved-conf.h"
76253e73f9c9c24fec755e485516f3b55d0707b4Dan Williams#include "resolved-bus.h"
76253e73f9c9c24fec755e485516f3b55d0707b4Dan Williams#include "resolved-manager.h"
139b011ab81ccea1d51f09e0261a1c390115c6ffPatrik Flykt
139b011ab81ccea1d51f09e0261a1c390115c6ffPatrik Flykt#define SEND_TIMEOUT_USEC (200 * USEC_PER_MSEC)
139b011ab81ccea1d51f09e0261a1c390115c6ffPatrik Flykt
139b011ab81ccea1d51f09e0261a1c390115c6ffPatrik Flyktstatic int manager_process_link(sd_rtnl *rtnl, sd_rtnl_message *mm, void *userdata) {
139b011ab81ccea1d51f09e0261a1c390115c6ffPatrik Flykt Manager *m = userdata;
139b011ab81ccea1d51f09e0261a1c390115c6ffPatrik Flykt uint16_t type;
139b011ab81ccea1d51f09e0261a1c390115c6ffPatrik Flykt Link *l;
76253e73f9c9c24fec755e485516f3b55d0707b4Dan Williams int ifindex, r;
76253e73f9c9c24fec755e485516f3b55d0707b4Dan Williams
76253e73f9c9c24fec755e485516f3b55d0707b4Dan Williams assert(rtnl);
f12abb48fc510b8b349c05e35ba048134debaf25Patrik Flykt assert(m);
a9aff3615b430f86bd0a824214d95f634efaf894Patrik Flykt assert(mm);
346e13a25dc6f76d3bc9d8decd40dc4782b02d2aPatrik Flykt
631bbe71298ec892f77f44f94feb612646fe6853Patrik Flykt r = sd_rtnl_message_get_type(mm, &type);
a9aff3615b430f86bd0a824214d95f634efaf894Patrik Flykt if (r < 0)
bbfa43ca37df0718287c25a8e39ee7477ebf33f6Patrik Flykt goto fail;
da6fe470e17fa02f3adedc779585caf8669252bdPatrik Flykt
da6fe470e17fa02f3adedc779585caf8669252bdPatrik Flykt r = sd_rtnl_message_link_get_ifindex(mm, &ifindex);
da6fe470e17fa02f3adedc779585caf8669252bdPatrik Flykt if (r < 0)
a9aff3615b430f86bd0a824214d95f634efaf894Patrik Flykt goto fail;
d1b0afe3653b4316a6361d204169620726d468a0Patrik Flykt
d1b0afe3653b4316a6361d204169620726d468a0Patrik Flykt l = hashmap_get(m->links, INT_TO_PTR(ifindex));
d1b0afe3653b4316a6361d204169620726d468a0Patrik Flykt
d1b0afe3653b4316a6361d204169620726d468a0Patrik Flykt switch (type) {
139b011ab81ccea1d51f09e0261a1c390115c6ffPatrik Flykt
139b011ab81ccea1d51f09e0261a1c390115c6ffPatrik Flykt case RTM_NEWLINK:{
764aad6258eec3bd4ae62ea341ea507bd69ce628Tom Gundersen bool is_new = !l;
66eac1201a9c1596f5901f8dbbf24bda7e350878Dan Williams
139b011ab81ccea1d51f09e0261a1c390115c6ffPatrik Flykt if (!l) {
139b011ab81ccea1d51f09e0261a1c390115c6ffPatrik Flykt r = link_new(m, &l, ifindex);
da6fe470e17fa02f3adedc779585caf8669252bdPatrik Flykt if (r < 0)
da6fe470e17fa02f3adedc779585caf8669252bdPatrik Flykt goto fail;
da6fe470e17fa02f3adedc779585caf8669252bdPatrik Flykt }
da6fe470e17fa02f3adedc779585caf8669252bdPatrik Flykt
41e4615d4f4f5c61afa84ba857f23c0ac496687bPatrik Flykt r = link_update_rtnl(l, mm);
da6fe470e17fa02f3adedc779585caf8669252bdPatrik Flykt if (r < 0)
da6fe470e17fa02f3adedc779585caf8669252bdPatrik Flykt goto fail;
a9aff3615b430f86bd0a824214d95f634efaf894Patrik Flykt
a9aff3615b430f86bd0a824214d95f634efaf894Patrik Flykt if (is_new)
a9aff3615b430f86bd0a824214d95f634efaf894Patrik Flykt log_debug("Found new link %i/%s", ifindex, l->name);
a9aff3615b430f86bd0a824214d95f634efaf894Patrik Flykt
a9aff3615b430f86bd0a824214d95f634efaf894Patrik Flykt break;
a9aff3615b430f86bd0a824214d95f634efaf894Patrik Flykt }
a9aff3615b430f86bd0a824214d95f634efaf894Patrik Flykt
a9aff3615b430f86bd0a824214d95f634efaf894Patrik Flykt case RTM_DELLINK:
a9aff3615b430f86bd0a824214d95f634efaf894Patrik Flykt if (l) {
a9aff3615b430f86bd0a824214d95f634efaf894Patrik Flykt log_debug("Removing link %i/%s", l->ifindex, l->name);
a9aff3615b430f86bd0a824214d95f634efaf894Patrik Flykt link_free(l);
a9aff3615b430f86bd0a824214d95f634efaf894Patrik Flykt }
a9aff3615b430f86bd0a824214d95f634efaf894Patrik Flykt
a9aff3615b430f86bd0a824214d95f634efaf894Patrik Flykt break;
a9aff3615b430f86bd0a824214d95f634efaf894Patrik Flykt }
a9aff3615b430f86bd0a824214d95f634efaf894Patrik Flykt
a9aff3615b430f86bd0a824214d95f634efaf894Patrik Flykt return 0;
a9aff3615b430f86bd0a824214d95f634efaf894Patrik Flykt
631bbe71298ec892f77f44f94feb612646fe6853Patrik Flyktfail:
631bbe71298ec892f77f44f94feb612646fe6853Patrik Flykt log_warning("Failed to process RTNL link message: %s", strerror(-r));
631bbe71298ec892f77f44f94feb612646fe6853Patrik Flykt return 0;
631bbe71298ec892f77f44f94feb612646fe6853Patrik Flykt}
631bbe71298ec892f77f44f94feb612646fe6853Patrik Flykt
631bbe71298ec892f77f44f94feb612646fe6853Patrik Flyktstatic int manager_process_address(sd_rtnl *rtnl, sd_rtnl_message *mm, void *userdata) {
631bbe71298ec892f77f44f94feb612646fe6853Patrik Flykt Manager *m = userdata;
631bbe71298ec892f77f44f94feb612646fe6853Patrik Flykt union in_addr_union address;
631bbe71298ec892f77f44f94feb612646fe6853Patrik Flykt uint16_t type;
631bbe71298ec892f77f44f94feb612646fe6853Patrik Flykt int r, ifindex, family;
631bbe71298ec892f77f44f94feb612646fe6853Patrik Flykt LinkAddress *a;
3f0c075f8ef3344da5a6bda524540201f9204e61Patrik Flykt Link *l;
3f0c075f8ef3344da5a6bda524540201f9204e61Patrik Flykt
3f0c075f8ef3344da5a6bda524540201f9204e61Patrik Flykt assert(rtnl);
3f0c075f8ef3344da5a6bda524540201f9204e61Patrik Flykt assert(mm);
3f0c075f8ef3344da5a6bda524540201f9204e61Patrik Flykt assert(m);
3f0c075f8ef3344da5a6bda524540201f9204e61Patrik Flykt
c3e2adeaba8e043caed0ef139eeaea016bd152d0Patrik Flykt r = sd_rtnl_message_get_type(mm, &type);
c3e2adeaba8e043caed0ef139eeaea016bd152d0Patrik Flykt if (r < 0)
139b011ab81ccea1d51f09e0261a1c390115c6ffPatrik Flykt goto fail;
139b011ab81ccea1d51f09e0261a1c390115c6ffPatrik Flykt
139b011ab81ccea1d51f09e0261a1c390115c6ffPatrik Flykt r = sd_rtnl_message_addr_get_ifindex(mm, &ifindex);
139b011ab81ccea1d51f09e0261a1c390115c6ffPatrik Flykt if (r < 0)
139b011ab81ccea1d51f09e0261a1c390115c6ffPatrik Flykt goto fail;
139b011ab81ccea1d51f09e0261a1c390115c6ffPatrik Flykt
139b011ab81ccea1d51f09e0261a1c390115c6ffPatrik Flykt l = hashmap_get(m->links, INT_TO_PTR(ifindex));
139b011ab81ccea1d51f09e0261a1c390115c6ffPatrik Flykt if (!l)
139b011ab81ccea1d51f09e0261a1c390115c6ffPatrik Flykt return 0;
139b011ab81ccea1d51f09e0261a1c390115c6ffPatrik Flykt
139b011ab81ccea1d51f09e0261a1c390115c6ffPatrik Flykt r = sd_rtnl_message_addr_get_family(mm, &family);
139b011ab81ccea1d51f09e0261a1c390115c6ffPatrik Flykt if (r < 0)
139b011ab81ccea1d51f09e0261a1c390115c6ffPatrik Flykt goto fail;
139b011ab81ccea1d51f09e0261a1c390115c6ffPatrik Flykt
139b011ab81ccea1d51f09e0261a1c390115c6ffPatrik Flykt switch (family) {
139b011ab81ccea1d51f09e0261a1c390115c6ffPatrik Flykt
139b011ab81ccea1d51f09e0261a1c390115c6ffPatrik Flykt case AF_INET:
139b011ab81ccea1d51f09e0261a1c390115c6ffPatrik Flykt r = sd_rtnl_message_read_in_addr(mm, IFA_LOCAL, &address.in);
139b011ab81ccea1d51f09e0261a1c390115c6ffPatrik Flykt if (r < 0) {
139b011ab81ccea1d51f09e0261a1c390115c6ffPatrik Flykt r = sd_rtnl_message_read_in_addr(mm, IFA_ADDRESS, &address.in);
139b011ab81ccea1d51f09e0261a1c390115c6ffPatrik Flykt if (r < 0)
76253e73f9c9c24fec755e485516f3b55d0707b4Dan Williams goto fail;
76253e73f9c9c24fec755e485516f3b55d0707b4Dan Williams }
139b011ab81ccea1d51f09e0261a1c390115c6ffPatrik Flykt
139b011ab81ccea1d51f09e0261a1c390115c6ffPatrik Flykt break;
76253e73f9c9c24fec755e485516f3b55d0707b4Dan Williams
76253e73f9c9c24fec755e485516f3b55d0707b4Dan Williams case AF_INET6:
76253e73f9c9c24fec755e485516f3b55d0707b4Dan Williams r = sd_rtnl_message_read_in6_addr(mm, IFA_LOCAL, &address.in6);
76253e73f9c9c24fec755e485516f3b55d0707b4Dan Williams if (r < 0) {
76253e73f9c9c24fec755e485516f3b55d0707b4Dan Williams r = sd_rtnl_message_read_in6_addr(mm, IFA_ADDRESS, &address.in6);
76253e73f9c9c24fec755e485516f3b55d0707b4Dan Williams if (r < 0)
76253e73f9c9c24fec755e485516f3b55d0707b4Dan Williams goto fail;
76253e73f9c9c24fec755e485516f3b55d0707b4Dan Williams }
139b011ab81ccea1d51f09e0261a1c390115c6ffPatrik Flykt
76253e73f9c9c24fec755e485516f3b55d0707b4Dan Williams break;
76253e73f9c9c24fec755e485516f3b55d0707b4Dan Williams
76253e73f9c9c24fec755e485516f3b55d0707b4Dan Williams default:
76253e73f9c9c24fec755e485516f3b55d0707b4Dan Williams return 0;
76253e73f9c9c24fec755e485516f3b55d0707b4Dan Williams }
76253e73f9c9c24fec755e485516f3b55d0707b4Dan Williams
76253e73f9c9c24fec755e485516f3b55d0707b4Dan Williams a = link_find_address(l, family, &address);
76253e73f9c9c24fec755e485516f3b55d0707b4Dan Williams
76253e73f9c9c24fec755e485516f3b55d0707b4Dan Williams switch (type) {
139b011ab81ccea1d51f09e0261a1c390115c6ffPatrik Flykt
139b011ab81ccea1d51f09e0261a1c390115c6ffPatrik Flykt case RTM_NEWADDR:
139b011ab81ccea1d51f09e0261a1c390115c6ffPatrik Flykt
139b011ab81ccea1d51f09e0261a1c390115c6ffPatrik Flykt if (!a) {
cc22955cfefb4bd6e7a135f1ec95fb5a07ba9ce3Thomas Haller r = link_address_new(l, &a, family, &address);
cc22955cfefb4bd6e7a135f1ec95fb5a07ba9ce3Thomas Haller if (r < 0)
cc22955cfefb4bd6e7a135f1ec95fb5a07ba9ce3Thomas Haller return r;
cc22955cfefb4bd6e7a135f1ec95fb5a07ba9ce3Thomas Haller }
cc22955cfefb4bd6e7a135f1ec95fb5a07ba9ce3Thomas Haller
cc22955cfefb4bd6e7a135f1ec95fb5a07ba9ce3Thomas Haller r = link_address_update_rtnl(a, mm);
cc22955cfefb4bd6e7a135f1ec95fb5a07ba9ce3Thomas Haller if (r < 0)
ebe207d4acf38165adbc45298662982eecdb9e9fTom Gundersen return r;
66eac1201a9c1596f5901f8dbbf24bda7e350878Dan Williams
66eac1201a9c1596f5901f8dbbf24bda7e350878Dan Williams break;
66eac1201a9c1596f5901f8dbbf24bda7e350878Dan Williams
66eac1201a9c1596f5901f8dbbf24bda7e350878Dan Williams case RTM_DELADDR:
66eac1201a9c1596f5901f8dbbf24bda7e350878Dan Williams if (a)
66eac1201a9c1596f5901f8dbbf24bda7e350878Dan Williams link_address_free(a);
fe4b2156256c5bdf52341576571ce9f095d9f085Tom Gundersen break;
fe4b2156256c5bdf52341576571ce9f095d9f085Tom Gundersen }
764aad6258eec3bd4ae62ea341ea507bd69ce628Tom Gundersen
fe4b2156256c5bdf52341576571ce9f095d9f085Tom Gundersen return 0;
fe4b2156256c5bdf52341576571ce9f095d9f085Tom Gundersen
fe4b2156256c5bdf52341576571ce9f095d9f085Tom Gundersenfail:
764aad6258eec3bd4ae62ea341ea507bd69ce628Tom Gundersen log_warning("Failed to process RTNL address message: %s", strerror(-r));
fe4b2156256c5bdf52341576571ce9f095d9f085Tom Gundersen return 0;
fe4b2156256c5bdf52341576571ce9f095d9f085Tom Gundersen}
fe4b2156256c5bdf52341576571ce9f095d9f085Tom Gundersen
764aad6258eec3bd4ae62ea341ea507bd69ce628Tom Gundersenstatic int manager_rtnl_listen(Manager *m) {
fe4b2156256c5bdf52341576571ce9f095d9f085Tom Gundersen _cleanup_rtnl_message_unref_ sd_rtnl_message *req = NULL, *reply = NULL;
fe4b2156256c5bdf52341576571ce9f095d9f085Tom Gundersen sd_rtnl_message *i;
fe4b2156256c5bdf52341576571ce9f095d9f085Tom Gundersen int r;
764aad6258eec3bd4ae62ea341ea507bd69ce628Tom Gundersen
fe4b2156256c5bdf52341576571ce9f095d9f085Tom Gundersen assert(m);
fe4b2156256c5bdf52341576571ce9f095d9f085Tom Gundersen
fe4b2156256c5bdf52341576571ce9f095d9f085Tom Gundersen /* First, subscibe to interfaces coming and going */
fe4b2156256c5bdf52341576571ce9f095d9f085Tom Gundersen r = sd_rtnl_open(&m->rtnl, 3, RTNLGRP_LINK, RTNLGRP_IPV4_IFADDR, RTNLGRP_IPV6_IFADDR);
fe4b2156256c5bdf52341576571ce9f095d9f085Tom Gundersen if (r < 0)
fe4b2156256c5bdf52341576571ce9f095d9f085Tom Gundersen return r;
fe4b2156256c5bdf52341576571ce9f095d9f085Tom Gundersen
764aad6258eec3bd4ae62ea341ea507bd69ce628Tom Gundersen r = sd_rtnl_attach_event(m->rtnl, m->event, 0);
ebe207d4acf38165adbc45298662982eecdb9e9fTom Gundersen if (r < 0)
764aad6258eec3bd4ae62ea341ea507bd69ce628Tom Gundersen return r;
66eac1201a9c1596f5901f8dbbf24bda7e350878Dan Williams
66eac1201a9c1596f5901f8dbbf24bda7e350878Dan Williams r = sd_rtnl_add_match(m->rtnl, RTM_NEWLINK, manager_process_link, m);
66eac1201a9c1596f5901f8dbbf24bda7e350878Dan Williams if (r < 0)
66eac1201a9c1596f5901f8dbbf24bda7e350878Dan Williams return r;
bbfa43ca37df0718287c25a8e39ee7477ebf33f6Patrik Flykt
bbfa43ca37df0718287c25a8e39ee7477ebf33f6Patrik Flykt r = sd_rtnl_add_match(m->rtnl, RTM_DELLINK, manager_process_link, m);
bbfa43ca37df0718287c25a8e39ee7477ebf33f6Patrik Flykt if (r < 0)
bbfa43ca37df0718287c25a8e39ee7477ebf33f6Patrik Flykt return r;
bbfa43ca37df0718287c25a8e39ee7477ebf33f6Patrik Flykt
bbfa43ca37df0718287c25a8e39ee7477ebf33f6Patrik Flykt r = sd_rtnl_add_match(m->rtnl, RTM_NEWADDR, manager_process_address, m);
bbfa43ca37df0718287c25a8e39ee7477ebf33f6Patrik Flykt if (r < 0)
bbfa43ca37df0718287c25a8e39ee7477ebf33f6Patrik Flykt return r;
bbfa43ca37df0718287c25a8e39ee7477ebf33f6Patrik Flykt
bbfa43ca37df0718287c25a8e39ee7477ebf33f6Patrik Flykt r = sd_rtnl_add_match(m->rtnl, RTM_DELADDR, manager_process_address, m);
bbfa43ca37df0718287c25a8e39ee7477ebf33f6Patrik Flykt if (r < 0)
bbfa43ca37df0718287c25a8e39ee7477ebf33f6Patrik Flykt return r;
bbfa43ca37df0718287c25a8e39ee7477ebf33f6Patrik Flykt
bbfa43ca37df0718287c25a8e39ee7477ebf33f6Patrik Flykt /* Then, enumerate all links */
bbfa43ca37df0718287c25a8e39ee7477ebf33f6Patrik Flykt r = sd_rtnl_message_new_link(m->rtnl, &req, RTM_GETLINK, 0);
bbfa43ca37df0718287c25a8e39ee7477ebf33f6Patrik Flykt if (r < 0)
bbfa43ca37df0718287c25a8e39ee7477ebf33f6Patrik Flykt return r;
bbfa43ca37df0718287c25a8e39ee7477ebf33f6Patrik Flykt
bbfa43ca37df0718287c25a8e39ee7477ebf33f6Patrik Flykt r = sd_rtnl_message_request_dump(req, true);
da6fe470e17fa02f3adedc779585caf8669252bdPatrik Flykt if (r < 0)
da6fe470e17fa02f3adedc779585caf8669252bdPatrik Flykt return r;
da6fe470e17fa02f3adedc779585caf8669252bdPatrik Flykt
da6fe470e17fa02f3adedc779585caf8669252bdPatrik Flykt r = sd_rtnl_call(m->rtnl, req, 0, &reply);
da6fe470e17fa02f3adedc779585caf8669252bdPatrik Flykt if (r < 0)
da6fe470e17fa02f3adedc779585caf8669252bdPatrik Flykt return r;
da6fe470e17fa02f3adedc779585caf8669252bdPatrik Flykt
da6fe470e17fa02f3adedc779585caf8669252bdPatrik Flykt for (i = reply; i; i = sd_rtnl_message_next(i)) {
da6fe470e17fa02f3adedc779585caf8669252bdPatrik Flykt r = manager_process_link(m->rtnl, i, m);
da6fe470e17fa02f3adedc779585caf8669252bdPatrik Flykt if (r < 0)
da6fe470e17fa02f3adedc779585caf8669252bdPatrik Flykt return r;
da6fe470e17fa02f3adedc779585caf8669252bdPatrik Flykt }
da6fe470e17fa02f3adedc779585caf8669252bdPatrik Flykt
da6fe470e17fa02f3adedc779585caf8669252bdPatrik Flykt req = sd_rtnl_message_unref(req);
da6fe470e17fa02f3adedc779585caf8669252bdPatrik Flykt reply = sd_rtnl_message_unref(reply);
da6fe470e17fa02f3adedc779585caf8669252bdPatrik Flykt
da6fe470e17fa02f3adedc779585caf8669252bdPatrik Flykt /* Finally, enumerate all addresses, too */
da6fe470e17fa02f3adedc779585caf8669252bdPatrik Flykt r = sd_rtnl_message_new_addr(m->rtnl, &req, RTM_GETADDR, 0, AF_UNSPEC);
da6fe470e17fa02f3adedc779585caf8669252bdPatrik Flykt if (r < 0)
da6fe470e17fa02f3adedc779585caf8669252bdPatrik Flykt return r;
da6fe470e17fa02f3adedc779585caf8669252bdPatrik Flykt
da6fe470e17fa02f3adedc779585caf8669252bdPatrik Flykt r = sd_rtnl_message_request_dump(req, true);
da6fe470e17fa02f3adedc779585caf8669252bdPatrik Flykt if (r < 0)
da6fe470e17fa02f3adedc779585caf8669252bdPatrik Flykt return r;
da6fe470e17fa02f3adedc779585caf8669252bdPatrik Flykt
da6fe470e17fa02f3adedc779585caf8669252bdPatrik Flykt r = sd_rtnl_call(m->rtnl, req, 0, &reply);
da6fe470e17fa02f3adedc779585caf8669252bdPatrik Flykt if (r < 0)
da6fe470e17fa02f3adedc779585caf8669252bdPatrik Flykt return r;
da6fe470e17fa02f3adedc779585caf8669252bdPatrik Flykt
da6fe470e17fa02f3adedc779585caf8669252bdPatrik Flykt for (i = reply; i; i = sd_rtnl_message_next(i)) {
da6fe470e17fa02f3adedc779585caf8669252bdPatrik Flykt r = manager_process_address(m->rtnl, i, m);
ea3b3a75abb3f8b853f7da454b9b8e258a120eeaPatrik Flykt if (r < 0)
ea3b3a75abb3f8b853f7da454b9b8e258a120eeaPatrik Flykt return r;
ea3b3a75abb3f8b853f7da454b9b8e258a120eeaPatrik Flykt }
ea3b3a75abb3f8b853f7da454b9b8e258a120eeaPatrik Flykt
ea3b3a75abb3f8b853f7da454b9b8e258a120eeaPatrik Flykt return r;
ea3b3a75abb3f8b853f7da454b9b8e258a120eeaPatrik Flykt}
ea3b3a75abb3f8b853f7da454b9b8e258a120eeaPatrik Flykt
ea3b3a75abb3f8b853f7da454b9b8e258a120eeaPatrik Flyktstatic int on_network_event(sd_event_source *s, int fd, uint32_t revents, void *userdata) {
ea3b3a75abb3f8b853f7da454b9b8e258a120eeaPatrik Flykt Manager *m = userdata;
ea3b3a75abb3f8b853f7da454b9b8e258a120eeaPatrik Flykt Iterator i;
ea3b3a75abb3f8b853f7da454b9b8e258a120eeaPatrik Flykt Link *l;
ea3b3a75abb3f8b853f7da454b9b8e258a120eeaPatrik Flykt int r;
3f0c075f8ef3344da5a6bda524540201f9204e61Patrik Flykt
3f0c075f8ef3344da5a6bda524540201f9204e61Patrik Flykt assert(m);
139b011ab81ccea1d51f09e0261a1c390115c6ffPatrik Flykt
139b011ab81ccea1d51f09e0261a1c390115c6ffPatrik Flykt sd_network_monitor_flush(m->network_monitor);
139b011ab81ccea1d51f09e0261a1c390115c6ffPatrik Flykt
c806ffb9592fa9a2b13a1f9f9be4c77cd5b211aaZbigniew Jędrzejewski-Szmek HASHMAP_FOREACH(l, m->links, i) {
139b011ab81ccea1d51f09e0261a1c390115c6ffPatrik Flykt r = link_update_monitor(l);
139b011ab81ccea1d51f09e0261a1c390115c6ffPatrik Flykt if (r < 0)
4e3e6679e8f73b83d38e4b20d8b025e12991d1cbPatrik Flykt log_warning("Failed to update monitor information for %i: %s", l->ifindex, strerror(-r));
4e3e6679e8f73b83d38e4b20d8b025e12991d1cbPatrik Flykt }
4e3e6679e8f73b83d38e4b20d8b025e12991d1cbPatrik Flykt
4e3e6679e8f73b83d38e4b20d8b025e12991d1cbPatrik Flykt r = manager_write_resolv_conf(m);
4e3e6679e8f73b83d38e4b20d8b025e12991d1cbPatrik Flykt if (r < 0)
a9aff3615b430f86bd0a824214d95f634efaf894Patrik Flykt log_warning("Could not update resolv.conf: %s", strerror(-r));
a9aff3615b430f86bd0a824214d95f634efaf894Patrik Flykt
a9aff3615b430f86bd0a824214d95f634efaf894Patrik Flykt return 0;
c806ffb9592fa9a2b13a1f9f9be4c77cd5b211aaZbigniew Jędrzejewski-Szmek}
a9aff3615b430f86bd0a824214d95f634efaf894Patrik Flykt
c3e2adeaba8e043caed0ef139eeaea016bd152d0Patrik Flyktstatic int manager_network_monitor_listen(Manager *m) {
346e13a25dc6f76d3bc9d8decd40dc4782b02d2aPatrik Flykt int r, fd, events;
a9aff3615b430f86bd0a824214d95f634efaf894Patrik Flykt
f12abb48fc510b8b349c05e35ba048134debaf25Patrik Flykt assert(m);
f12abb48fc510b8b349c05e35ba048134debaf25Patrik Flykt
f12abb48fc510b8b349c05e35ba048134debaf25Patrik Flykt r = sd_network_monitor_new(&m->network_monitor, NULL);
f12abb48fc510b8b349c05e35ba048134debaf25Patrik Flykt if (r < 0)
f12abb48fc510b8b349c05e35ba048134debaf25Patrik Flykt return r;
d1b0afe3653b4316a6361d204169620726d468a0Patrik Flykt
d1b0afe3653b4316a6361d204169620726d468a0Patrik Flykt fd = sd_network_monitor_get_fd(m->network_monitor);
d1b0afe3653b4316a6361d204169620726d468a0Patrik Flykt if (fd < 0)
d1b0afe3653b4316a6361d204169620726d468a0Patrik Flykt return fd;
d1b0afe3653b4316a6361d204169620726d468a0Patrik Flykt
d1b0afe3653b4316a6361d204169620726d468a0Patrik Flykt events = sd_network_monitor_get_events(m->network_monitor);
139b011ab81ccea1d51f09e0261a1c390115c6ffPatrik Flykt if (events < 0)
139b011ab81ccea1d51f09e0261a1c390115c6ffPatrik Flykt return events;
139b011ab81ccea1d51f09e0261a1c390115c6ffPatrik Flykt
139b011ab81ccea1d51f09e0261a1c390115c6ffPatrik Flykt r = sd_event_add_io(m->event, &m->network_event_source, fd, events, &on_network_event, m);
139b011ab81ccea1d51f09e0261a1c390115c6ffPatrik Flykt if (r < 0)
3f0c075f8ef3344da5a6bda524540201f9204e61Patrik Flykt return r;
3f0c075f8ef3344da5a6bda524540201f9204e61Patrik Flykt
139b011ab81ccea1d51f09e0261a1c390115c6ffPatrik Flykt return 0;
3f0c075f8ef3344da5a6bda524540201f9204e61Patrik Flykt}
139b011ab81ccea1d51f09e0261a1c390115c6ffPatrik Flykt
3f0c075f8ef3344da5a6bda524540201f9204e61Patrik Flyktstatic int determine_hostname(char **ret) {
3f0c075f8ef3344da5a6bda524540201f9204e61Patrik Flykt _cleanup_free_ char *h = NULL, *n = NULL;
3f0c075f8ef3344da5a6bda524540201f9204e61Patrik Flykt int r;
139b011ab81ccea1d51f09e0261a1c390115c6ffPatrik Flykt
139b011ab81ccea1d51f09e0261a1c390115c6ffPatrik Flykt assert(ret);
346e13a25dc6f76d3bc9d8decd40dc4782b02d2aPatrik Flykt
a9aff3615b430f86bd0a824214d95f634efaf894Patrik Flykt h = gethostname_malloc();
a9aff3615b430f86bd0a824214d95f634efaf894Patrik Flykt if (!h)
a9aff3615b430f86bd0a824214d95f634efaf894Patrik Flykt return log_oom();
a9aff3615b430f86bd0a824214d95f634efaf894Patrik Flykt
a9aff3615b430f86bd0a824214d95f634efaf894Patrik Flykt if (!utf8_is_valid(h)) {
a9aff3615b430f86bd0a824214d95f634efaf894Patrik Flykt log_error("System hostname is not UTF-8 clean.");
346e13a25dc6f76d3bc9d8decd40dc4782b02d2aPatrik Flykt return -EINVAL;
346e13a25dc6f76d3bc9d8decd40dc4782b02d2aPatrik Flykt }
a9aff3615b430f86bd0a824214d95f634efaf894Patrik Flykt
a9aff3615b430f86bd0a824214d95f634efaf894Patrik Flykt r = dns_name_normalize(h, &n);
a9aff3615b430f86bd0a824214d95f634efaf894Patrik Flykt if (r < 0) {
a9aff3615b430f86bd0a824214d95f634efaf894Patrik Flykt log_error("System hostname '%s' cannot be normalized.", h);
a9aff3615b430f86bd0a824214d95f634efaf894Patrik Flykt return r;
a9aff3615b430f86bd0a824214d95f634efaf894Patrik Flykt }
a9aff3615b430f86bd0a824214d95f634efaf894Patrik Flykt
a9aff3615b430f86bd0a824214d95f634efaf894Patrik Flykt *ret = n;
a9aff3615b430f86bd0a824214d95f634efaf894Patrik Flykt n = NULL;
a9aff3615b430f86bd0a824214d95f634efaf894Patrik Flykt
a9aff3615b430f86bd0a824214d95f634efaf894Patrik Flykt return 0;
a9aff3615b430f86bd0a824214d95f634efaf894Patrik Flykt}
bbfa43ca37df0718287c25a8e39ee7477ebf33f6Patrik Flykt
bbfa43ca37df0718287c25a8e39ee7477ebf33f6Patrik Flyktstatic int on_hostname_change(sd_event_source *es, int fd, uint32_t revents, void *userdata) {
bbfa43ca37df0718287c25a8e39ee7477ebf33f6Patrik Flykt _cleanup_free_ char *h = NULL;
bbfa43ca37df0718287c25a8e39ee7477ebf33f6Patrik Flykt Manager *m = userdata;
bbfa43ca37df0718287c25a8e39ee7477ebf33f6Patrik Flykt int r;
a9aff3615b430f86bd0a824214d95f634efaf894Patrik Flykt
a9aff3615b430f86bd0a824214d95f634efaf894Patrik Flykt assert(m);
a9aff3615b430f86bd0a824214d95f634efaf894Patrik Flykt
ed6ee21953dac9c78383da00bc4514ece6b75ab5Patrik Flykt r = determine_hostname(&h);
ed6ee21953dac9c78383da00bc4514ece6b75ab5Patrik Flykt if (r < 0)
926695f1b5f9395eeb416cc2f478a9cf75fdbeb4Thomas Hindoe Paaboel Andersen return 0; /* ignore invalid hostnames */
926695f1b5f9395eeb416cc2f478a9cf75fdbeb4Thomas Hindoe Paaboel Andersen
ed6ee21953dac9c78383da00bc4514ece6b75ab5Patrik Flykt if (streq(h, m->hostname))
7246333cb803b03440d3bd0bdaa233564d09b5aePatrik Flykt return 0;
a9aff3615b430f86bd0a824214d95f634efaf894Patrik Flykt
a9aff3615b430f86bd0a824214d95f634efaf894Patrik Flykt log_info("System hostname changed to '%s'.", h);
a9aff3615b430f86bd0a824214d95f634efaf894Patrik Flykt free(m->hostname);
7246333cb803b03440d3bd0bdaa233564d09b5aePatrik Flykt m->hostname = h;
7246333cb803b03440d3bd0bdaa233564d09b5aePatrik Flykt h = NULL;
7246333cb803b03440d3bd0bdaa233564d09b5aePatrik Flykt
3dc34fcc97b41f8b7b019027225b121dfbb9871dPatrik Flykt manager_refresh_rrs(m);
3dc34fcc97b41f8b7b019027225b121dfbb9871dPatrik Flykt
3dc34fcc97b41f8b7b019027225b121dfbb9871dPatrik Flykt return 0;
3dc34fcc97b41f8b7b019027225b121dfbb9871dPatrik Flykt}
3dc34fcc97b41f8b7b019027225b121dfbb9871dPatrik Flykt
3dc34fcc97b41f8b7b019027225b121dfbb9871dPatrik Flyktstatic int manager_watch_hostname(Manager *m) {
7246333cb803b03440d3bd0bdaa233564d09b5aePatrik Flykt int r;
7246333cb803b03440d3bd0bdaa233564d09b5aePatrik Flykt
7246333cb803b03440d3bd0bdaa233564d09b5aePatrik Flykt assert(m);
7246333cb803b03440d3bd0bdaa233564d09b5aePatrik Flykt
7246333cb803b03440d3bd0bdaa233564d09b5aePatrik Flykt m->hostname_fd = open("/proc/sys/kernel/hostname", O_RDONLY|O_CLOEXEC|O_NDELAY|O_NOCTTY);
7246333cb803b03440d3bd0bdaa233564d09b5aePatrik Flykt if (m->hostname_fd < 0) {
7246333cb803b03440d3bd0bdaa233564d09b5aePatrik Flykt log_warning("Failed to watch hostname: %m");
7246333cb803b03440d3bd0bdaa233564d09b5aePatrik Flykt return 0;
a9aff3615b430f86bd0a824214d95f634efaf894Patrik Flykt }
a9aff3615b430f86bd0a824214d95f634efaf894Patrik Flykt
a9aff3615b430f86bd0a824214d95f634efaf894Patrik Flykt r = sd_event_add_io(m->event, &m->hostname_event_source, m->hostname_fd, 0, on_hostname_change, m);
a9aff3615b430f86bd0a824214d95f634efaf894Patrik Flykt if (r < 0) {
a9aff3615b430f86bd0a824214d95f634efaf894Patrik Flykt if (r == -EPERM)
3dc34fcc97b41f8b7b019027225b121dfbb9871dPatrik Flykt /* kernels prior to 3.2 don't support polling this file. Ignore the failure. */
3dc34fcc97b41f8b7b019027225b121dfbb9871dPatrik Flykt m->hostname_fd = safe_close(m->hostname_fd);
3dc34fcc97b41f8b7b019027225b121dfbb9871dPatrik Flykt else {
3dc34fcc97b41f8b7b019027225b121dfbb9871dPatrik Flykt log_error("Failed to add hostname event source: %s", strerror(-r));
3dc34fcc97b41f8b7b019027225b121dfbb9871dPatrik Flykt return r;
3dc34fcc97b41f8b7b019027225b121dfbb9871dPatrik Flykt }
3dc34fcc97b41f8b7b019027225b121dfbb9871dPatrik Flykt }
3dc34fcc97b41f8b7b019027225b121dfbb9871dPatrik Flykt
3dc34fcc97b41f8b7b019027225b121dfbb9871dPatrik Flykt r = determine_hostname(&m->hostname);
a9aff3615b430f86bd0a824214d95f634efaf894Patrik Flykt if (r < 0) {
a34b57c0d43b8bf819ccd4f62c314b41b625454dPatrik Flykt log_info("Defaulting to hostname 'linux'.");
a9aff3615b430f86bd0a824214d95f634efaf894Patrik Flykt m->hostname = strdup("linux");
a9aff3615b430f86bd0a824214d95f634efaf894Patrik Flykt if (!m->hostname)
a9aff3615b430f86bd0a824214d95f634efaf894Patrik Flykt return log_oom();
da6fe470e17fa02f3adedc779585caf8669252bdPatrik Flykt } else
da6fe470e17fa02f3adedc779585caf8669252bdPatrik Flykt log_info("Using system hostname '%s'.", m->hostname);
da6fe470e17fa02f3adedc779585caf8669252bdPatrik Flykt
da6fe470e17fa02f3adedc779585caf8669252bdPatrik Flykt return 0;
da6fe470e17fa02f3adedc779585caf8669252bdPatrik Flykt}
da6fe470e17fa02f3adedc779585caf8669252bdPatrik Flykt
cc22955cfefb4bd6e7a135f1ec95fb5a07ba9ce3Thomas Hallerstatic void manager_llmnr_stop(Manager *m) {
7246333cb803b03440d3bd0bdaa233564d09b5aePatrik Flykt assert(m);
66eac1201a9c1596f5901f8dbbf24bda7e350878Dan Williams
7246333cb803b03440d3bd0bdaa233564d09b5aePatrik Flykt m->llmnr_ipv4_udp_event_source = sd_event_source_unref(m->llmnr_ipv4_udp_event_source);
7246333cb803b03440d3bd0bdaa233564d09b5aePatrik Flykt m->llmnr_ipv4_udp_fd = safe_close(m->llmnr_ipv4_udp_fd);
7246333cb803b03440d3bd0bdaa233564d09b5aePatrik Flykt
346e13a25dc6f76d3bc9d8decd40dc4782b02d2aPatrik Flykt m->llmnr_ipv6_udp_event_source = sd_event_source_unref(m->llmnr_ipv6_udp_event_source);
346e13a25dc6f76d3bc9d8decd40dc4782b02d2aPatrik Flykt m->llmnr_ipv6_udp_fd = safe_close(m->llmnr_ipv6_udp_fd);
346e13a25dc6f76d3bc9d8decd40dc4782b02d2aPatrik Flykt
346e13a25dc6f76d3bc9d8decd40dc4782b02d2aPatrik Flykt m->llmnr_ipv4_tcp_event_source = sd_event_source_unref(m->llmnr_ipv4_tcp_event_source);
346e13a25dc6f76d3bc9d8decd40dc4782b02d2aPatrik Flykt m->llmnr_ipv4_tcp_fd = safe_close(m->llmnr_ipv4_tcp_fd);
346e13a25dc6f76d3bc9d8decd40dc4782b02d2aPatrik Flykt
346e13a25dc6f76d3bc9d8decd40dc4782b02d2aPatrik Flykt m->llmnr_ipv6_tcp_event_source = sd_event_source_unref(m->llmnr_ipv6_tcp_event_source);
346e13a25dc6f76d3bc9d8decd40dc4782b02d2aPatrik Flykt m->llmnr_ipv6_tcp_fd = safe_close(m->llmnr_ipv6_tcp_fd);
346e13a25dc6f76d3bc9d8decd40dc4782b02d2aPatrik Flykt}
346e13a25dc6f76d3bc9d8decd40dc4782b02d2aPatrik Flykt
346e13a25dc6f76d3bc9d8decd40dc4782b02d2aPatrik Flyktstatic int manager_llmnr_start(Manager *m) {
a9aff3615b430f86bd0a824214d95f634efaf894Patrik Flykt int r;
a9aff3615b430f86bd0a824214d95f634efaf894Patrik Flykt
a9aff3615b430f86bd0a824214d95f634efaf894Patrik Flykt assert(m);
a9aff3615b430f86bd0a824214d95f634efaf894Patrik Flykt
a9aff3615b430f86bd0a824214d95f634efaf894Patrik Flykt if (m->llmnr_support == SUPPORT_NO)
a9aff3615b430f86bd0a824214d95f634efaf894Patrik Flykt return 0;
a9aff3615b430f86bd0a824214d95f634efaf894Patrik Flykt
a9aff3615b430f86bd0a824214d95f634efaf894Patrik Flykt r = manager_llmnr_ipv4_udp_fd(m);
a9aff3615b430f86bd0a824214d95f634efaf894Patrik Flykt if (r == -EADDRINUSE)
a9aff3615b430f86bd0a824214d95f634efaf894Patrik Flykt goto eaddrinuse;
a9aff3615b430f86bd0a824214d95f634efaf894Patrik Flykt if (r < 0)
a34b57c0d43b8bf819ccd4f62c314b41b625454dPatrik Flykt return r;
a34b57c0d43b8bf819ccd4f62c314b41b625454dPatrik Flykt
a34b57c0d43b8bf819ccd4f62c314b41b625454dPatrik Flykt r = manager_llmnr_ipv6_udp_fd(m);
a34b57c0d43b8bf819ccd4f62c314b41b625454dPatrik Flykt if (r == -EADDRINUSE)
a34b57c0d43b8bf819ccd4f62c314b41b625454dPatrik Flykt goto eaddrinuse;
a34b57c0d43b8bf819ccd4f62c314b41b625454dPatrik Flykt if (r < 0)
a34b57c0d43b8bf819ccd4f62c314b41b625454dPatrik Flykt return r;
a34b57c0d43b8bf819ccd4f62c314b41b625454dPatrik Flykt
a34b57c0d43b8bf819ccd4f62c314b41b625454dPatrik Flykt r = manager_llmnr_ipv4_tcp_fd(m);
a34b57c0d43b8bf819ccd4f62c314b41b625454dPatrik Flykt if (r == -EADDRINUSE)
a34b57c0d43b8bf819ccd4f62c314b41b625454dPatrik Flykt goto eaddrinuse;
a34b57c0d43b8bf819ccd4f62c314b41b625454dPatrik Flykt if (r < 0)
a34b57c0d43b8bf819ccd4f62c314b41b625454dPatrik Flykt return r;
3dc34fcc97b41f8b7b019027225b121dfbb9871dPatrik Flykt
3dc34fcc97b41f8b7b019027225b121dfbb9871dPatrik Flykt r = manager_llmnr_ipv6_tcp_fd(m);
a34b57c0d43b8bf819ccd4f62c314b41b625454dPatrik Flykt if (r == -EADDRINUSE)
a34b57c0d43b8bf819ccd4f62c314b41b625454dPatrik Flykt goto eaddrinuse;
a34b57c0d43b8bf819ccd4f62c314b41b625454dPatrik Flykt if (r < 0)
a34b57c0d43b8bf819ccd4f62c314b41b625454dPatrik Flykt return r;
a34b57c0d43b8bf819ccd4f62c314b41b625454dPatrik Flykt
a34b57c0d43b8bf819ccd4f62c314b41b625454dPatrik Flykt return 0;
a34b57c0d43b8bf819ccd4f62c314b41b625454dPatrik Flykt
a34b57c0d43b8bf819ccd4f62c314b41b625454dPatrik Flykteaddrinuse:
a34b57c0d43b8bf819ccd4f62c314b41b625454dPatrik Flykt log_warning("There appears to be another LLMNR respondering running. Turning off LLMNR support.");
a34b57c0d43b8bf819ccd4f62c314b41b625454dPatrik Flykt m->llmnr_support = SUPPORT_NO;
a34b57c0d43b8bf819ccd4f62c314b41b625454dPatrik Flykt manager_llmnr_stop(m);
a34b57c0d43b8bf819ccd4f62c314b41b625454dPatrik Flykt return 0;
a34b57c0d43b8bf819ccd4f62c314b41b625454dPatrik Flykt}
a34b57c0d43b8bf819ccd4f62c314b41b625454dPatrik Flykt
a34b57c0d43b8bf819ccd4f62c314b41b625454dPatrik Flyktint manager_new(Manager **ret) {
a34b57c0d43b8bf819ccd4f62c314b41b625454dPatrik Flykt _cleanup_(manager_freep) Manager *m = NULL;
3dc34fcc97b41f8b7b019027225b121dfbb9871dPatrik Flykt int r;
3dc34fcc97b41f8b7b019027225b121dfbb9871dPatrik Flykt
a34b57c0d43b8bf819ccd4f62c314b41b625454dPatrik Flykt assert(ret);
a34b57c0d43b8bf819ccd4f62c314b41b625454dPatrik Flykt
a34b57c0d43b8bf819ccd4f62c314b41b625454dPatrik Flykt m = new0(Manager, 1);
d1b0afe3653b4316a6361d204169620726d468a0Patrik Flykt if (!m)
d1b0afe3653b4316a6361d204169620726d468a0Patrik Flykt return -ENOMEM;
d1b0afe3653b4316a6361d204169620726d468a0Patrik Flykt
3dc34fcc97b41f8b7b019027225b121dfbb9871dPatrik Flykt m->dns_ipv4_fd = m->dns_ipv6_fd = -1;
3dc34fcc97b41f8b7b019027225b121dfbb9871dPatrik Flykt m->llmnr_ipv4_udp_fd = m->llmnr_ipv6_udp_fd = -1;
d1b0afe3653b4316a6361d204169620726d468a0Patrik Flykt m->llmnr_ipv4_tcp_fd = m->llmnr_ipv6_tcp_fd = -1;
d1b0afe3653b4316a6361d204169620726d468a0Patrik Flykt m->hostname_fd = -1;
d1b0afe3653b4316a6361d204169620726d468a0Patrik Flykt
d1b0afe3653b4316a6361d204169620726d468a0Patrik Flykt m->llmnr_support = SUPPORT_YES;
d1b0afe3653b4316a6361d204169620726d468a0Patrik Flykt m->read_resolv_conf = true;
3dc34fcc97b41f8b7b019027225b121dfbb9871dPatrik Flykt
3dc34fcc97b41f8b7b019027225b121dfbb9871dPatrik Flykt r = manager_parse_dns_server(m, DNS_SERVER_FALLBACK, DNS_SERVERS);
d1b0afe3653b4316a6361d204169620726d468a0Patrik Flykt if (r < 0)
d1b0afe3653b4316a6361d204169620726d468a0Patrik Flykt return r;
3dc34fcc97b41f8b7b019027225b121dfbb9871dPatrik Flykt
3dc34fcc97b41f8b7b019027225b121dfbb9871dPatrik Flykt r = sd_event_default(&m->event);
3dc34fcc97b41f8b7b019027225b121dfbb9871dPatrik Flykt if (r < 0)
3dc34fcc97b41f8b7b019027225b121dfbb9871dPatrik Flykt return r;
3dc34fcc97b41f8b7b019027225b121dfbb9871dPatrik Flykt
d1b0afe3653b4316a6361d204169620726d468a0Patrik Flykt sd_event_add_signal(m->event, NULL, SIGTERM, NULL, NULL);
d1b0afe3653b4316a6361d204169620726d468a0Patrik Flykt sd_event_add_signal(m->event, NULL, SIGINT, NULL, NULL);
d1b0afe3653b4316a6361d204169620726d468a0Patrik Flykt
d1b0afe3653b4316a6361d204169620726d468a0Patrik Flykt sd_event_set_watchdog(m->event, true);
d1b0afe3653b4316a6361d204169620726d468a0Patrik Flykt
d1b0afe3653b4316a6361d204169620726d468a0Patrik Flykt r = manager_watch_hostname(m);
d1b0afe3653b4316a6361d204169620726d468a0Patrik Flykt if (r < 0)
d1b0afe3653b4316a6361d204169620726d468a0Patrik Flykt return r;
d1b0afe3653b4316a6361d204169620726d468a0Patrik Flykt
d1b0afe3653b4316a6361d204169620726d468a0Patrik Flykt r = dns_scope_new(m, &m->unicast_scope, NULL, DNS_PROTOCOL_DNS, AF_UNSPEC);
d1b0afe3653b4316a6361d204169620726d468a0Patrik Flykt if (r < 0)
d1b0afe3653b4316a6361d204169620726d468a0Patrik Flykt return r;
4b4923e65423e60d755841b5b264730e8f3deab3Tom Gundersen
5e91345094a9e983e7abb2313334e7808bcd2cc2Tom Gundersen r = manager_network_monitor_listen(m);
513a6fa8679510ea1b55967bdb482dd5f8a39f21Ronny Chevalier if (r < 0)
d1b0afe3653b4316a6361d204169620726d468a0Patrik Flykt return r;
3dc34fcc97b41f8b7b019027225b121dfbb9871dPatrik Flykt
d1b0afe3653b4316a6361d204169620726d468a0Patrik Flykt r = manager_rtnl_listen(m);
d1b0afe3653b4316a6361d204169620726d468a0Patrik Flykt if (r < 0)
d1b0afe3653b4316a6361d204169620726d468a0Patrik Flykt return r;
d1b0afe3653b4316a6361d204169620726d468a0Patrik Flykt
d1b0afe3653b4316a6361d204169620726d468a0Patrik Flykt r = manager_connect_bus(m);
d1b0afe3653b4316a6361d204169620726d468a0Patrik Flykt if (r < 0)
d1b0afe3653b4316a6361d204169620726d468a0Patrik Flykt return r;
d1b0afe3653b4316a6361d204169620726d468a0Patrik Flykt
bbfa43ca37df0718287c25a8e39ee7477ebf33f6Patrik Flykt *ret = m;
bbfa43ca37df0718287c25a8e39ee7477ebf33f6Patrik Flykt m = NULL;
bbfa43ca37df0718287c25a8e39ee7477ebf33f6Patrik Flykt
bbfa43ca37df0718287c25a8e39ee7477ebf33f6Patrik Flykt return 0;
bbfa43ca37df0718287c25a8e39ee7477ebf33f6Patrik Flykt}
bbfa43ca37df0718287c25a8e39ee7477ebf33f6Patrik Flykt
d1b0afe3653b4316a6361d204169620726d468a0Patrik Flyktint manager_start(Manager *m) {
7246333cb803b03440d3bd0bdaa233564d09b5aePatrik Flykt int r;
7246333cb803b03440d3bd0bdaa233564d09b5aePatrik Flykt
7246333cb803b03440d3bd0bdaa233564d09b5aePatrik Flykt assert(m);
7246333cb803b03440d3bd0bdaa233564d09b5aePatrik Flykt
7246333cb803b03440d3bd0bdaa233564d09b5aePatrik Flykt r = manager_llmnr_start(m);
7246333cb803b03440d3bd0bdaa233564d09b5aePatrik Flykt if (r < 0)
d1b0afe3653b4316a6361d204169620726d468a0Patrik Flykt return r;
d1b0afe3653b4316a6361d204169620726d468a0Patrik Flykt
d1b0afe3653b4316a6361d204169620726d468a0Patrik Flykt return 0;
d1b0afe3653b4316a6361d204169620726d468a0Patrik Flykt}
d1b0afe3653b4316a6361d204169620726d468a0Patrik Flykt
7246333cb803b03440d3bd0bdaa233564d09b5aePatrik FlyktManager *manager_free(Manager *m) {
7246333cb803b03440d3bd0bdaa233564d09b5aePatrik Flykt Link *l;
7246333cb803b03440d3bd0bdaa233564d09b5aePatrik Flykt
7246333cb803b03440d3bd0bdaa233564d09b5aePatrik Flykt if (!m)
7246333cb803b03440d3bd0bdaa233564d09b5aePatrik Flykt return NULL;
7246333cb803b03440d3bd0bdaa233564d09b5aePatrik Flykt
7246333cb803b03440d3bd0bdaa233564d09b5aePatrik Flykt while ((l = hashmap_first(m->links)))
3dc34fcc97b41f8b7b019027225b121dfbb9871dPatrik Flykt link_free(l);
3dc34fcc97b41f8b7b019027225b121dfbb9871dPatrik Flykt
3dc34fcc97b41f8b7b019027225b121dfbb9871dPatrik Flykt while (m->dns_queries)
3dc34fcc97b41f8b7b019027225b121dfbb9871dPatrik Flykt dns_query_free(m->dns_queries);
3dc34fcc97b41f8b7b019027225b121dfbb9871dPatrik Flykt
3dc34fcc97b41f8b7b019027225b121dfbb9871dPatrik Flykt dns_scope_free(m->unicast_scope);
3dc34fcc97b41f8b7b019027225b121dfbb9871dPatrik Flykt
3dc34fcc97b41f8b7b019027225b121dfbb9871dPatrik Flykt while (m->dns_servers)
3dc34fcc97b41f8b7b019027225b121dfbb9871dPatrik Flykt dns_server_free(m->dns_servers);
3dc34fcc97b41f8b7b019027225b121dfbb9871dPatrik Flykt while (m->fallback_dns_servers)
3dc34fcc97b41f8b7b019027225b121dfbb9871dPatrik Flykt dns_server_free(m->fallback_dns_servers);
3dc34fcc97b41f8b7b019027225b121dfbb9871dPatrik Flykt
3dc34fcc97b41f8b7b019027225b121dfbb9871dPatrik Flykt hashmap_free(m->links);
3dc34fcc97b41f8b7b019027225b121dfbb9871dPatrik Flykt hashmap_free(m->dns_transactions);
3dc34fcc97b41f8b7b019027225b121dfbb9871dPatrik Flykt
3dc34fcc97b41f8b7b019027225b121dfbb9871dPatrik Flykt sd_event_source_unref(m->network_event_source);
3dc34fcc97b41f8b7b019027225b121dfbb9871dPatrik Flykt sd_network_monitor_unref(m->network_monitor);
3dc34fcc97b41f8b7b019027225b121dfbb9871dPatrik Flykt
3dc34fcc97b41f8b7b019027225b121dfbb9871dPatrik Flykt sd_event_source_unref(m->dns_ipv4_event_source);
3dc34fcc97b41f8b7b019027225b121dfbb9871dPatrik Flykt sd_event_source_unref(m->dns_ipv6_event_source);
3dc34fcc97b41f8b7b019027225b121dfbb9871dPatrik Flykt safe_close(m->dns_ipv4_fd);
3dc34fcc97b41f8b7b019027225b121dfbb9871dPatrik Flykt safe_close(m->dns_ipv6_fd);
3dc34fcc97b41f8b7b019027225b121dfbb9871dPatrik Flykt
3dc34fcc97b41f8b7b019027225b121dfbb9871dPatrik Flykt manager_llmnr_stop(m);
3dc34fcc97b41f8b7b019027225b121dfbb9871dPatrik Flykt
3dc34fcc97b41f8b7b019027225b121dfbb9871dPatrik Flykt sd_event_source_unref(m->bus_retry_event_source);
d1b0afe3653b4316a6361d204169620726d468a0Patrik Flykt sd_bus_unref(m->bus);
a34b57c0d43b8bf819ccd4f62c314b41b625454dPatrik Flykt
d1b0afe3653b4316a6361d204169620726d468a0Patrik Flykt sd_event_unref(m->event);
d1b0afe3653b4316a6361d204169620726d468a0Patrik Flykt
d1b0afe3653b4316a6361d204169620726d468a0Patrik Flykt dns_resource_key_unref(m->host_ipv4_key);
d1b0afe3653b4316a6361d204169620726d468a0Patrik Flykt dns_resource_key_unref(m->host_ipv6_key);
d1b0afe3653b4316a6361d204169620726d468a0Patrik Flykt
d1b0afe3653b4316a6361d204169620726d468a0Patrik Flykt safe_close(m->hostname_fd);
d1b0afe3653b4316a6361d204169620726d468a0Patrik Flykt sd_event_source_unref(m->hostname_event_source);
d1b0afe3653b4316a6361d204169620726d468a0Patrik Flykt free(m->hostname);
d1b0afe3653b4316a6361d204169620726d468a0Patrik Flykt
fa94c34b083b5b4019975624453e53d0cbad2a5dTom Gundersen free(m);
d1b0afe3653b4316a6361d204169620726d468a0Patrik Flykt
d1b0afe3653b4316a6361d204169620726d468a0Patrik Flykt return NULL;
d1b0afe3653b4316a6361d204169620726d468a0Patrik Flykt}
346e13a25dc6f76d3bc9d8decd40dc4782b02d2aPatrik Flykt
346e13a25dc6f76d3bc9d8decd40dc4782b02d2aPatrik Flyktint manager_read_resolv_conf(Manager *m) {
346e13a25dc6f76d3bc9d8decd40dc4782b02d2aPatrik Flykt _cleanup_fclose_ FILE *f = NULL;
346e13a25dc6f76d3bc9d8decd40dc4782b02d2aPatrik Flykt struct stat st, own;
d1b0afe3653b4316a6361d204169620726d468a0Patrik Flykt char line[LINE_MAX];
d1b0afe3653b4316a6361d204169620726d468a0Patrik Flykt DnsServer *s, *nx;
d1b0afe3653b4316a6361d204169620726d468a0Patrik Flykt usec_t t;
a9aff3615b430f86bd0a824214d95f634efaf894Patrik Flykt int r;
a9aff3615b430f86bd0a824214d95f634efaf894Patrik Flykt
a9aff3615b430f86bd0a824214d95f634efaf894Patrik Flykt assert(m);
a9aff3615b430f86bd0a824214d95f634efaf894Patrik Flykt
d1b0afe3653b4316a6361d204169620726d468a0Patrik Flykt /* Reads the system /etc/resolv.conf, if it exists and is not
d1b0afe3653b4316a6361d204169620726d468a0Patrik Flykt * symlinked to our own resolv.conf instance */
d1b0afe3653b4316a6361d204169620726d468a0Patrik Flykt
d1b0afe3653b4316a6361d204169620726d468a0Patrik Flykt if (!m->read_resolv_conf)
d1b0afe3653b4316a6361d204169620726d468a0Patrik Flykt return 0;
d1b0afe3653b4316a6361d204169620726d468a0Patrik Flykt
d1b0afe3653b4316a6361d204169620726d468a0Patrik Flykt r = stat("/etc/resolv.conf", &st);
d1b0afe3653b4316a6361d204169620726d468a0Patrik Flykt if (r < 0) {
d1b0afe3653b4316a6361d204169620726d468a0Patrik Flykt if (errno != ENOENT)
d1b0afe3653b4316a6361d204169620726d468a0Patrik Flykt log_warning("Failed to open /etc/resolv.conf: %m");
d1b0afe3653b4316a6361d204169620726d468a0Patrik Flykt r = -errno;
d1b0afe3653b4316a6361d204169620726d468a0Patrik Flykt goto clear;
d1b0afe3653b4316a6361d204169620726d468a0Patrik Flykt }
fa94c34b083b5b4019975624453e53d0cbad2a5dTom Gundersen
d1b0afe3653b4316a6361d204169620726d468a0Patrik Flykt /* Have we already seen the file? */
d1b0afe3653b4316a6361d204169620726d468a0Patrik Flykt t = timespec_load(&st.st_mtim);
d1b0afe3653b4316a6361d204169620726d468a0Patrik Flykt if (t == m->resolv_conf_mtime)
d1b0afe3653b4316a6361d204169620726d468a0Patrik Flykt return 0;
d1b0afe3653b4316a6361d204169620726d468a0Patrik Flykt
d1b0afe3653b4316a6361d204169620726d468a0Patrik Flykt m->resolv_conf_mtime = t;
d1b0afe3653b4316a6361d204169620726d468a0Patrik Flykt
d1b0afe3653b4316a6361d204169620726d468a0Patrik Flykt /* Is it symlinked to our own file? */
d1b0afe3653b4316a6361d204169620726d468a0Patrik Flykt if (stat("/run/systemd/resolve/resolv.conf", &own) >= 0 &&
d1b0afe3653b4316a6361d204169620726d468a0Patrik Flykt st.st_dev == own.st_dev &&
d1b0afe3653b4316a6361d204169620726d468a0Patrik Flykt st.st_ino == own.st_ino) {
356779df90a2ecab5da2cb310ad0f8ebc9ca9f46Lennart Poettering r = 0;
9021bb9f935c93b516b10c88db2a212a9e3a8140Tom Gundersen goto clear;
9021bb9f935c93b516b10c88db2a212a9e3a8140Tom Gundersen }
9021bb9f935c93b516b10c88db2a212a9e3a8140Tom Gundersen
d1b0afe3653b4316a6361d204169620726d468a0Patrik Flykt f = fopen("/etc/resolv.conf", "re");
d1b0afe3653b4316a6361d204169620726d468a0Patrik Flykt if (!f) {
d1b0afe3653b4316a6361d204169620726d468a0Patrik Flykt if (errno != ENOENT)
d1b0afe3653b4316a6361d204169620726d468a0Patrik Flykt log_warning("Failed to open /etc/resolv.conf: %m");
d1b0afe3653b4316a6361d204169620726d468a0Patrik Flykt r = -errno;
d1b0afe3653b4316a6361d204169620726d468a0Patrik Flykt goto clear;
d1b0afe3653b4316a6361d204169620726d468a0Patrik Flykt }
fa94c34b083b5b4019975624453e53d0cbad2a5dTom Gundersen
d1b0afe3653b4316a6361d204169620726d468a0Patrik Flykt if (fstat(fileno(f), &st) < 0) {
d1b0afe3653b4316a6361d204169620726d468a0Patrik Flykt log_error("Failed to stat open file: %m");
d1b0afe3653b4316a6361d204169620726d468a0Patrik Flykt r = -errno;
d1b0afe3653b4316a6361d204169620726d468a0Patrik Flykt goto clear;
d1b0afe3653b4316a6361d204169620726d468a0Patrik Flykt }
d1b0afe3653b4316a6361d204169620726d468a0Patrik Flykt
d1b0afe3653b4316a6361d204169620726d468a0Patrik Flykt LIST_FOREACH(servers, s, m->dns_servers)
d1b0afe3653b4316a6361d204169620726d468a0Patrik Flykt s->marked = true;
d1b0afe3653b4316a6361d204169620726d468a0Patrik Flykt
d1b0afe3653b4316a6361d204169620726d468a0Patrik Flykt FOREACH_LINE(line, f, r = -errno; goto clear) {
9021bb9f935c93b516b10c88db2a212a9e3a8140Tom Gundersen union in_addr_union address;
356779df90a2ecab5da2cb310ad0f8ebc9ca9f46Lennart Poettering int family;
9021bb9f935c93b516b10c88db2a212a9e3a8140Tom Gundersen char *l;
9021bb9f935c93b516b10c88db2a212a9e3a8140Tom Gundersen const char *a;
d1b0afe3653b4316a6361d204169620726d468a0Patrik Flykt
d1b0afe3653b4316a6361d204169620726d468a0Patrik Flykt truncate_nl(line);
d1b0afe3653b4316a6361d204169620726d468a0Patrik Flykt
d1b0afe3653b4316a6361d204169620726d468a0Patrik Flykt l = strstrip(line);
d1b0afe3653b4316a6361d204169620726d468a0Patrik Flykt if (*l == '#' || *l == ';')
d1b0afe3653b4316a6361d204169620726d468a0Patrik Flykt continue;
d1b0afe3653b4316a6361d204169620726d468a0Patrik Flykt
d1b0afe3653b4316a6361d204169620726d468a0Patrik Flykt a = first_word(l, "nameserver");
d1b0afe3653b4316a6361d204169620726d468a0Patrik Flykt if (!a)
f12abb48fc510b8b349c05e35ba048134debaf25Patrik Flykt continue;
cfb5b3805759e63dc5e0cae6e92e1df885b5c5b6Tom Gundersen
f12abb48fc510b8b349c05e35ba048134debaf25Patrik Flykt r = in_addr_from_string_auto(a, &family, &address);
f12abb48fc510b8b349c05e35ba048134debaf25Patrik Flykt if (r < 0) {
f12abb48fc510b8b349c05e35ba048134debaf25Patrik Flykt log_warning("Failed to parse name server %s.", a);
f12abb48fc510b8b349c05e35ba048134debaf25Patrik Flykt continue;
f12abb48fc510b8b349c05e35ba048134debaf25Patrik Flykt }
f12abb48fc510b8b349c05e35ba048134debaf25Patrik Flykt
cfb5b3805759e63dc5e0cae6e92e1df885b5c5b6Tom Gundersen LIST_FOREACH(servers, s, m->dns_servers)
cfb5b3805759e63dc5e0cae6e92e1df885b5c5b6Tom Gundersen if (s->family == family && in_addr_equal(family, &s->address, &address) > 0)
cfb5b3805759e63dc5e0cae6e92e1df885b5c5b6Tom Gundersen break;
f12abb48fc510b8b349c05e35ba048134debaf25Patrik Flykt
f12abb48fc510b8b349c05e35ba048134debaf25Patrik Flykt if (s)
f12abb48fc510b8b349c05e35ba048134debaf25Patrik Flykt s->marked = false;
f12abb48fc510b8b349c05e35ba048134debaf25Patrik Flykt else {
631bbe71298ec892f77f44f94feb612646fe6853Patrik Flykt r = dns_server_new(m, NULL, DNS_SERVER_SYSTEM, NULL, family, &address);
631bbe71298ec892f77f44f94feb612646fe6853Patrik Flykt if (r < 0)
631bbe71298ec892f77f44f94feb612646fe6853Patrik Flykt goto clear;
631bbe71298ec892f77f44f94feb612646fe6853Patrik Flykt }
44481a8b537839cd9ffead4d261491641f5b5260Zbigniew Jędrzejewski-Szmek }
631bbe71298ec892f77f44f94feb612646fe6853Patrik Flykt
631bbe71298ec892f77f44f94feb612646fe6853Patrik Flykt LIST_FOREACH_SAFE(servers, s, nx, m->dns_servers)
631bbe71298ec892f77f44f94feb612646fe6853Patrik Flykt if (s->marked)
631bbe71298ec892f77f44f94feb612646fe6853Patrik Flykt dns_server_free(s);
631bbe71298ec892f77f44f94feb612646fe6853Patrik Flykt
44481a8b537839cd9ffead4d261491641f5b5260Zbigniew Jędrzejewski-Szmek return 0;
44481a8b537839cd9ffead4d261491641f5b5260Zbigniew Jędrzejewski-Szmek
44481a8b537839cd9ffead4d261491641f5b5260Zbigniew Jędrzejewski-Szmekclear:
631bbe71298ec892f77f44f94feb612646fe6853Patrik Flykt while (m->dns_servers)
631bbe71298ec892f77f44f94feb612646fe6853Patrik Flykt dns_server_free(m->dns_servers);
631bbe71298ec892f77f44f94feb612646fe6853Patrik Flykt
631bbe71298ec892f77f44f94feb612646fe6853Patrik Flykt return r;
631bbe71298ec892f77f44f94feb612646fe6853Patrik Flykt}
631bbe71298ec892f77f44f94feb612646fe6853Patrik Flykt
631bbe71298ec892f77f44f94feb612646fe6853Patrik Flyktstatic void write_resolve_conf_server(DnsServer *s, FILE *f, unsigned *count) {
631bbe71298ec892f77f44f94feb612646fe6853Patrik Flykt _cleanup_free_ char *t = NULL;
631bbe71298ec892f77f44f94feb612646fe6853Patrik Flykt int r;
631bbe71298ec892f77f44f94feb612646fe6853Patrik Flykt
66eac1201a9c1596f5901f8dbbf24bda7e350878Dan Williams assert(s);
631bbe71298ec892f77f44f94feb612646fe6853Patrik Flykt assert(f);
631bbe71298ec892f77f44f94feb612646fe6853Patrik Flykt assert(count);
631bbe71298ec892f77f44f94feb612646fe6853Patrik Flykt
631bbe71298ec892f77f44f94feb612646fe6853Patrik Flykt r = in_addr_to_string(s->family, &s->address, &t);
631bbe71298ec892f77f44f94feb612646fe6853Patrik Flykt if (r < 0) {
631bbe71298ec892f77f44f94feb612646fe6853Patrik Flykt log_warning("Invalid DNS address. Ignoring: %s", strerror(-r));
631bbe71298ec892f77f44f94feb612646fe6853Patrik Flykt return;
631bbe71298ec892f77f44f94feb612646fe6853Patrik Flykt }
631bbe71298ec892f77f44f94feb612646fe6853Patrik Flykt
631bbe71298ec892f77f44f94feb612646fe6853Patrik Flykt if (*count == MAXNS)
631bbe71298ec892f77f44f94feb612646fe6853Patrik Flykt fputs("# Too many DNS servers configured, the following entries may be ignored\n", f);
631bbe71298ec892f77f44f94feb612646fe6853Patrik Flykt
631bbe71298ec892f77f44f94feb612646fe6853Patrik Flykt fprintf(f, "nameserver %s\n", t);
631bbe71298ec892f77f44f94feb612646fe6853Patrik Flykt (*count) ++;
631bbe71298ec892f77f44f94feb612646fe6853Patrik Flykt}
631bbe71298ec892f77f44f94feb612646fe6853Patrik Flykt
631bbe71298ec892f77f44f94feb612646fe6853Patrik Flyktint manager_write_resolv_conf(Manager *m) {
631bbe71298ec892f77f44f94feb612646fe6853Patrik Flykt static const char path[] = "/run/systemd/resolve/resolv.conf";
631bbe71298ec892f77f44f94feb612646fe6853Patrik Flykt _cleanup_free_ char *temp_path = NULL;
631bbe71298ec892f77f44f94feb612646fe6853Patrik Flykt _cleanup_fclose_ FILE *f = NULL;
631bbe71298ec892f77f44f94feb612646fe6853Patrik Flykt unsigned count = 0;
631bbe71298ec892f77f44f94feb612646fe6853Patrik Flykt DnsServer *s;
631bbe71298ec892f77f44f94feb612646fe6853Patrik Flykt Iterator i;
631bbe71298ec892f77f44f94feb612646fe6853Patrik Flykt Link *l;
631bbe71298ec892f77f44f94feb612646fe6853Patrik Flykt int r;
631bbe71298ec892f77f44f94feb612646fe6853Patrik Flykt
631bbe71298ec892f77f44f94feb612646fe6853Patrik Flykt assert(m);
631bbe71298ec892f77f44f94feb612646fe6853Patrik Flykt
631bbe71298ec892f77f44f94feb612646fe6853Patrik Flykt /* Read the system /etc/resolv.conf first */
631bbe71298ec892f77f44f94feb612646fe6853Patrik Flykt manager_read_resolv_conf(m);
631bbe71298ec892f77f44f94feb612646fe6853Patrik Flykt
631bbe71298ec892f77f44f94feb612646fe6853Patrik Flykt r = fopen_temporary(path, &f, &temp_path);
631bbe71298ec892f77f44f94feb612646fe6853Patrik Flykt if (r < 0)
631bbe71298ec892f77f44f94feb612646fe6853Patrik Flykt return r;
631bbe71298ec892f77f44f94feb612646fe6853Patrik Flykt
631bbe71298ec892f77f44f94feb612646fe6853Patrik Flykt fchmod(fileno(f), 0644);
631bbe71298ec892f77f44f94feb612646fe6853Patrik Flykt
631bbe71298ec892f77f44f94feb612646fe6853Patrik Flykt fputs("# This file is managed by systemd-resolved(8). Do not edit.\n#\n"
631bbe71298ec892f77f44f94feb612646fe6853Patrik Flykt "# Third party programs must not access this file directly, but\n"
631bbe71298ec892f77f44f94feb612646fe6853Patrik Flykt "# only through the symlink at /etc/resolv.conf. To manage\n"
631bbe71298ec892f77f44f94feb612646fe6853Patrik Flykt "# resolv.conf(5) in a different way, replace the symlink by a\n"
631bbe71298ec892f77f44f94feb612646fe6853Patrik Flykt "# static file or a different symlink.\n\n", f);
631bbe71298ec892f77f44f94feb612646fe6853Patrik Flykt
631bbe71298ec892f77f44f94feb612646fe6853Patrik Flykt LIST_FOREACH(servers, s, m->dns_servers)
631bbe71298ec892f77f44f94feb612646fe6853Patrik Flykt write_resolve_conf_server(s, f, &count);
631bbe71298ec892f77f44f94feb612646fe6853Patrik Flykt
631bbe71298ec892f77f44f94feb612646fe6853Patrik Flykt HASHMAP_FOREACH(l, m->links, i)
631bbe71298ec892f77f44f94feb612646fe6853Patrik Flykt LIST_FOREACH(servers, s, l->dns_servers)
631bbe71298ec892f77f44f94feb612646fe6853Patrik Flykt write_resolve_conf_server(s, f, &count);
bbfa43ca37df0718287c25a8e39ee7477ebf33f6Patrik Flykt
bbfa43ca37df0718287c25a8e39ee7477ebf33f6Patrik Flykt if (count == 0) {
bbfa43ca37df0718287c25a8e39ee7477ebf33f6Patrik Flykt LIST_FOREACH(servers, s, m->fallback_dns_servers)
bbfa43ca37df0718287c25a8e39ee7477ebf33f6Patrik Flykt write_resolve_conf_server(s, f, &count);
bbfa43ca37df0718287c25a8e39ee7477ebf33f6Patrik Flykt }
bbfa43ca37df0718287c25a8e39ee7477ebf33f6Patrik Flykt
631bbe71298ec892f77f44f94feb612646fe6853Patrik Flykt r = fflush_and_check(f);
631bbe71298ec892f77f44f94feb612646fe6853Patrik Flykt if (r < 0)
631bbe71298ec892f77f44f94feb612646fe6853Patrik Flykt goto fail;
631bbe71298ec892f77f44f94feb612646fe6853Patrik Flykt
631bbe71298ec892f77f44f94feb612646fe6853Patrik Flykt if (rename(temp_path, path) < 0) {
631bbe71298ec892f77f44f94feb612646fe6853Patrik Flykt r = -errno;
631bbe71298ec892f77f44f94feb612646fe6853Patrik Flykt goto fail;
631bbe71298ec892f77f44f94feb612646fe6853Patrik Flykt }
631bbe71298ec892f77f44f94feb612646fe6853Patrik Flykt
631bbe71298ec892f77f44f94feb612646fe6853Patrik Flykt return 0;
631bbe71298ec892f77f44f94feb612646fe6853Patrik Flykt
631bbe71298ec892f77f44f94feb612646fe6853Patrik Flyktfail:
631bbe71298ec892f77f44f94feb612646fe6853Patrik Flykt unlink(path);
631bbe71298ec892f77f44f94feb612646fe6853Patrik Flykt unlink(temp_path);
631bbe71298ec892f77f44f94feb612646fe6853Patrik Flykt return r;
631bbe71298ec892f77f44f94feb612646fe6853Patrik Flykt}
ed6ee21953dac9c78383da00bc4514ece6b75ab5Patrik Flykt
ed6ee21953dac9c78383da00bc4514ece6b75ab5Patrik Flyktint manager_recv(Manager *m, int fd, DnsProtocol protocol, DnsPacket **ret) {
ed6ee21953dac9c78383da00bc4514ece6b75ab5Patrik Flykt _cleanup_(dns_packet_unrefp) DnsPacket *p = NULL;
ed6ee21953dac9c78383da00bc4514ece6b75ab5Patrik Flykt union {
ed6ee21953dac9c78383da00bc4514ece6b75ab5Patrik Flykt struct cmsghdr header; /* For alignment */
ed6ee21953dac9c78383da00bc4514ece6b75ab5Patrik Flykt uint8_t buffer[CMSG_SPACE(MAX(sizeof(struct in_pktinfo), sizeof(struct in6_pktinfo)))
ed6ee21953dac9c78383da00bc4514ece6b75ab5Patrik Flykt + CMSG_SPACE(int) /* ttl/hoplimit */
7bd8e95d44977833d0de3fc4e893eb3bc84351d6Patrik Flykt + EXTRA_CMSG_SPACE /* kernel appears to require extra buffer space */];
7bd8e95d44977833d0de3fc4e893eb3bc84351d6Patrik Flykt } control;
7bd8e95d44977833d0de3fc4e893eb3bc84351d6Patrik Flykt union sockaddr_union sa;
7bd8e95d44977833d0de3fc4e893eb3bc84351d6Patrik Flykt struct msghdr mh = {};
7bd8e95d44977833d0de3fc4e893eb3bc84351d6Patrik Flykt struct cmsghdr *cmsg;
7bd8e95d44977833d0de3fc4e893eb3bc84351d6Patrik Flykt struct iovec iov;
7bd8e95d44977833d0de3fc4e893eb3bc84351d6Patrik Flykt int ms = 0, r;
5da1b97f3c3d15521f2dcfbc18eccd6580122ebcPatrik Flykt ssize_t l;
5da1b97f3c3d15521f2dcfbc18eccd6580122ebcPatrik Flykt
5da1b97f3c3d15521f2dcfbc18eccd6580122ebcPatrik Flykt assert(m);
5da1b97f3c3d15521f2dcfbc18eccd6580122ebcPatrik Flykt assert(fd >= 0);
5da1b97f3c3d15521f2dcfbc18eccd6580122ebcPatrik Flykt assert(ret);
5da1b97f3c3d15521f2dcfbc18eccd6580122ebcPatrik Flykt
5da1b97f3c3d15521f2dcfbc18eccd6580122ebcPatrik Flykt r = ioctl(fd, FIONREAD, &ms);
5da1b97f3c3d15521f2dcfbc18eccd6580122ebcPatrik Flykt if (r < 0)
6599680e2d33597f0f11a99e1c3c957b42418568Patrik Flykt return -errno;
6599680e2d33597f0f11a99e1c3c957b42418568Patrik Flykt if (ms < 0)
6599680e2d33597f0f11a99e1c3c957b42418568Patrik Flykt return -EIO;
6599680e2d33597f0f11a99e1c3c957b42418568Patrik Flykt
6599680e2d33597f0f11a99e1c3c957b42418568Patrik Flykt r = dns_packet_new(&p, protocol, ms);
6599680e2d33597f0f11a99e1c3c957b42418568Patrik Flykt if (r < 0)
41e4615d4f4f5c61afa84ba857f23c0ac496687bPatrik Flykt return r;
41e4615d4f4f5c61afa84ba857f23c0ac496687bPatrik Flykt
41e4615d4f4f5c61afa84ba857f23c0ac496687bPatrik Flykt iov.iov_base = DNS_PACKET_DATA(p);
41e4615d4f4f5c61afa84ba857f23c0ac496687bPatrik Flykt iov.iov_len = p->allocated;
41e4615d4f4f5c61afa84ba857f23c0ac496687bPatrik Flykt
41e4615d4f4f5c61afa84ba857f23c0ac496687bPatrik Flykt mh.msg_name = &sa.sa;
41e4615d4f4f5c61afa84ba857f23c0ac496687bPatrik Flykt mh.msg_namelen = sizeof(sa);
631bbe71298ec892f77f44f94feb612646fe6853Patrik Flykt mh.msg_iov = &iov;
6599680e2d33597f0f11a99e1c3c957b42418568Patrik Flykt mh.msg_iovlen = 1;
631bbe71298ec892f77f44f94feb612646fe6853Patrik Flykt mh.msg_control = &control;
631bbe71298ec892f77f44f94feb612646fe6853Patrik Flykt mh.msg_controllen = sizeof(control);
c47e8936a43ce546e8a74fa569e9fbfae6c64be7Patrik Flykt
c47e8936a43ce546e8a74fa569e9fbfae6c64be7Patrik Flykt l = recvmsg(fd, &mh, 0);
c47e8936a43ce546e8a74fa569e9fbfae6c64be7Patrik Flykt if (l < 0) {
c47e8936a43ce546e8a74fa569e9fbfae6c64be7Patrik Flykt if (errno == EAGAIN || errno == EINTR)
631bbe71298ec892f77f44f94feb612646fe6853Patrik Flykt return 0;
631bbe71298ec892f77f44f94feb612646fe6853Patrik Flykt
631bbe71298ec892f77f44f94feb612646fe6853Patrik Flykt return -errno;
631bbe71298ec892f77f44f94feb612646fe6853Patrik Flykt }
631bbe71298ec892f77f44f94feb612646fe6853Patrik Flykt
bbfa43ca37df0718287c25a8e39ee7477ebf33f6Patrik Flykt if (l <= 0)
bbfa43ca37df0718287c25a8e39ee7477ebf33f6Patrik Flykt return -EIO;
bbfa43ca37df0718287c25a8e39ee7477ebf33f6Patrik Flykt
bbfa43ca37df0718287c25a8e39ee7477ebf33f6Patrik Flykt assert(!(mh.msg_flags & MSG_CTRUNC));
bbfa43ca37df0718287c25a8e39ee7477ebf33f6Patrik Flykt assert(!(mh.msg_flags & MSG_TRUNC));
bbfa43ca37df0718287c25a8e39ee7477ebf33f6Patrik Flykt
631bbe71298ec892f77f44f94feb612646fe6853Patrik Flykt p->size = (size_t) l;
631bbe71298ec892f77f44f94feb612646fe6853Patrik Flykt
631bbe71298ec892f77f44f94feb612646fe6853Patrik Flykt p->family = sa.sa.sa_family;
631bbe71298ec892f77f44f94feb612646fe6853Patrik Flykt p->ipproto = IPPROTO_UDP;
a34b57c0d43b8bf819ccd4f62c314b41b625454dPatrik Flykt if (p->family == AF_INET) {
a34b57c0d43b8bf819ccd4f62c314b41b625454dPatrik Flykt p->sender.in = sa.in.sin_addr;
a34b57c0d43b8bf819ccd4f62c314b41b625454dPatrik Flykt p->sender_port = be16toh(sa.in.sin_port);
a34b57c0d43b8bf819ccd4f62c314b41b625454dPatrik Flykt } else if (p->family == AF_INET6) {
a34b57c0d43b8bf819ccd4f62c314b41b625454dPatrik Flykt p->sender.in6 = sa.in6.sin6_addr;
ed6ee21953dac9c78383da00bc4514ece6b75ab5Patrik Flykt p->sender_port = be16toh(sa.in6.sin6_port);
a34b57c0d43b8bf819ccd4f62c314b41b625454dPatrik Flykt p->ifindex = sa.in6.sin6_scope_id;
a34b57c0d43b8bf819ccd4f62c314b41b625454dPatrik Flykt } else
ed6ee21953dac9c78383da00bc4514ece6b75ab5Patrik Flykt return -EAFNOSUPPORT;
a34b57c0d43b8bf819ccd4f62c314b41b625454dPatrik Flykt
a34b57c0d43b8bf819ccd4f62c314b41b625454dPatrik Flykt for (cmsg = CMSG_FIRSTHDR(&mh); cmsg; cmsg = CMSG_NXTHDR(&mh, cmsg)) {
a34b57c0d43b8bf819ccd4f62c314b41b625454dPatrik Flykt
a34b57c0d43b8bf819ccd4f62c314b41b625454dPatrik Flykt if (cmsg->cmsg_level == IPPROTO_IPV6) {
a34b57c0d43b8bf819ccd4f62c314b41b625454dPatrik Flykt assert(p->family == AF_INET6);
a34b57c0d43b8bf819ccd4f62c314b41b625454dPatrik Flykt
a34b57c0d43b8bf819ccd4f62c314b41b625454dPatrik Flykt switch (cmsg->cmsg_type) {
a34b57c0d43b8bf819ccd4f62c314b41b625454dPatrik Flykt
a34b57c0d43b8bf819ccd4f62c314b41b625454dPatrik Flykt case IPV6_PKTINFO: {
ed6ee21953dac9c78383da00bc4514ece6b75ab5Patrik Flykt struct in6_pktinfo *i = (struct in6_pktinfo*) CMSG_DATA(cmsg);
ed6ee21953dac9c78383da00bc4514ece6b75ab5Patrik Flykt
ed6ee21953dac9c78383da00bc4514ece6b75ab5Patrik Flykt if (p->ifindex <= 0)
ed6ee21953dac9c78383da00bc4514ece6b75ab5Patrik Flykt p->ifindex = i->ipi6_ifindex;
ed6ee21953dac9c78383da00bc4514ece6b75ab5Patrik Flykt
ed6ee21953dac9c78383da00bc4514ece6b75ab5Patrik Flykt p->destination.in6 = i->ipi6_addr;
ed6ee21953dac9c78383da00bc4514ece6b75ab5Patrik Flykt break;
ed6ee21953dac9c78383da00bc4514ece6b75ab5Patrik Flykt }
ed6ee21953dac9c78383da00bc4514ece6b75ab5Patrik Flykt
bbfa43ca37df0718287c25a8e39ee7477ebf33f6Patrik Flykt case IPV6_HOPLIMIT:
5364f729ba9616cd9fdab8d5413fbc25a1af3a57Lennart Poettering p->ttl = *(int *) CMSG_DATA(cmsg);
bbfa43ca37df0718287c25a8e39ee7477ebf33f6Patrik Flykt break;
bbfa43ca37df0718287c25a8e39ee7477ebf33f6Patrik Flykt
a34b57c0d43b8bf819ccd4f62c314b41b625454dPatrik Flykt }
9d89d1ae71cb298218e35a69d6b70e2c94de5271Patrik Flykt } else if (cmsg->cmsg_level == IPPROTO_IP) {
9d89d1ae71cb298218e35a69d6b70e2c94de5271Patrik Flykt assert(p->family == AF_INET);
a34b57c0d43b8bf819ccd4f62c314b41b625454dPatrik Flykt
a34b57c0d43b8bf819ccd4f62c314b41b625454dPatrik Flykt switch (cmsg->cmsg_type) {
a34b57c0d43b8bf819ccd4f62c314b41b625454dPatrik Flykt
a34b57c0d43b8bf819ccd4f62c314b41b625454dPatrik Flykt case IP_PKTINFO: {
631bbe71298ec892f77f44f94feb612646fe6853Patrik Flykt struct in_pktinfo *i = (struct in_pktinfo*) CMSG_DATA(cmsg);
631bbe71298ec892f77f44f94feb612646fe6853Patrik Flykt
631bbe71298ec892f77f44f94feb612646fe6853Patrik Flykt if (p->ifindex <= 0)
631bbe71298ec892f77f44f94feb612646fe6853Patrik Flykt p->ifindex = i->ipi_ifindex;
631bbe71298ec892f77f44f94feb612646fe6853Patrik Flykt
631bbe71298ec892f77f44f94feb612646fe6853Patrik Flykt p->destination.in = i->ipi_addr;
631bbe71298ec892f77f44f94feb612646fe6853Patrik Flykt break;
ed6ee21953dac9c78383da00bc4514ece6b75ab5Patrik Flykt }
631bbe71298ec892f77f44f94feb612646fe6853Patrik Flykt
631bbe71298ec892f77f44f94feb612646fe6853Patrik Flykt case IP_TTL:
631bbe71298ec892f77f44f94feb612646fe6853Patrik Flykt p->ttl = *(int *) CMSG_DATA(cmsg);
631bbe71298ec892f77f44f94feb612646fe6853Patrik Flykt break;
631bbe71298ec892f77f44f94feb612646fe6853Patrik Flykt }
631bbe71298ec892f77f44f94feb612646fe6853Patrik Flykt }
631bbe71298ec892f77f44f94feb612646fe6853Patrik Flykt }
631bbe71298ec892f77f44f94feb612646fe6853Patrik Flykt
631bbe71298ec892f77f44f94feb612646fe6853Patrik Flykt /* The Linux kernel sets the interface index to the loopback
631bbe71298ec892f77f44f94feb612646fe6853Patrik Flykt * device if the packet came from the local host since it
631bbe71298ec892f77f44f94feb612646fe6853Patrik Flykt * avoids the routing table in such a case. Let's unset the
631bbe71298ec892f77f44f94feb612646fe6853Patrik Flykt * interface index in such a case. */
631bbe71298ec892f77f44f94feb612646fe6853Patrik Flykt if (p->ifindex > 0 && manager_ifindex_is_loopback(m, p->ifindex) != 0)
631bbe71298ec892f77f44f94feb612646fe6853Patrik Flykt p->ifindex = 0;
bbfa43ca37df0718287c25a8e39ee7477ebf33f6Patrik Flykt
bbfa43ca37df0718287c25a8e39ee7477ebf33f6Patrik Flykt /* If we don't know the interface index still, we look for the
631bbe71298ec892f77f44f94feb612646fe6853Patrik Flykt * first local interface with a matching address. Yuck! */
631bbe71298ec892f77f44f94feb612646fe6853Patrik Flykt if (p->ifindex <= 0)
631bbe71298ec892f77f44f94feb612646fe6853Patrik Flykt p->ifindex = manager_find_ifindex(m, p->family, &p->destination);
631bbe71298ec892f77f44f94feb612646fe6853Patrik Flykt
631bbe71298ec892f77f44f94feb612646fe6853Patrik Flykt *ret = p;
631bbe71298ec892f77f44f94feb612646fe6853Patrik Flykt p = NULL;
7246333cb803b03440d3bd0bdaa233564d09b5aePatrik Flykt
7246333cb803b03440d3bd0bdaa233564d09b5aePatrik Flykt return 1;
7246333cb803b03440d3bd0bdaa233564d09b5aePatrik Flykt}
631bbe71298ec892f77f44f94feb612646fe6853Patrik Flykt
631bbe71298ec892f77f44f94feb612646fe6853Patrik Flyktstatic int on_dns_packet(sd_event_source *s, int fd, uint32_t revents, void *userdata) {
631bbe71298ec892f77f44f94feb612646fe6853Patrik Flykt _cleanup_(dns_packet_unrefp) DnsPacket *p = NULL;
a9aff3615b430f86bd0a824214d95f634efaf894Patrik Flykt DnsTransaction *t = NULL;
631bbe71298ec892f77f44f94feb612646fe6853Patrik Flykt Manager *m = userdata;
631bbe71298ec892f77f44f94feb612646fe6853Patrik Flykt int r;
3f0c075f8ef3344da5a6bda524540201f9204e61Patrik Flykt
631bbe71298ec892f77f44f94feb612646fe6853Patrik Flykt r = manager_recv(m, fd, DNS_PROTOCOL_DNS, &p);
631bbe71298ec892f77f44f94feb612646fe6853Patrik Flykt if (r <= 0)
631bbe71298ec892f77f44f94feb612646fe6853Patrik Flykt return r;
631bbe71298ec892f77f44f94feb612646fe6853Patrik Flykt
631bbe71298ec892f77f44f94feb612646fe6853Patrik Flykt if (dns_packet_validate_reply(p) > 0) {
631bbe71298ec892f77f44f94feb612646fe6853Patrik Flykt t = hashmap_get(m->dns_transactions, UINT_TO_PTR(DNS_PACKET_ID(p)));
631bbe71298ec892f77f44f94feb612646fe6853Patrik Flykt if (!t)
631bbe71298ec892f77f44f94feb612646fe6853Patrik Flykt return 0;
631bbe71298ec892f77f44f94feb612646fe6853Patrik Flykt
631bbe71298ec892f77f44f94feb612646fe6853Patrik Flykt dns_transaction_process_reply(t, p);
631bbe71298ec892f77f44f94feb612646fe6853Patrik Flykt
631bbe71298ec892f77f44f94feb612646fe6853Patrik Flykt } else
631bbe71298ec892f77f44f94feb612646fe6853Patrik Flykt log_debug("Invalid DNS packet.");
631bbe71298ec892f77f44f94feb612646fe6853Patrik Flykt
631bbe71298ec892f77f44f94feb612646fe6853Patrik Flykt return 0;
631bbe71298ec892f77f44f94feb612646fe6853Patrik Flykt}
631bbe71298ec892f77f44f94feb612646fe6853Patrik Flykt
6ec60d20724d2a32e20d25ef75d2af178c242bc2Ronny Chevalierint manager_dns_ipv4_fd(Manager *m) {
631bbe71298ec892f77f44f94feb612646fe6853Patrik Flykt const int one = 1;
631bbe71298ec892f77f44f94feb612646fe6853Patrik Flykt int r;
631bbe71298ec892f77f44f94feb612646fe6853Patrik Flykt
631bbe71298ec892f77f44f94feb612646fe6853Patrik Flykt assert(m);
631bbe71298ec892f77f44f94feb612646fe6853Patrik Flykt
631bbe71298ec892f77f44f94feb612646fe6853Patrik Flykt if (m->dns_ipv4_fd >= 0)
631bbe71298ec892f77f44f94feb612646fe6853Patrik Flykt return m->dns_ipv4_fd;
631bbe71298ec892f77f44f94feb612646fe6853Patrik Flykt
631bbe71298ec892f77f44f94feb612646fe6853Patrik Flykt m->dns_ipv4_fd = socket(AF_INET, SOCK_DGRAM|SOCK_CLOEXEC|SOCK_NONBLOCK, 0);
631bbe71298ec892f77f44f94feb612646fe6853Patrik Flykt if (m->dns_ipv4_fd < 0)
631bbe71298ec892f77f44f94feb612646fe6853Patrik Flykt return -errno;
631bbe71298ec892f77f44f94feb612646fe6853Patrik Flykt
631bbe71298ec892f77f44f94feb612646fe6853Patrik Flykt r = setsockopt(m->dns_ipv4_fd, IPPROTO_IP, IP_PKTINFO, &one, sizeof(one));
631bbe71298ec892f77f44f94feb612646fe6853Patrik Flykt if (r < 0) {
631bbe71298ec892f77f44f94feb612646fe6853Patrik Flykt r = -errno;
631bbe71298ec892f77f44f94feb612646fe6853Patrik Flykt goto fail;
631bbe71298ec892f77f44f94feb612646fe6853Patrik Flykt }
631bbe71298ec892f77f44f94feb612646fe6853Patrik Flykt
631bbe71298ec892f77f44f94feb612646fe6853Patrik Flykt r = sd_event_add_io(m->event, &m->dns_ipv4_event_source, m->dns_ipv4_fd, EPOLLIN, on_dns_packet, m);
631bbe71298ec892f77f44f94feb612646fe6853Patrik Flykt if (r < 0)
631bbe71298ec892f77f44f94feb612646fe6853Patrik Flykt goto fail;
631bbe71298ec892f77f44f94feb612646fe6853Patrik Flykt
631bbe71298ec892f77f44f94feb612646fe6853Patrik Flykt return m->dns_ipv4_fd;
631bbe71298ec892f77f44f94feb612646fe6853Patrik Flykt
631bbe71298ec892f77f44f94feb612646fe6853Patrik Flyktfail:
631bbe71298ec892f77f44f94feb612646fe6853Patrik Flykt m->dns_ipv4_fd = safe_close(m->dns_ipv4_fd);
631bbe71298ec892f77f44f94feb612646fe6853Patrik Flykt return r;
631bbe71298ec892f77f44f94feb612646fe6853Patrik Flykt}
631bbe71298ec892f77f44f94feb612646fe6853Patrik Flykt
631bbe71298ec892f77f44f94feb612646fe6853Patrik Flyktint manager_dns_ipv6_fd(Manager *m) {
631bbe71298ec892f77f44f94feb612646fe6853Patrik Flykt const int one = 1;
631bbe71298ec892f77f44f94feb612646fe6853Patrik Flykt int r;
bbfa43ca37df0718287c25a8e39ee7477ebf33f6Patrik Flykt
bbfa43ca37df0718287c25a8e39ee7477ebf33f6Patrik Flykt assert(m);
bbfa43ca37df0718287c25a8e39ee7477ebf33f6Patrik Flykt
bbfa43ca37df0718287c25a8e39ee7477ebf33f6Patrik Flykt if (m->dns_ipv6_fd >= 0)
bbfa43ca37df0718287c25a8e39ee7477ebf33f6Patrik Flykt return m->dns_ipv6_fd;
bbfa43ca37df0718287c25a8e39ee7477ebf33f6Patrik Flykt
bbfa43ca37df0718287c25a8e39ee7477ebf33f6Patrik Flykt m->dns_ipv6_fd = socket(AF_INET6, SOCK_DGRAM|SOCK_CLOEXEC|SOCK_NONBLOCK, 0);
bbfa43ca37df0718287c25a8e39ee7477ebf33f6Patrik Flykt if (m->dns_ipv6_fd < 0)
bbfa43ca37df0718287c25a8e39ee7477ebf33f6Patrik Flykt return -errno;
bbfa43ca37df0718287c25a8e39ee7477ebf33f6Patrik Flykt
bbfa43ca37df0718287c25a8e39ee7477ebf33f6Patrik Flykt r = setsockopt(m->dns_ipv6_fd, IPPROTO_IPV6, IPV6_RECVPKTINFO, &one, sizeof(one));
631bbe71298ec892f77f44f94feb612646fe6853Patrik Flykt if (r < 0) {
631bbe71298ec892f77f44f94feb612646fe6853Patrik Flykt r = -errno;
631bbe71298ec892f77f44f94feb612646fe6853Patrik Flykt goto fail;
ed6ee21953dac9c78383da00bc4514ece6b75ab5Patrik Flykt }
7246333cb803b03440d3bd0bdaa233564d09b5aePatrik Flykt
7246333cb803b03440d3bd0bdaa233564d09b5aePatrik Flykt r = sd_event_add_io(m->event, &m->dns_ipv6_event_source, m->dns_ipv6_fd, EPOLLIN, on_dns_packet, m);
ed6ee21953dac9c78383da00bc4514ece6b75ab5Patrik Flykt if (r < 0)
ed6ee21953dac9c78383da00bc4514ece6b75ab5Patrik Flykt goto fail;
631bbe71298ec892f77f44f94feb612646fe6853Patrik Flykt
ed6ee21953dac9c78383da00bc4514ece6b75ab5Patrik Flykt return m->dns_ipv6_fd;
7246333cb803b03440d3bd0bdaa233564d09b5aePatrik Flykt
3dc34fcc97b41f8b7b019027225b121dfbb9871dPatrik Flyktfail:
3dc34fcc97b41f8b7b019027225b121dfbb9871dPatrik Flykt m->dns_ipv6_fd = safe_close(m->dns_ipv6_fd);
3dc34fcc97b41f8b7b019027225b121dfbb9871dPatrik Flykt return r;
a34b57c0d43b8bf819ccd4f62c314b41b625454dPatrik Flykt}
a34b57c0d43b8bf819ccd4f62c314b41b625454dPatrik Flykt
a34b57c0d43b8bf819ccd4f62c314b41b625454dPatrik Flyktstatic int sendmsg_loop(int fd, struct msghdr *mh, int flags) {
a34b57c0d43b8bf819ccd4f62c314b41b625454dPatrik Flykt int r;
a34b57c0d43b8bf819ccd4f62c314b41b625454dPatrik Flykt
a34b57c0d43b8bf819ccd4f62c314b41b625454dPatrik Flykt assert(fd >= 0);
a34b57c0d43b8bf819ccd4f62c314b41b625454dPatrik Flykt assert(mh);
a34b57c0d43b8bf819ccd4f62c314b41b625454dPatrik Flykt
a34b57c0d43b8bf819ccd4f62c314b41b625454dPatrik Flykt for (;;) {
a34b57c0d43b8bf819ccd4f62c314b41b625454dPatrik Flykt if (sendmsg(fd, mh, flags) >= 0)
a34b57c0d43b8bf819ccd4f62c314b41b625454dPatrik Flykt return 0;
a34b57c0d43b8bf819ccd4f62c314b41b625454dPatrik Flykt
3f0c075f8ef3344da5a6bda524540201f9204e61Patrik Flykt if (errno == EINTR)
a34b57c0d43b8bf819ccd4f62c314b41b625454dPatrik Flykt continue;
a34b57c0d43b8bf819ccd4f62c314b41b625454dPatrik Flykt
a34b57c0d43b8bf819ccd4f62c314b41b625454dPatrik Flykt if (errno != EAGAIN)
a34b57c0d43b8bf819ccd4f62c314b41b625454dPatrik Flykt return -errno;
a34b57c0d43b8bf819ccd4f62c314b41b625454dPatrik Flykt
a34b57c0d43b8bf819ccd4f62c314b41b625454dPatrik Flykt r = fd_wait_for_event(fd, POLLOUT, SEND_TIMEOUT_USEC);
a34b57c0d43b8bf819ccd4f62c314b41b625454dPatrik Flykt if (r < 0)
a34b57c0d43b8bf819ccd4f62c314b41b625454dPatrik Flykt return r;
631bbe71298ec892f77f44f94feb612646fe6853Patrik Flykt if (r == 0)
631bbe71298ec892f77f44f94feb612646fe6853Patrik Flykt return -ETIMEDOUT;
631bbe71298ec892f77f44f94feb612646fe6853Patrik Flykt }
631bbe71298ec892f77f44f94feb612646fe6853Patrik Flykt}
631bbe71298ec892f77f44f94feb612646fe6853Patrik Flykt
631bbe71298ec892f77f44f94feb612646fe6853Patrik Flyktstatic int manager_ipv4_send(Manager *m, int fd, int ifindex, const struct in_addr *addr, uint16_t port, DnsPacket *p) {
631bbe71298ec892f77f44f94feb612646fe6853Patrik Flykt union sockaddr_union sa = {
631bbe71298ec892f77f44f94feb612646fe6853Patrik Flykt .in.sin_family = AF_INET,
631bbe71298ec892f77f44f94feb612646fe6853Patrik Flykt };
a9aff3615b430f86bd0a824214d95f634efaf894Patrik Flykt union {
a9aff3615b430f86bd0a824214d95f634efaf894Patrik Flykt struct cmsghdr header; /* For alignment */
a9aff3615b430f86bd0a824214d95f634efaf894Patrik Flykt uint8_t buffer[CMSG_SPACE(sizeof(struct in_pktinfo))];
c3e2adeaba8e043caed0ef139eeaea016bd152d0Patrik Flykt } control;
f12abb48fc510b8b349c05e35ba048134debaf25Patrik Flykt struct msghdr mh = {};
f12abb48fc510b8b349c05e35ba048134debaf25Patrik Flykt struct iovec iov;
a34b57c0d43b8bf819ccd4f62c314b41b625454dPatrik Flykt
a34b57c0d43b8bf819ccd4f62c314b41b625454dPatrik Flykt assert(m);
f12abb48fc510b8b349c05e35ba048134debaf25Patrik Flykt assert(fd >= 0);
f12abb48fc510b8b349c05e35ba048134debaf25Patrik Flykt assert(addr);
f12abb48fc510b8b349c05e35ba048134debaf25Patrik Flykt assert(port > 0);
f12abb48fc510b8b349c05e35ba048134debaf25Patrik Flykt assert(p);
c3e2adeaba8e043caed0ef139eeaea016bd152d0Patrik Flykt
f12abb48fc510b8b349c05e35ba048134debaf25Patrik Flykt iov.iov_base = DNS_PACKET_DATA(p);
c3e2adeaba8e043caed0ef139eeaea016bd152d0Patrik Flykt iov.iov_len = p->size;
c3e2adeaba8e043caed0ef139eeaea016bd152d0Patrik Flykt
c3e2adeaba8e043caed0ef139eeaea016bd152d0Patrik Flykt sa.in.sin_addr = *addr;
c3e2adeaba8e043caed0ef139eeaea016bd152d0Patrik Flykt sa.in.sin_port = htobe16(port),
c3e2adeaba8e043caed0ef139eeaea016bd152d0Patrik Flykt
f12abb48fc510b8b349c05e35ba048134debaf25Patrik Flykt mh.msg_iov = &iov;
38a03f06a7393d2721c23f23f0589d2f6d0904afLennart Poettering mh.msg_iovlen = 1;
38a03f06a7393d2721c23f23f0589d2f6d0904afLennart Poettering mh.msg_name = &sa.sa;
38a03f06a7393d2721c23f23f0589d2f6d0904afLennart Poettering mh.msg_namelen = sizeof(sa.in);
346e13a25dc6f76d3bc9d8decd40dc4782b02d2aPatrik Flykt
c3e2adeaba8e043caed0ef139eeaea016bd152d0Patrik Flykt if (ifindex > 0) {
c3e2adeaba8e043caed0ef139eeaea016bd152d0Patrik Flykt struct cmsghdr *cmsg;
bbfa43ca37df0718287c25a8e39ee7477ebf33f6Patrik Flykt struct in_pktinfo *pi;
bbfa43ca37df0718287c25a8e39ee7477ebf33f6Patrik Flykt
a9aff3615b430f86bd0a824214d95f634efaf894Patrik Flykt zero(control);
bbfa43ca37df0718287c25a8e39ee7477ebf33f6Patrik Flykt
bbfa43ca37df0718287c25a8e39ee7477ebf33f6Patrik Flykt mh.msg_control = &control;
9021bb9f935c93b516b10c88db2a212a9e3a8140Tom Gundersen mh.msg_controllen = CMSG_LEN(sizeof(struct in_pktinfo));
bbfa43ca37df0718287c25a8e39ee7477ebf33f6Patrik Flykt
bbfa43ca37df0718287c25a8e39ee7477ebf33f6Patrik Flykt cmsg = CMSG_FIRSTHDR(&mh);
c3e2adeaba8e043caed0ef139eeaea016bd152d0Patrik Flykt cmsg->cmsg_len = mh.msg_controllen;
c3e2adeaba8e043caed0ef139eeaea016bd152d0Patrik Flykt cmsg->cmsg_level = IPPROTO_IP;
7246333cb803b03440d3bd0bdaa233564d09b5aePatrik Flykt cmsg->cmsg_type = IP_PKTINFO;
7246333cb803b03440d3bd0bdaa233564d09b5aePatrik Flykt
bbfa43ca37df0718287c25a8e39ee7477ebf33f6Patrik Flykt pi = (struct in_pktinfo*) CMSG_DATA(cmsg);
7246333cb803b03440d3bd0bdaa233564d09b5aePatrik Flykt pi->ipi_ifindex = ifindex;
3dc34fcc97b41f8b7b019027225b121dfbb9871dPatrik Flykt }
3dc34fcc97b41f8b7b019027225b121dfbb9871dPatrik Flykt
a34b57c0d43b8bf819ccd4f62c314b41b625454dPatrik Flykt return sendmsg_loop(fd, &mh, 0);
7246333cb803b03440d3bd0bdaa233564d09b5aePatrik Flykt}
7246333cb803b03440d3bd0bdaa233564d09b5aePatrik Flykt
c3e2adeaba8e043caed0ef139eeaea016bd152d0Patrik Flyktstatic int manager_ipv6_send(Manager *m, int fd, int ifindex, const struct in6_addr *addr, uint16_t port, DnsPacket *p) {
a34b57c0d43b8bf819ccd4f62c314b41b625454dPatrik Flykt union sockaddr_union sa = {
a34b57c0d43b8bf819ccd4f62c314b41b625454dPatrik Flykt .in6.sin6_family = AF_INET6,
a34b57c0d43b8bf819ccd4f62c314b41b625454dPatrik Flykt };
a34b57c0d43b8bf819ccd4f62c314b41b625454dPatrik Flykt union {
a34b57c0d43b8bf819ccd4f62c314b41b625454dPatrik Flykt struct cmsghdr header; /* For alignment */
a34b57c0d43b8bf819ccd4f62c314b41b625454dPatrik Flykt uint8_t buffer[CMSG_SPACE(sizeof(struct in6_pktinfo))];
a34b57c0d43b8bf819ccd4f62c314b41b625454dPatrik Flykt } control;
a34b57c0d43b8bf819ccd4f62c314b41b625454dPatrik Flykt struct msghdr mh = {};
a34b57c0d43b8bf819ccd4f62c314b41b625454dPatrik Flykt struct iovec iov;
a34b57c0d43b8bf819ccd4f62c314b41b625454dPatrik Flykt
a34b57c0d43b8bf819ccd4f62c314b41b625454dPatrik Flykt assert(m);
a34b57c0d43b8bf819ccd4f62c314b41b625454dPatrik Flykt assert(fd >= 0);
a34b57c0d43b8bf819ccd4f62c314b41b625454dPatrik Flykt assert(addr);
a34b57c0d43b8bf819ccd4f62c314b41b625454dPatrik Flykt assert(port > 0);
a34b57c0d43b8bf819ccd4f62c314b41b625454dPatrik Flykt assert(p);
a34b57c0d43b8bf819ccd4f62c314b41b625454dPatrik Flykt
a34b57c0d43b8bf819ccd4f62c314b41b625454dPatrik Flykt iov.iov_base = DNS_PACKET_DATA(p);
a34b57c0d43b8bf819ccd4f62c314b41b625454dPatrik Flykt iov.iov_len = p->size;
a34b57c0d43b8bf819ccd4f62c314b41b625454dPatrik Flykt
a34b57c0d43b8bf819ccd4f62c314b41b625454dPatrik Flykt sa.in6.sin6_addr = *addr;
a34b57c0d43b8bf819ccd4f62c314b41b625454dPatrik Flykt sa.in6.sin6_port = htobe16(port),
a34b57c0d43b8bf819ccd4f62c314b41b625454dPatrik Flykt sa.in6.sin6_scope_id = ifindex;
fa94c34b083b5b4019975624453e53d0cbad2a5dTom Gundersen
a34b57c0d43b8bf819ccd4f62c314b41b625454dPatrik Flykt mh.msg_iov = &iov;
a34b57c0d43b8bf819ccd4f62c314b41b625454dPatrik Flykt mh.msg_iovlen = 1;
a34b57c0d43b8bf819ccd4f62c314b41b625454dPatrik Flykt mh.msg_name = &sa.sa;
a34b57c0d43b8bf819ccd4f62c314b41b625454dPatrik Flykt mh.msg_namelen = sizeof(sa.in6);
a34b57c0d43b8bf819ccd4f62c314b41b625454dPatrik Flykt
a34b57c0d43b8bf819ccd4f62c314b41b625454dPatrik Flykt if (ifindex > 0) {
a34b57c0d43b8bf819ccd4f62c314b41b625454dPatrik Flykt struct cmsghdr *cmsg;
a34b57c0d43b8bf819ccd4f62c314b41b625454dPatrik Flykt struct in6_pktinfo *pi;
a34b57c0d43b8bf819ccd4f62c314b41b625454dPatrik Flykt
a34b57c0d43b8bf819ccd4f62c314b41b625454dPatrik Flykt zero(control);
356779df90a2ecab5da2cb310ad0f8ebc9ca9f46Lennart Poettering
9021bb9f935c93b516b10c88db2a212a9e3a8140Tom Gundersen mh.msg_control = &control;
9021bb9f935c93b516b10c88db2a212a9e3a8140Tom Gundersen mh.msg_controllen = CMSG_LEN(sizeof(struct in6_pktinfo));
9021bb9f935c93b516b10c88db2a212a9e3a8140Tom Gundersen
a34b57c0d43b8bf819ccd4f62c314b41b625454dPatrik Flykt cmsg = CMSG_FIRSTHDR(&mh);
a34b57c0d43b8bf819ccd4f62c314b41b625454dPatrik Flykt cmsg->cmsg_len = mh.msg_controllen;
a34b57c0d43b8bf819ccd4f62c314b41b625454dPatrik Flykt cmsg->cmsg_level = IPPROTO_IPV6;
a34b57c0d43b8bf819ccd4f62c314b41b625454dPatrik Flykt cmsg->cmsg_type = IPV6_PKTINFO;
a34b57c0d43b8bf819ccd4f62c314b41b625454dPatrik Flykt
a34b57c0d43b8bf819ccd4f62c314b41b625454dPatrik Flykt pi = (struct in6_pktinfo*) CMSG_DATA(cmsg);
a34b57c0d43b8bf819ccd4f62c314b41b625454dPatrik Flykt pi->ipi6_ifindex = ifindex;
a34b57c0d43b8bf819ccd4f62c314b41b625454dPatrik Flykt }
a34b57c0d43b8bf819ccd4f62c314b41b625454dPatrik Flykt
fa94c34b083b5b4019975624453e53d0cbad2a5dTom Gundersen return sendmsg_loop(fd, &mh, 0);
a34b57c0d43b8bf819ccd4f62c314b41b625454dPatrik Flykt}
a34b57c0d43b8bf819ccd4f62c314b41b625454dPatrik Flykt
a34b57c0d43b8bf819ccd4f62c314b41b625454dPatrik Flyktint manager_send(Manager *m, int fd, int ifindex, int family, const union in_addr_union *addr, uint16_t port, DnsPacket *p) {
a34b57c0d43b8bf819ccd4f62c314b41b625454dPatrik Flykt assert(m);
a34b57c0d43b8bf819ccd4f62c314b41b625454dPatrik Flykt assert(fd >= 0);
a34b57c0d43b8bf819ccd4f62c314b41b625454dPatrik Flykt assert(addr);
a34b57c0d43b8bf819ccd4f62c314b41b625454dPatrik Flykt assert(port > 0);
a34b57c0d43b8bf819ccd4f62c314b41b625454dPatrik Flykt assert(p);
a34b57c0d43b8bf819ccd4f62c314b41b625454dPatrik Flykt
a34b57c0d43b8bf819ccd4f62c314b41b625454dPatrik Flykt 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));
356779df90a2ecab5da2cb310ad0f8ebc9ca9f46Lennart Poettering
9021bb9f935c93b516b10c88db2a212a9e3a8140Tom Gundersen if (family == AF_INET)
9021bb9f935c93b516b10c88db2a212a9e3a8140Tom Gundersen return manager_ipv4_send(m, fd, ifindex, &addr->in, port, p);
9021bb9f935c93b516b10c88db2a212a9e3a8140Tom Gundersen else if (family == AF_INET6)
3dc34fcc97b41f8b7b019027225b121dfbb9871dPatrik Flykt return manager_ipv6_send(m, fd, ifindex, &addr->in6, port, p);
3dc34fcc97b41f8b7b019027225b121dfbb9871dPatrik Flykt
a34b57c0d43b8bf819ccd4f62c314b41b625454dPatrik Flykt return -EAFNOSUPPORT;
c3e2adeaba8e043caed0ef139eeaea016bd152d0Patrik Flykt}
a9aff3615b430f86bd0a824214d95f634efaf894Patrik Flykt
c3e2adeaba8e043caed0ef139eeaea016bd152d0Patrik FlyktDnsServer* manager_find_dns_server(Manager *m, int family, const union in_addr_union *in_addr) {
346e13a25dc6f76d3bc9d8decd40dc4782b02d2aPatrik Flykt DnsServer *s;
d1b0afe3653b4316a6361d204169620726d468a0Patrik Flykt
d1b0afe3653b4316a6361d204169620726d468a0Patrik Flykt assert(m);
fa94c34b083b5b4019975624453e53d0cbad2a5dTom Gundersen assert(in_addr);
d1b0afe3653b4316a6361d204169620726d468a0Patrik Flykt
d1b0afe3653b4316a6361d204169620726d468a0Patrik Flykt LIST_FOREACH(servers, s, m->dns_servers)
d1b0afe3653b4316a6361d204169620726d468a0Patrik Flykt if (s->family == family && in_addr_equal(family, &s->address, in_addr) > 0)
d1b0afe3653b4316a6361d204169620726d468a0Patrik Flykt return s;
d1b0afe3653b4316a6361d204169620726d468a0Patrik Flykt
d1b0afe3653b4316a6361d204169620726d468a0Patrik Flykt LIST_FOREACH(servers, s, m->fallback_dns_servers)
d1b0afe3653b4316a6361d204169620726d468a0Patrik Flykt if (s->family == family && in_addr_equal(family, &s->address, in_addr) > 0)
d1b0afe3653b4316a6361d204169620726d468a0Patrik Flykt return s;
d1b0afe3653b4316a6361d204169620726d468a0Patrik Flykt
356779df90a2ecab5da2cb310ad0f8ebc9ca9f46Lennart Poettering return NULL;
9021bb9f935c93b516b10c88db2a212a9e3a8140Tom Gundersen}
9021bb9f935c93b516b10c88db2a212a9e3a8140Tom Gundersen
9021bb9f935c93b516b10c88db2a212a9e3a8140Tom GundersenDnsServer *manager_set_dns_server(Manager *m, DnsServer *s) {
f12abb48fc510b8b349c05e35ba048134debaf25Patrik Flykt assert(m);
f12abb48fc510b8b349c05e35ba048134debaf25Patrik Flykt
f12abb48fc510b8b349c05e35ba048134debaf25Patrik Flykt if (m->current_dns_server == s)
139b011ab81ccea1d51f09e0261a1c390115c6ffPatrik Flykt return s;
139b011ab81ccea1d51f09e0261a1c390115c6ffPatrik Flykt
139b011ab81ccea1d51f09e0261a1c390115c6ffPatrik Flykt if (s) {
139b011ab81ccea1d51f09e0261a1c390115c6ffPatrik Flykt _cleanup_free_ char *ip = NULL;
139b011ab81ccea1d51f09e0261a1c390115c6ffPatrik Flykt
139b011ab81ccea1d51f09e0261a1c390115c6ffPatrik Flykt in_addr_to_string(s->family, &s->address, &ip);
139b011ab81ccea1d51f09e0261a1c390115c6ffPatrik Flykt log_info("Switching to system DNS server %s.", strna(ip));
139b011ab81ccea1d51f09e0261a1c390115c6ffPatrik Flykt }
139b011ab81ccea1d51f09e0261a1c390115c6ffPatrik Flykt
139b011ab81ccea1d51f09e0261a1c390115c6ffPatrik Flykt m->current_dns_server = s;
bbfa43ca37df0718287c25a8e39ee7477ebf33f6Patrik Flykt
139b011ab81ccea1d51f09e0261a1c390115c6ffPatrik Flykt if (m->unicast_scope)
139b011ab81ccea1d51f09e0261a1c390115c6ffPatrik Flykt dns_cache_flush(&m->unicast_scope->cache);
139b011ab81ccea1d51f09e0261a1c390115c6ffPatrik Flykt
139b011ab81ccea1d51f09e0261a1c390115c6ffPatrik Flykt return s;
139b011ab81ccea1d51f09e0261a1c390115c6ffPatrik Flykt}
c806ffb9592fa9a2b13a1f9f9be4c77cd5b211aaZbigniew Jędrzejewski-Szmek
f12abb48fc510b8b349c05e35ba048134debaf25Patrik FlyktDnsServer *manager_get_dns_server(Manager *m) {
f12abb48fc510b8b349c05e35ba048134debaf25Patrik Flykt Link *l;
f12abb48fc510b8b349c05e35ba048134debaf25Patrik Flykt assert(m);
bbfa43ca37df0718287c25a8e39ee7477ebf33f6Patrik Flykt
bbfa43ca37df0718287c25a8e39ee7477ebf33f6Patrik Flykt /* Try to read updates resolv.conf */
bbfa43ca37df0718287c25a8e39ee7477ebf33f6Patrik Flykt manager_read_resolv_conf(m);
bbfa43ca37df0718287c25a8e39ee7477ebf33f6Patrik Flykt
cc22955cfefb4bd6e7a135f1ec95fb5a07ba9ce3Thomas Haller if (!m->current_dns_server)
cc22955cfefb4bd6e7a135f1ec95fb5a07ba9ce3Thomas Haller manager_set_dns_server(m, m->dns_servers);
cc22955cfefb4bd6e7a135f1ec95fb5a07ba9ce3Thomas Haller
cc22955cfefb4bd6e7a135f1ec95fb5a07ba9ce3Thomas Haller if (!m->current_dns_server) {
bbfa43ca37df0718287c25a8e39ee7477ebf33f6Patrik Flykt bool found = false;
bbfa43ca37df0718287c25a8e39ee7477ebf33f6Patrik Flykt Iterator i;
bbfa43ca37df0718287c25a8e39ee7477ebf33f6Patrik Flykt
bbfa43ca37df0718287c25a8e39ee7477ebf33f6Patrik Flykt /* No DNS servers configured, let's see if there are
bbfa43ca37df0718287c25a8e39ee7477ebf33f6Patrik Flykt * any on any links. If not, we use the fallback
bbfa43ca37df0718287c25a8e39ee7477ebf33f6Patrik Flykt * servers */
bbfa43ca37df0718287c25a8e39ee7477ebf33f6Patrik Flykt
bbfa43ca37df0718287c25a8e39ee7477ebf33f6Patrik Flykt HASHMAP_FOREACH(l, m->links, i)
bbfa43ca37df0718287c25a8e39ee7477ebf33f6Patrik Flykt if (l->dns_servers) {
bbfa43ca37df0718287c25a8e39ee7477ebf33f6Patrik Flykt found = true;
bbfa43ca37df0718287c25a8e39ee7477ebf33f6Patrik Flykt break;
bbfa43ca37df0718287c25a8e39ee7477ebf33f6Patrik Flykt }
bbfa43ca37df0718287c25a8e39ee7477ebf33f6Patrik Flykt
bbfa43ca37df0718287c25a8e39ee7477ebf33f6Patrik Flykt if (!found)
bbfa43ca37df0718287c25a8e39ee7477ebf33f6Patrik Flykt manager_set_dns_server(m, m->fallback_dns_servers);
bbfa43ca37df0718287c25a8e39ee7477ebf33f6Patrik Flykt }
bbfa43ca37df0718287c25a8e39ee7477ebf33f6Patrik Flykt
bbfa43ca37df0718287c25a8e39ee7477ebf33f6Patrik Flykt return m->current_dns_server;
bbfa43ca37df0718287c25a8e39ee7477ebf33f6Patrik Flykt}
bbfa43ca37df0718287c25a8e39ee7477ebf33f6Patrik Flykt
bbfa43ca37df0718287c25a8e39ee7477ebf33f6Patrik Flyktvoid manager_next_dns_server(Manager *m) {
bbfa43ca37df0718287c25a8e39ee7477ebf33f6Patrik Flykt assert(m);
bbfa43ca37df0718287c25a8e39ee7477ebf33f6Patrik Flykt
bbfa43ca37df0718287c25a8e39ee7477ebf33f6Patrik Flykt /* If there's currently no DNS server set, then the next
bbfa43ca37df0718287c25a8e39ee7477ebf33f6Patrik Flykt * manager_get_dns_server() will find one */
bbfa43ca37df0718287c25a8e39ee7477ebf33f6Patrik Flykt if (!m->current_dns_server)
bbfa43ca37df0718287c25a8e39ee7477ebf33f6Patrik Flykt return;
bbfa43ca37df0718287c25a8e39ee7477ebf33f6Patrik Flykt
bbfa43ca37df0718287c25a8e39ee7477ebf33f6Patrik Flykt /* Change to the next one */
bbfa43ca37df0718287c25a8e39ee7477ebf33f6Patrik Flykt if (m->current_dns_server->servers_next) {
bbfa43ca37df0718287c25a8e39ee7477ebf33f6Patrik Flykt manager_set_dns_server(m, m->current_dns_server->servers_next);
bbfa43ca37df0718287c25a8e39ee7477ebf33f6Patrik Flykt return;
bbfa43ca37df0718287c25a8e39ee7477ebf33f6Patrik Flykt }
bbfa43ca37df0718287c25a8e39ee7477ebf33f6Patrik Flykt
139b011ab81ccea1d51f09e0261a1c390115c6ffPatrik Flykt /* If there was no next one, then start from the beginning of
139b011ab81ccea1d51f09e0261a1c390115c6ffPatrik Flykt * the list */
139b011ab81ccea1d51f09e0261a1c390115c6ffPatrik Flykt if (m->current_dns_server->type == DNS_SERVER_FALLBACK)
139b011ab81ccea1d51f09e0261a1c390115c6ffPatrik Flykt manager_set_dns_server(m, m->fallback_dns_servers);
139b011ab81ccea1d51f09e0261a1c390115c6ffPatrik Flykt else
139b011ab81ccea1d51f09e0261a1c390115c6ffPatrik Flykt manager_set_dns_server(m, m->dns_servers);
139b011ab81ccea1d51f09e0261a1c390115c6ffPatrik Flykt}
139b011ab81ccea1d51f09e0261a1c390115c6ffPatrik Flykt
139b011ab81ccea1d51f09e0261a1c390115c6ffPatrik Flyktuint32_t manager_find_mtu(Manager *m) {
139b011ab81ccea1d51f09e0261a1c390115c6ffPatrik Flykt uint32_t mtu = 0;
139b011ab81ccea1d51f09e0261a1c390115c6ffPatrik Flykt Link *l;
139b011ab81ccea1d51f09e0261a1c390115c6ffPatrik Flykt Iterator i;
139b011ab81ccea1d51f09e0261a1c390115c6ffPatrik Flykt
139b011ab81ccea1d51f09e0261a1c390115c6ffPatrik Flykt /* If we don't know on which link a DNS packet would be
139b011ab81ccea1d51f09e0261a1c390115c6ffPatrik Flykt * delivered, let's find the largest MTU that works on all
139b011ab81ccea1d51f09e0261a1c390115c6ffPatrik Flykt * interfaces we know of */
139b011ab81ccea1d51f09e0261a1c390115c6ffPatrik Flykt
139b011ab81ccea1d51f09e0261a1c390115c6ffPatrik Flykt HASHMAP_FOREACH(l, m->links, i) {
139b011ab81ccea1d51f09e0261a1c390115c6ffPatrik Flykt if (l->mtu <= 0)
139b011ab81ccea1d51f09e0261a1c390115c6ffPatrik Flykt continue;
139b011ab81ccea1d51f09e0261a1c390115c6ffPatrik Flykt
139b011ab81ccea1d51f09e0261a1c390115c6ffPatrik Flykt if (mtu <= 0 || l->mtu < mtu)
139b011ab81ccea1d51f09e0261a1c390115c6ffPatrik Flykt mtu = l->mtu;
139b011ab81ccea1d51f09e0261a1c390115c6ffPatrik Flykt }
139b011ab81ccea1d51f09e0261a1c390115c6ffPatrik Flykt
139b011ab81ccea1d51f09e0261a1c390115c6ffPatrik Flykt return mtu;
139b011ab81ccea1d51f09e0261a1c390115c6ffPatrik Flykt}
139b011ab81ccea1d51f09e0261a1c390115c6ffPatrik Flykt
139b011ab81ccea1d51f09e0261a1c390115c6ffPatrik Flyktstatic int on_llmnr_packet(sd_event_source *s, int fd, uint32_t revents, void *userdata) {
139b011ab81ccea1d51f09e0261a1c390115c6ffPatrik Flykt _cleanup_(dns_packet_unrefp) DnsPacket *p = NULL;
139b011ab81ccea1d51f09e0261a1c390115c6ffPatrik Flykt DnsTransaction *t = NULL;
139b011ab81ccea1d51f09e0261a1c390115c6ffPatrik Flykt Manager *m = userdata;
139b011ab81ccea1d51f09e0261a1c390115c6ffPatrik Flykt int r;
139b011ab81ccea1d51f09e0261a1c390115c6ffPatrik Flykt
139b011ab81ccea1d51f09e0261a1c390115c6ffPatrik Flykt r = manager_recv(m, fd, DNS_PROTOCOL_LLMNR, &p);
139b011ab81ccea1d51f09e0261a1c390115c6ffPatrik Flykt if (r <= 0)
139b011ab81ccea1d51f09e0261a1c390115c6ffPatrik Flykt return r;
139b011ab81ccea1d51f09e0261a1c390115c6ffPatrik Flykt
139b011ab81ccea1d51f09e0261a1c390115c6ffPatrik Flykt if (dns_packet_validate_reply(p) > 0) {
139b011ab81ccea1d51f09e0261a1c390115c6ffPatrik Flykt log_debug("Got reply packet for id %u", DNS_PACKET_ID(p));
139b011ab81ccea1d51f09e0261a1c390115c6ffPatrik Flykt
139b011ab81ccea1d51f09e0261a1c390115c6ffPatrik Flykt t = hashmap_get(m->dns_transactions, UINT_TO_PTR(DNS_PACKET_ID(p)));
139b011ab81ccea1d51f09e0261a1c390115c6ffPatrik Flykt if (!t)
139b011ab81ccea1d51f09e0261a1c390115c6ffPatrik Flykt return 0;
139b011ab81ccea1d51f09e0261a1c390115c6ffPatrik Flykt
139b011ab81ccea1d51f09e0261a1c390115c6ffPatrik Flykt dns_transaction_process_reply(t, p);
f0c4b1c3fd827b429ba36aa45fd39e0a023cbf2cTom Gundersen
c806ffb9592fa9a2b13a1f9f9be4c77cd5b211aaZbigniew Jędrzejewski-Szmek } else if (dns_packet_validate_query(p) > 0) {
139b011ab81ccea1d51f09e0261a1c390115c6ffPatrik Flykt Link *l;
139b011ab81ccea1d51f09e0261a1c390115c6ffPatrik Flykt
62e3d1aed512d68cab1fc9b509e813a1fa2b3790Lennart Poettering l = hashmap_get(m->links, INT_TO_PTR(p->ifindex));
139b011ab81ccea1d51f09e0261a1c390115c6ffPatrik Flykt if (l) {
da6fe470e17fa02f3adedc779585caf8669252bdPatrik Flykt DnsScope *scope = NULL;
139b011ab81ccea1d51f09e0261a1c390115c6ffPatrik Flykt
139b011ab81ccea1d51f09e0261a1c390115c6ffPatrik Flykt if (p->family == AF_INET)
139b011ab81ccea1d51f09e0261a1c390115c6ffPatrik Flykt scope = l->llmnr_ipv4_scope;
139b011ab81ccea1d51f09e0261a1c390115c6ffPatrik Flykt else if (p->family == AF_INET6)
139b011ab81ccea1d51f09e0261a1c390115c6ffPatrik Flykt scope = l->llmnr_ipv6_scope;
139b011ab81ccea1d51f09e0261a1c390115c6ffPatrik Flykt
139b011ab81ccea1d51f09e0261a1c390115c6ffPatrik Flykt if (scope)
139b011ab81ccea1d51f09e0261a1c390115c6ffPatrik Flykt dns_scope_process_query(scope, NULL, p);
139b011ab81ccea1d51f09e0261a1c390115c6ffPatrik Flykt }
139b011ab81ccea1d51f09e0261a1c390115c6ffPatrik Flykt } else
3f0c075f8ef3344da5a6bda524540201f9204e61Patrik Flykt log_debug("Invalid LLMNR packet.");
da6fe470e17fa02f3adedc779585caf8669252bdPatrik Flykt
139b011ab81ccea1d51f09e0261a1c390115c6ffPatrik Flykt return 0;
139b011ab81ccea1d51f09e0261a1c390115c6ffPatrik Flykt}
139b011ab81ccea1d51f09e0261a1c390115c6ffPatrik Flykt
139b011ab81ccea1d51f09e0261a1c390115c6ffPatrik Flyktint manager_llmnr_ipv4_udp_fd(Manager *m) {
139b011ab81ccea1d51f09e0261a1c390115c6ffPatrik Flykt union sockaddr_union sa = {
139b011ab81ccea1d51f09e0261a1c390115c6ffPatrik Flykt .in.sin_family = AF_INET,
139b011ab81ccea1d51f09e0261a1c390115c6ffPatrik Flykt .in.sin_port = htobe16(5355),
139b011ab81ccea1d51f09e0261a1c390115c6ffPatrik Flykt };
139b011ab81ccea1d51f09e0261a1c390115c6ffPatrik Flykt static const int one = 1, pmtu = IP_PMTUDISC_DONT, ttl = 255;
f12abb48fc510b8b349c05e35ba048134debaf25Patrik Flykt int r;
f12abb48fc510b8b349c05e35ba048134debaf25Patrik Flykt
139b011ab81ccea1d51f09e0261a1c390115c6ffPatrik Flykt assert(m);
139b011ab81ccea1d51f09e0261a1c390115c6ffPatrik Flykt
c806ffb9592fa9a2b13a1f9f9be4c77cd5b211aaZbigniew Jędrzejewski-Szmek if (m->llmnr_ipv4_udp_fd >= 0)
c806ffb9592fa9a2b13a1f9f9be4c77cd5b211aaZbigniew Jędrzejewski-Szmek return m->llmnr_ipv4_udp_fd;
da6fe470e17fa02f3adedc779585caf8669252bdPatrik Flykt
da6fe470e17fa02f3adedc779585caf8669252bdPatrik Flykt m->llmnr_ipv4_udp_fd = socket(AF_INET, SOCK_DGRAM|SOCK_CLOEXEC|SOCK_NONBLOCK, 0);
da6fe470e17fa02f3adedc779585caf8669252bdPatrik Flykt if (m->llmnr_ipv4_udp_fd < 0)
da6fe470e17fa02f3adedc779585caf8669252bdPatrik Flykt return -errno;
da6fe470e17fa02f3adedc779585caf8669252bdPatrik Flykt
da6fe470e17fa02f3adedc779585caf8669252bdPatrik Flykt /* RFC 4795, section 2.5 recommends setting the TTL of UDP packets to 255. */
da6fe470e17fa02f3adedc779585caf8669252bdPatrik Flykt r = setsockopt(m->llmnr_ipv4_udp_fd, IPPROTO_IP, IP_TTL, &ttl, sizeof(ttl));
da6fe470e17fa02f3adedc779585caf8669252bdPatrik Flykt if (r < 0) {
da6fe470e17fa02f3adedc779585caf8669252bdPatrik Flykt r = -errno;
139b011ab81ccea1d51f09e0261a1c390115c6ffPatrik Flykt goto fail;
139b011ab81ccea1d51f09e0261a1c390115c6ffPatrik Flykt }
139b011ab81ccea1d51f09e0261a1c390115c6ffPatrik Flykt
139b011ab81ccea1d51f09e0261a1c390115c6ffPatrik Flykt r = setsockopt(m->llmnr_ipv4_udp_fd, IPPROTO_IP, IP_MULTICAST_TTL, &ttl, sizeof(ttl));
139b011ab81ccea1d51f09e0261a1c390115c6ffPatrik Flykt if (r < 0) {
r = -errno;
goto fail;
}
r = setsockopt(m->llmnr_ipv4_udp_fd, IPPROTO_IP, IP_MULTICAST_LOOP, &one, sizeof(one));
if (r < 0) {
r = -errno;
goto fail;
}
r = setsockopt(m->llmnr_ipv4_udp_fd, SOL_SOCKET, SO_REUSEADDR, &one, sizeof(one));
if (r < 0) {
r = -errno;
goto fail;
}
r = setsockopt(m->llmnr_ipv4_udp_fd, IPPROTO_IP, IP_PKTINFO, &one, sizeof(one));
if (r < 0) {
r = -errno;
goto fail;
}
r = setsockopt(m->llmnr_ipv4_udp_fd, IPPROTO_IP, IP_RECVTTL, &one, sizeof(one));
if (r < 0) {
r = -errno;
goto fail;
}
/* Disable Don't-Fragment bit in the IP header */
r = setsockopt(m->llmnr_ipv4_udp_fd, IPPROTO_IP, IP_MTU_DISCOVER, &pmtu, sizeof(pmtu));
if (r < 0) {
r = -errno;
goto fail;
}
r = bind(m->llmnr_ipv4_udp_fd, &sa.sa, sizeof(sa.in));
if (r < 0) {
r = -errno;
goto fail;
}
r = sd_event_add_io(m->event, &m->llmnr_ipv4_udp_event_source, m->llmnr_ipv4_udp_fd, EPOLLIN, on_llmnr_packet, m);
if (r < 0)
goto fail;
return m->llmnr_ipv4_udp_fd;
fail:
m->llmnr_ipv4_udp_fd = safe_close(m->llmnr_ipv4_udp_fd);
return r;
}
int manager_llmnr_ipv6_udp_fd(Manager *m) {
union sockaddr_union sa = {
.in6.sin6_family = AF_INET6,
.in6.sin6_port = htobe16(5355),
};
static const int one = 1, ttl = 255;
int r;
assert(m);
if (m->llmnr_ipv6_udp_fd >= 0)
return m->llmnr_ipv6_udp_fd;
m->llmnr_ipv6_udp_fd = socket(AF_INET6, SOCK_DGRAM|SOCK_CLOEXEC|SOCK_NONBLOCK, 0);
if (m->llmnr_ipv6_udp_fd < 0)
return -errno;
r = setsockopt(m->llmnr_ipv6_udp_fd, IPPROTO_IPV6, IPV6_UNICAST_HOPS, &ttl, sizeof(ttl));
if (r < 0) {
r = -errno;
goto fail;
}
/* RFC 4795, section 2.5 recommends setting the TTL of UDP packets to 255. */
r = setsockopt(m->llmnr_ipv6_udp_fd, IPPROTO_IPV6, IPV6_MULTICAST_HOPS, &ttl, sizeof(ttl));
if (r < 0) {
r = -errno;
goto fail;
}
r = setsockopt(m->llmnr_ipv6_udp_fd, IPPROTO_IPV6, IPV6_MULTICAST_LOOP, &one, sizeof(one));
if (r < 0) {
r = -errno;
goto fail;
}
r = setsockopt(m->llmnr_ipv6_udp_fd, IPPROTO_IPV6, IPV6_V6ONLY, &one, sizeof(one));
if (r < 0) {
r = -errno;
goto fail;
}
r = setsockopt(m->llmnr_ipv6_udp_fd, SOL_SOCKET, SO_REUSEADDR, &one, sizeof(one));
if (r < 0) {
r = -errno;
goto fail;
}
r = setsockopt(m->llmnr_ipv6_udp_fd, IPPROTO_IPV6, IPV6_RECVPKTINFO, &one, sizeof(one));
if (r < 0) {
r = -errno;
goto fail;
}
r = setsockopt(m->llmnr_ipv6_udp_fd, IPPROTO_IPV6, IPV6_RECVHOPLIMIT, &one, sizeof(one));
if (r < 0) {
r = -errno;
goto fail;
}
r = bind(m->llmnr_ipv6_udp_fd, &sa.sa, sizeof(sa.in6));
if (r < 0) {
r = -errno;
goto fail;
}
r = sd_event_add_io(m->event, &m->llmnr_ipv6_udp_event_source, m->llmnr_ipv6_udp_fd, EPOLLIN, on_llmnr_packet, m);
if (r < 0) {
r = -errno;
goto fail;
}
return m->llmnr_ipv6_udp_fd;
fail:
m->llmnr_ipv6_udp_fd = safe_close(m->llmnr_ipv6_udp_fd);
return r;
}
static int on_llmnr_stream_packet(DnsStream *s) {
assert(s);
if (dns_packet_validate_query(s->read_packet) > 0) {
Link *l;
l = hashmap_get(s->manager->links, INT_TO_PTR(s->read_packet->ifindex));
if (l) {
DnsScope *scope = NULL;
if (s->read_packet->family == AF_INET)
scope = l->llmnr_ipv4_scope;
else if (s->read_packet->family == AF_INET6)
scope = l->llmnr_ipv6_scope;
if (scope) {
dns_scope_process_query(scope, s, s->read_packet);
/* If no reply packet was set, we free the stream */
if (s->write_packet)
return 0;
}
}
}
dns_stream_free(s);
return 0;
}
static int on_llmnr_stream(sd_event_source *s, int fd, uint32_t revents, void *userdata) {
DnsStream *stream;
Manager *m = userdata;
int cfd, r;
cfd = accept4(fd, NULL, NULL, SOCK_NONBLOCK|SOCK_CLOEXEC);
if (cfd < 0) {
if (errno == EAGAIN || errno == EINTR)
return 0;
return -errno;
}
r = dns_stream_new(m, &stream, DNS_PROTOCOL_LLMNR, cfd);
if (r < 0) {
safe_close(cfd);
return r;
}
stream->on_packet = on_llmnr_stream_packet;
return 0;
}
int manager_llmnr_ipv4_tcp_fd(Manager *m) {
union sockaddr_union sa = {
.in.sin_family = AF_INET,
.in.sin_port = htobe16(5355),
};
static const int one = 1, pmtu = IP_PMTUDISC_DONT;
int r;
assert(m);
if (m->llmnr_ipv4_tcp_fd >= 0)
return m->llmnr_ipv4_tcp_fd;
m->llmnr_ipv4_tcp_fd = socket(AF_INET, SOCK_STREAM|SOCK_CLOEXEC|SOCK_NONBLOCK, 0);
if (m->llmnr_ipv4_tcp_fd < 0)
return -errno;
/* RFC 4795, section 2.5. requires setting the TTL of TCP streams to 1 */
r = setsockopt(m->llmnr_ipv4_tcp_fd, IPPROTO_IP, IP_TTL, &one, sizeof(one));
if (r < 0) {
r = -errno;
goto fail;
}
r = setsockopt(m->llmnr_ipv4_tcp_fd, SOL_SOCKET, SO_REUSEADDR, &one, sizeof(one));
if (r < 0) {
r = -errno;
goto fail;
}
r = setsockopt(m->llmnr_ipv4_tcp_fd, IPPROTO_IP, IP_PKTINFO, &one, sizeof(one));
if (r < 0) {
r = -errno;
goto fail;
}
r = setsockopt(m->llmnr_ipv4_tcp_fd, IPPROTO_IP, IP_RECVTTL, &one, sizeof(one));
if (r < 0) {
r = -errno;
goto fail;
}
/* Disable Don't-Fragment bit in the IP header */
r = setsockopt(m->llmnr_ipv4_tcp_fd, IPPROTO_IP, IP_MTU_DISCOVER, &pmtu, sizeof(pmtu));
if (r < 0) {
r = -errno;
goto fail;
}
r = bind(m->llmnr_ipv4_tcp_fd, &sa.sa, sizeof(sa.in));
if (r < 0) {
r = -errno;
goto fail;
}
r = listen(m->llmnr_ipv4_tcp_fd, SOMAXCONN);
if (r < 0) {
r = -errno;
goto fail;
}
r = sd_event_add_io(m->event, &m->llmnr_ipv4_tcp_event_source, m->llmnr_ipv4_tcp_fd, EPOLLIN, on_llmnr_stream, m);
if (r < 0)
goto fail;
return m->llmnr_ipv4_tcp_fd;
fail:
m->llmnr_ipv4_tcp_fd = safe_close(m->llmnr_ipv4_tcp_fd);
return r;
}
int manager_llmnr_ipv6_tcp_fd(Manager *m) {
union sockaddr_union sa = {
.in6.sin6_family = AF_INET6,
.in6.sin6_port = htobe16(5355),
};
static const int one = 1;
int r;
assert(m);
if (m->llmnr_ipv6_tcp_fd >= 0)
return m->llmnr_ipv6_tcp_fd;
m->llmnr_ipv6_tcp_fd = socket(AF_INET6, SOCK_STREAM|SOCK_CLOEXEC|SOCK_NONBLOCK, 0);
if (m->llmnr_ipv6_tcp_fd < 0)
return -errno;
/* RFC 4795, section 2.5. requires setting the TTL of TCP streams to 1 */
r = setsockopt(m->llmnr_ipv6_tcp_fd, IPPROTO_IPV6, IPV6_UNICAST_HOPS, &one, sizeof(one));
if (r < 0) {
r = -errno;
goto fail;
}
r = setsockopt(m->llmnr_ipv6_tcp_fd, IPPROTO_IPV6, IPV6_V6ONLY, &one, sizeof(one));
if (r < 0) {
r = -errno;
goto fail;
}
r = setsockopt(m->llmnr_ipv6_tcp_fd, SOL_SOCKET, SO_REUSEADDR, &one, sizeof(one));
if (r < 0) {
r = -errno;
goto fail;
}
r = setsockopt(m->llmnr_ipv6_tcp_fd, IPPROTO_IPV6, IPV6_RECVPKTINFO, &one, sizeof(one));
if (r < 0) {
r = -errno;
goto fail;
}
r = setsockopt(m->llmnr_ipv6_tcp_fd, IPPROTO_IPV6, IPV6_RECVHOPLIMIT, &one, sizeof(one));
if (r < 0) {
r = -errno;
goto fail;
}
r = bind(m->llmnr_ipv6_tcp_fd, &sa.sa, sizeof(sa.in6));
if (r < 0) {
r = -errno;
goto fail;
}
r = listen(m->llmnr_ipv6_tcp_fd, SOMAXCONN);
if (r < 0) {
r = -errno;
goto fail;
}
r = sd_event_add_io(m->event, &m->llmnr_ipv6_tcp_event_source, m->llmnr_ipv6_tcp_fd, EPOLLIN, on_llmnr_stream, m);
if (r < 0) {
r = -errno;
goto fail;
}
return m->llmnr_ipv6_tcp_fd;
fail:
m->llmnr_ipv6_tcp_fd = safe_close(m->llmnr_ipv6_tcp_fd);
return r;
}
int manager_ifindex_is_loopback(Manager *m, int ifindex) {
Link *l;
assert(m);
if (ifindex <= 0)
return -EINVAL;
l = hashmap_get(m->links, INT_TO_PTR(ifindex));
if (l->flags & IFF_LOOPBACK)
return 1;
return 0;
}
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->host_ipv4_key = dns_resource_key_unref(m->host_ipv4_key);
m->host_ipv6_key = dns_resource_key_unref(m->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;
char *h;
assert(m);
p = strchr(m->hostname, 0);
assert(p);
while (p > m->hostname) {
if (!strchr("0123456789", p[-1]))
break;
p--;
}
if (*p == 0 || safe_atou64(p, &u) < 0 || u <= 0)
u = 1;
u++;
if (asprintf(&h, "%.*s%" PRIu64, (int) (p - m->hostname), m->hostname, u) < 0)
return -ENOMEM;
log_info("Hostname conflict, changing published hostname from '%s' to '%s'.", m->hostname, h);
free(m->hostname);
m->hostname = h;
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;
}
int manager_our_packet(Manager *m, DnsPacket *p) {
assert(m);
assert(p);
return !!manager_find_link_address(m, p->family, &p->sender);
}
static const char* const support_table[_SUPPORT_MAX] = {
[SUPPORT_NO] = "no",
[SUPPORT_YES] = "yes",
[SUPPORT_RESOLVE] = "resolve",
};
DEFINE_STRING_TABLE_LOOKUP(support, Support);