resolved-manager.c revision a38d99451f2bf8026ec51aee91662292e823c6a8
091a364c802e34a58f3260c9cb5db9b75c62215cTom Gundersen/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
091a364c802e34a58f3260c9cb5db9b75c62215cTom Gundersen
091a364c802e34a58f3260c9cb5db9b75c62215cTom Gundersen/***
091a364c802e34a58f3260c9cb5db9b75c62215cTom Gundersen This file is part of systemd.
091a364c802e34a58f3260c9cb5db9b75c62215cTom Gundersen
091a364c802e34a58f3260c9cb5db9b75c62215cTom Gundersen Copyright 2014 Tom Gundersen <teg@jklm.no>
091a364c802e34a58f3260c9cb5db9b75c62215cTom Gundersen
091a364c802e34a58f3260c9cb5db9b75c62215cTom Gundersen systemd is free software; you can redistribute it and/or modify it
091a364c802e34a58f3260c9cb5db9b75c62215cTom Gundersen under the terms of the GNU Lesser General Public License as published by
091a364c802e34a58f3260c9cb5db9b75c62215cTom Gundersen the Free Software Foundation; either version 2.1 of the License, or
091a364c802e34a58f3260c9cb5db9b75c62215cTom Gundersen (at your option) any later version.
091a364c802e34a58f3260c9cb5db9b75c62215cTom Gundersen
091a364c802e34a58f3260c9cb5db9b75c62215cTom Gundersen systemd is distributed in the hope that it will be useful, but
091a364c802e34a58f3260c9cb5db9b75c62215cTom Gundersen WITHOUT ANY WARRANTY; without even the implied warranty of
091a364c802e34a58f3260c9cb5db9b75c62215cTom Gundersen MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
091a364c802e34a58f3260c9cb5db9b75c62215cTom Gundersen Lesser General Public License for more details.
091a364c802e34a58f3260c9cb5db9b75c62215cTom Gundersen
091a364c802e34a58f3260c9cb5db9b75c62215cTom Gundersen You should have received a copy of the GNU Lesser General Public License
091a364c802e34a58f3260c9cb5db9b75c62215cTom Gundersen along with systemd; If not, see <http://www.gnu.org/licenses/>.
091a364c802e34a58f3260c9cb5db9b75c62215cTom Gundersen ***/
091a364c802e34a58f3260c9cb5db9b75c62215cTom Gundersen
091a364c802e34a58f3260c9cb5db9b75c62215cTom Gundersen#include <arpa/inet.h>
091a364c802e34a58f3260c9cb5db9b75c62215cTom Gundersen#include <resolv.h>
1716f6dcf54d4c181c2e2558e3d5414f54c8d9caLennart Poettering#include <net/if.h>
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering#include <sys/ioctl.h>
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering#include <sys/poll.h>
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering#include <netinet/in.h>
091a364c802e34a58f3260c9cb5db9b75c62215cTom Gundersen
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering#include "rtnl-util.h"
091a364c802e34a58f3260c9cb5db9b75c62215cTom Gundersen#include "event-util.h"
091a364c802e34a58f3260c9cb5db9b75c62215cTom Gundersen#include "network-util.h"
091a364c802e34a58f3260c9cb5db9b75c62215cTom Gundersen#include "network-internal.h"
091a364c802e34a58f3260c9cb5db9b75c62215cTom Gundersen#include "conf-parser.h"
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering#include "socket-util.h"
a2a416f768e2aa7db5b975cd50eb19237cac9cceLennart Poettering#include "af-list.h"
eb60f9cd4e93ff5016dc1b5486fd1b7e1565fd92Lennart Poettering#include "utf8.h"
a5a807e63a50314e190e9166d8a453cd8dd258e3Zbigniew Jędrzejewski-Szmek#include "fileio-label.h"
4e945a6f7971fd7d1f6b2c62ee3afdaff3c95ce4Lennart Poettering
eb60f9cd4e93ff5016dc1b5486fd1b7e1565fd92Lennart Poettering#include "resolved-dns-domain.h"
39d8db043b599a7382f94bfc904d5e108af438bdLennart Poettering#include "resolved-conf.h"
39d8db043b599a7382f94bfc904d5e108af438bdLennart Poettering#include "resolved-bus.h"
39d8db043b599a7382f94bfc904d5e108af438bdLennart Poettering#include "resolved-manager.h"
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering#define SEND_TIMEOUT_USEC (200 * USEC_PER_MSEC)
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poetteringstatic int manager_process_link(sd_rtnl *rtnl, sd_rtnl_message *mm, void *userdata) {
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering Manager *m = userdata;
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering uint16_t type;
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering Link *l;
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering int ifindex, r;
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering assert(rtnl);
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering assert(m);
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering assert(mm);
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering r = sd_rtnl_message_get_type(mm, &type);
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering if (r < 0)
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering goto fail;
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering r = sd_rtnl_message_link_get_ifindex(mm, &ifindex);
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering if (r < 0)
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering goto fail;
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering l = hashmap_get(m->links, INT_TO_PTR(ifindex));
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering switch (type) {
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering
a2a416f768e2aa7db5b975cd50eb19237cac9cceLennart Poettering case RTM_NEWLINK:{
a2a416f768e2aa7db5b975cd50eb19237cac9cceLennart Poettering bool is_new = !l;
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering
a2a416f768e2aa7db5b975cd50eb19237cac9cceLennart Poettering if (!l) {
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering r = link_new(m, &l, ifindex);
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering if (r < 0)
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering goto fail;
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering }
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering r = link_update_rtnl(l, mm);
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering if (r < 0)
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering goto fail;
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering
21d73c87b09ec2b8642424bc714ce9af3da4fc40Lennart Poettering r = link_update_monitor(l);
21d73c87b09ec2b8642424bc714ce9af3da4fc40Lennart Poettering if (r < 0)
21d73c87b09ec2b8642424bc714ce9af3da4fc40Lennart Poettering goto fail;
21d73c87b09ec2b8642424bc714ce9af3da4fc40Lennart Poettering
a2a416f768e2aa7db5b975cd50eb19237cac9cceLennart Poettering if (is_new)
a2a416f768e2aa7db5b975cd50eb19237cac9cceLennart Poettering log_debug("Found new link %i/%s", ifindex, l->name);
a2a416f768e2aa7db5b975cd50eb19237cac9cceLennart Poettering
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering break;
a2a416f768e2aa7db5b975cd50eb19237cac9cceLennart Poettering }
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering case RTM_DELLINK:
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering if (l) {
a2a416f768e2aa7db5b975cd50eb19237cac9cceLennart Poettering log_debug("Removing link %i/%s", l->ifindex, l->name);
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering link_free(l);
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering }
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering break;
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering }
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering return 0;
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poetteringfail:
da927ba997d68401563b927f92e6e40e021a8e5cMichal Schmidt log_warning_errno(r, "Failed to process RTNL link message: %m");
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering return 0;
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering}
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poetteringstatic int manager_process_address(sd_rtnl *rtnl, sd_rtnl_message *mm, void *userdata) {
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering Manager *m = userdata;
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering union in_addr_union address;
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering uint16_t type;
0dd25fb9f005d8ab7ac4bc10a609d00569f8c56aLennart Poettering int r, ifindex, family;
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering LinkAddress *a;
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering Link *l;
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering assert(rtnl);
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering assert(mm);
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering assert(m);
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering r = sd_rtnl_message_get_type(mm, &type);
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering if (r < 0)
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering goto fail;
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering r = sd_rtnl_message_addr_get_ifindex(mm, &ifindex);
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering if (r < 0)
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering goto fail;
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering l = hashmap_get(m->links, INT_TO_PTR(ifindex));
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering if (!l)
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering return 0;
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering r = sd_rtnl_message_addr_get_family(mm, &family);
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering if (r < 0)
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering goto fail;
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering switch (family) {
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering case AF_INET:
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering r = sd_rtnl_message_read_in_addr(mm, IFA_LOCAL, &address.in);
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering if (r < 0) {
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering r = sd_rtnl_message_read_in_addr(mm, IFA_ADDRESS, &address.in);
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering if (r < 0)
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering goto fail;
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering }
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering break;
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering case AF_INET6:
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering r = sd_rtnl_message_read_in6_addr(mm, IFA_LOCAL, &address.in6);
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering if (r < 0) {
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering r = sd_rtnl_message_read_in6_addr(mm, IFA_ADDRESS, &address.in6);
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering if (r < 0)
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering goto fail;
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering }
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering break;
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering default:
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering return 0;
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering }
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering a = link_find_address(l, family, &address);
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering switch (type) {
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering case RTM_NEWADDR:
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering if (!a) {
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering r = link_address_new(l, &a, family, &address);
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering if (r < 0)
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering return r;
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering }
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering r = link_address_update_rtnl(a, mm);
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering if (r < 0)
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering return r;
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering break;
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering case RTM_DELADDR:
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering if (a)
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering link_address_free(a);
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering break;
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering }
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering return 0;
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poetteringfail:
da927ba997d68401563b927f92e6e40e021a8e5cMichal Schmidt log_warning_errno(r, "Failed to process RTNL address message: %m");
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering return 0;
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering}
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poetteringstatic int manager_rtnl_listen(Manager *m) {
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering _cleanup_rtnl_message_unref_ sd_rtnl_message *req = NULL, *reply = NULL;
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering sd_rtnl_message *i;
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering int r;
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering assert(m);
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering
cc98b3025eeb89addb76a27390cb2baca4eab8b9Torstein Husebø /* First, subscribe to interfaces coming and going */
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering r = sd_rtnl_open(&m->rtnl, 3, RTNLGRP_LINK, RTNLGRP_IPV4_IFADDR, RTNLGRP_IPV6_IFADDR);
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering if (r < 0)
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering return r;
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering r = sd_rtnl_attach_event(m->rtnl, m->event, 0);
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering if (r < 0)
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering return r;
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering r = sd_rtnl_add_match(m->rtnl, RTM_NEWLINK, manager_process_link, m);
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering if (r < 0)
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering return r;
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering r = sd_rtnl_add_match(m->rtnl, RTM_DELLINK, manager_process_link, m);
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering if (r < 0)
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering return r;
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering r = sd_rtnl_add_match(m->rtnl, RTM_NEWADDR, manager_process_address, m);
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering if (r < 0)
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering return r;
091a364c802e34a58f3260c9cb5db9b75c62215cTom Gundersen
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering r = sd_rtnl_add_match(m->rtnl, RTM_DELADDR, manager_process_address, m);
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering if (r < 0)
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering return r;
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering /* Then, enumerate all links */
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering r = sd_rtnl_message_new_link(m->rtnl, &req, RTM_GETLINK, 0);
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering if (r < 0)
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering return r;
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering r = sd_rtnl_message_request_dump(req, true);
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering if (r < 0)
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering return r;
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering r = sd_rtnl_call(m->rtnl, req, 0, &reply);
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering if (r < 0)
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering return r;
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering for (i = reply; i; i = sd_rtnl_message_next(i)) {
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering r = manager_process_link(m->rtnl, i, m);
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering if (r < 0)
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering return r;
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering }
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering req = sd_rtnl_message_unref(req);
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering reply = sd_rtnl_message_unref(reply);
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering /* Finally, enumerate all addresses, too */
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering r = sd_rtnl_message_new_addr(m->rtnl, &req, RTM_GETADDR, 0, AF_UNSPEC);
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering if (r < 0)
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering return r;
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering r = sd_rtnl_message_request_dump(req, true);
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering if (r < 0)
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering return r;
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering r = sd_rtnl_call(m->rtnl, req, 0, &reply);
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering if (r < 0)
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering return r;
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering for (i = reply; i; i = sd_rtnl_message_next(i)) {
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering r = manager_process_address(m->rtnl, i, m);
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering if (r < 0)
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering return r;
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering }
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering return r;
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering}
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poetteringstatic int on_network_event(sd_event_source *s, int fd, uint32_t revents, void *userdata) {
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering Manager *m = userdata;
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering Iterator i;
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering Link *l;
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering int r;
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering assert(m);
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering sd_network_monitor_flush(m->network_monitor);
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering HASHMAP_FOREACH(l, m->links, i) {
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering r = link_update_monitor(l);
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering if (r < 0)
da927ba997d68401563b927f92e6e40e021a8e5cMichal Schmidt log_warning_errno(r, "Failed to update monitor information for %i: %m", l->ifindex);
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering }
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering r = manager_write_resolv_conf(m);
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering if (r < 0)
da927ba997d68401563b927f92e6e40e021a8e5cMichal Schmidt log_warning_errno(r, "Could not update resolv.conf: %m");
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering return 0;
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering}
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poetteringstatic int manager_network_monitor_listen(Manager *m) {
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering int r, fd, events;
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering assert(m);
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering
0014a4ad505d119c7ac4346d9d774c3f17f663a5Lennart Poettering r = sd_network_monitor_new(&m->network_monitor, NULL);
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering if (r < 0)
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering return r;
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering fd = sd_network_monitor_get_fd(m->network_monitor);
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering if (fd < 0)
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering return fd;
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering events = sd_network_monitor_get_events(m->network_monitor);
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering if (events < 0)
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering return events;
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering r = sd_event_add_io(m->event, &m->network_event_source, fd, events, &on_network_event, m);
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering if (r < 0)
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering return r;
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering return 0;
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering}
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering
eb60f9cd4e93ff5016dc1b5486fd1b7e1565fd92Lennart Poetteringstatic int determine_hostname(char **ret) {
eb60f9cd4e93ff5016dc1b5486fd1b7e1565fd92Lennart Poettering _cleanup_free_ char *h = NULL, *n = NULL;
eb60f9cd4e93ff5016dc1b5486fd1b7e1565fd92Lennart Poettering int r;
eb60f9cd4e93ff5016dc1b5486fd1b7e1565fd92Lennart Poettering
eb60f9cd4e93ff5016dc1b5486fd1b7e1565fd92Lennart Poettering assert(ret);
eb60f9cd4e93ff5016dc1b5486fd1b7e1565fd92Lennart Poettering
eb60f9cd4e93ff5016dc1b5486fd1b7e1565fd92Lennart Poettering h = gethostname_malloc();
eb60f9cd4e93ff5016dc1b5486fd1b7e1565fd92Lennart Poettering if (!h)
eb60f9cd4e93ff5016dc1b5486fd1b7e1565fd92Lennart Poettering return log_oom();
eb60f9cd4e93ff5016dc1b5486fd1b7e1565fd92Lennart Poettering
eb60f9cd4e93ff5016dc1b5486fd1b7e1565fd92Lennart Poettering if (!utf8_is_valid(h)) {
eb60f9cd4e93ff5016dc1b5486fd1b7e1565fd92Lennart Poettering log_error("System hostname is not UTF-8 clean.");
eb60f9cd4e93ff5016dc1b5486fd1b7e1565fd92Lennart Poettering return -EINVAL;
eb60f9cd4e93ff5016dc1b5486fd1b7e1565fd92Lennart Poettering }
eb60f9cd4e93ff5016dc1b5486fd1b7e1565fd92Lennart Poettering
eb60f9cd4e93ff5016dc1b5486fd1b7e1565fd92Lennart Poettering r = dns_name_normalize(h, &n);
eb60f9cd4e93ff5016dc1b5486fd1b7e1565fd92Lennart Poettering if (r < 0) {
eb60f9cd4e93ff5016dc1b5486fd1b7e1565fd92Lennart Poettering log_error("System hostname '%s' cannot be normalized.", h);
eb60f9cd4e93ff5016dc1b5486fd1b7e1565fd92Lennart Poettering return r;
eb60f9cd4e93ff5016dc1b5486fd1b7e1565fd92Lennart Poettering }
eb60f9cd4e93ff5016dc1b5486fd1b7e1565fd92Lennart Poettering
eb60f9cd4e93ff5016dc1b5486fd1b7e1565fd92Lennart Poettering *ret = n;
eb60f9cd4e93ff5016dc1b5486fd1b7e1565fd92Lennart Poettering n = NULL;
eb60f9cd4e93ff5016dc1b5486fd1b7e1565fd92Lennart Poettering
eb60f9cd4e93ff5016dc1b5486fd1b7e1565fd92Lennart Poettering return 0;
eb60f9cd4e93ff5016dc1b5486fd1b7e1565fd92Lennart Poettering}
eb60f9cd4e93ff5016dc1b5486fd1b7e1565fd92Lennart Poettering
eb60f9cd4e93ff5016dc1b5486fd1b7e1565fd92Lennart Poetteringstatic int on_hostname_change(sd_event_source *es, int fd, uint32_t revents, void *userdata) {
eb60f9cd4e93ff5016dc1b5486fd1b7e1565fd92Lennart Poettering _cleanup_free_ char *h = NULL;
eb60f9cd4e93ff5016dc1b5486fd1b7e1565fd92Lennart Poettering Manager *m = userdata;
eb60f9cd4e93ff5016dc1b5486fd1b7e1565fd92Lennart Poettering int r;
eb60f9cd4e93ff5016dc1b5486fd1b7e1565fd92Lennart Poettering
eb60f9cd4e93ff5016dc1b5486fd1b7e1565fd92Lennart Poettering assert(m);
eb60f9cd4e93ff5016dc1b5486fd1b7e1565fd92Lennart Poettering
eb60f9cd4e93ff5016dc1b5486fd1b7e1565fd92Lennart Poettering r = determine_hostname(&h);
eb60f9cd4e93ff5016dc1b5486fd1b7e1565fd92Lennart Poettering if (r < 0)
eb60f9cd4e93ff5016dc1b5486fd1b7e1565fd92Lennart Poettering return 0; /* ignore invalid hostnames */
eb60f9cd4e93ff5016dc1b5486fd1b7e1565fd92Lennart Poettering
eb60f9cd4e93ff5016dc1b5486fd1b7e1565fd92Lennart Poettering if (streq(h, m->hostname))
eb60f9cd4e93ff5016dc1b5486fd1b7e1565fd92Lennart Poettering return 0;
eb60f9cd4e93ff5016dc1b5486fd1b7e1565fd92Lennart Poettering
eb60f9cd4e93ff5016dc1b5486fd1b7e1565fd92Lennart Poettering log_info("System hostname changed to '%s'.", h);
eb60f9cd4e93ff5016dc1b5486fd1b7e1565fd92Lennart Poettering free(m->hostname);
eb60f9cd4e93ff5016dc1b5486fd1b7e1565fd92Lennart Poettering m->hostname = h;
eb60f9cd4e93ff5016dc1b5486fd1b7e1565fd92Lennart Poettering h = NULL;
eb60f9cd4e93ff5016dc1b5486fd1b7e1565fd92Lennart Poettering
eb60f9cd4e93ff5016dc1b5486fd1b7e1565fd92Lennart Poettering manager_refresh_rrs(m);
eb60f9cd4e93ff5016dc1b5486fd1b7e1565fd92Lennart Poettering
eb60f9cd4e93ff5016dc1b5486fd1b7e1565fd92Lennart Poettering return 0;
eb60f9cd4e93ff5016dc1b5486fd1b7e1565fd92Lennart Poettering}
eb60f9cd4e93ff5016dc1b5486fd1b7e1565fd92Lennart Poettering
eb60f9cd4e93ff5016dc1b5486fd1b7e1565fd92Lennart Poetteringstatic int manager_watch_hostname(Manager *m) {
eb60f9cd4e93ff5016dc1b5486fd1b7e1565fd92Lennart Poettering int r;
eb60f9cd4e93ff5016dc1b5486fd1b7e1565fd92Lennart Poettering
eb60f9cd4e93ff5016dc1b5486fd1b7e1565fd92Lennart Poettering assert(m);
eb60f9cd4e93ff5016dc1b5486fd1b7e1565fd92Lennart Poettering
eb60f9cd4e93ff5016dc1b5486fd1b7e1565fd92Lennart Poettering m->hostname_fd = open("/proc/sys/kernel/hostname", O_RDONLY|O_CLOEXEC|O_NDELAY|O_NOCTTY);
eb60f9cd4e93ff5016dc1b5486fd1b7e1565fd92Lennart Poettering if (m->hostname_fd < 0) {
56f64d95763a799ba4475daf44d8e9f72a1bd474Michal Schmidt log_warning_errno(errno, "Failed to watch hostname: %m");
eb60f9cd4e93ff5016dc1b5486fd1b7e1565fd92Lennart Poettering return 0;
eb60f9cd4e93ff5016dc1b5486fd1b7e1565fd92Lennart Poettering }
eb60f9cd4e93ff5016dc1b5486fd1b7e1565fd92Lennart Poettering
eb60f9cd4e93ff5016dc1b5486fd1b7e1565fd92Lennart Poettering r = sd_event_add_io(m->event, &m->hostname_event_source, m->hostname_fd, 0, on_hostname_change, m);
eb60f9cd4e93ff5016dc1b5486fd1b7e1565fd92Lennart Poettering if (r < 0) {
eb60f9cd4e93ff5016dc1b5486fd1b7e1565fd92Lennart Poettering if (r == -EPERM)
eb60f9cd4e93ff5016dc1b5486fd1b7e1565fd92Lennart Poettering /* kernels prior to 3.2 don't support polling this file. Ignore the failure. */
eb60f9cd4e93ff5016dc1b5486fd1b7e1565fd92Lennart Poettering m->hostname_fd = safe_close(m->hostname_fd);
8d3d7072e609ef0e0fb37e1d19a29307d58146c3Michal Schmidt else
8d3d7072e609ef0e0fb37e1d19a29307d58146c3Michal Schmidt return log_error_errno(r, "Failed to add hostname event source: %m");
eb60f9cd4e93ff5016dc1b5486fd1b7e1565fd92Lennart Poettering }
eb60f9cd4e93ff5016dc1b5486fd1b7e1565fd92Lennart Poettering
eb60f9cd4e93ff5016dc1b5486fd1b7e1565fd92Lennart Poettering r = determine_hostname(&m->hostname);
eb60f9cd4e93ff5016dc1b5486fd1b7e1565fd92Lennart Poettering if (r < 0) {
eb60f9cd4e93ff5016dc1b5486fd1b7e1565fd92Lennart Poettering log_info("Defaulting to hostname 'linux'.");
eb60f9cd4e93ff5016dc1b5486fd1b7e1565fd92Lennart Poettering m->hostname = strdup("linux");
eb60f9cd4e93ff5016dc1b5486fd1b7e1565fd92Lennart Poettering if (!m->hostname)
eb60f9cd4e93ff5016dc1b5486fd1b7e1565fd92Lennart Poettering return log_oom();
eb60f9cd4e93ff5016dc1b5486fd1b7e1565fd92Lennart Poettering } else
eb60f9cd4e93ff5016dc1b5486fd1b7e1565fd92Lennart Poettering log_info("Using system hostname '%s'.", m->hostname);
eb60f9cd4e93ff5016dc1b5486fd1b7e1565fd92Lennart Poettering
eb60f9cd4e93ff5016dc1b5486fd1b7e1565fd92Lennart Poettering return 0;
eb60f9cd4e93ff5016dc1b5486fd1b7e1565fd92Lennart Poettering}
eb60f9cd4e93ff5016dc1b5486fd1b7e1565fd92Lennart Poettering
edc501d4674dadc304d45a7e1c5b69e207eb8cd4Lennart Poetteringstatic void manager_llmnr_stop(Manager *m) {
edc501d4674dadc304d45a7e1c5b69e207eb8cd4Lennart Poettering assert(m);
edc501d4674dadc304d45a7e1c5b69e207eb8cd4Lennart Poettering
edc501d4674dadc304d45a7e1c5b69e207eb8cd4Lennart Poettering m->llmnr_ipv4_udp_event_source = sd_event_source_unref(m->llmnr_ipv4_udp_event_source);
edc501d4674dadc304d45a7e1c5b69e207eb8cd4Lennart Poettering m->llmnr_ipv4_udp_fd = safe_close(m->llmnr_ipv4_udp_fd);
edc501d4674dadc304d45a7e1c5b69e207eb8cd4Lennart Poettering
edc501d4674dadc304d45a7e1c5b69e207eb8cd4Lennart Poettering m->llmnr_ipv6_udp_event_source = sd_event_source_unref(m->llmnr_ipv6_udp_event_source);
edc501d4674dadc304d45a7e1c5b69e207eb8cd4Lennart Poettering m->llmnr_ipv6_udp_fd = safe_close(m->llmnr_ipv6_udp_fd);
edc501d4674dadc304d45a7e1c5b69e207eb8cd4Lennart Poettering
edc501d4674dadc304d45a7e1c5b69e207eb8cd4Lennart Poettering m->llmnr_ipv4_tcp_event_source = sd_event_source_unref(m->llmnr_ipv4_tcp_event_source);
edc501d4674dadc304d45a7e1c5b69e207eb8cd4Lennart Poettering m->llmnr_ipv4_tcp_fd = safe_close(m->llmnr_ipv4_tcp_fd);
edc501d4674dadc304d45a7e1c5b69e207eb8cd4Lennart Poettering
edc501d4674dadc304d45a7e1c5b69e207eb8cd4Lennart Poettering m->llmnr_ipv6_tcp_event_source = sd_event_source_unref(m->llmnr_ipv6_tcp_event_source);
edc501d4674dadc304d45a7e1c5b69e207eb8cd4Lennart Poettering m->llmnr_ipv6_tcp_fd = safe_close(m->llmnr_ipv6_tcp_fd);
edc501d4674dadc304d45a7e1c5b69e207eb8cd4Lennart Poettering}
edc501d4674dadc304d45a7e1c5b69e207eb8cd4Lennart Poettering
edc501d4674dadc304d45a7e1c5b69e207eb8cd4Lennart Poetteringstatic int manager_llmnr_start(Manager *m) {
edc501d4674dadc304d45a7e1c5b69e207eb8cd4Lennart Poettering int r;
edc501d4674dadc304d45a7e1c5b69e207eb8cd4Lennart Poettering
edc501d4674dadc304d45a7e1c5b69e207eb8cd4Lennart Poettering assert(m);
edc501d4674dadc304d45a7e1c5b69e207eb8cd4Lennart Poettering
edc501d4674dadc304d45a7e1c5b69e207eb8cd4Lennart Poettering if (m->llmnr_support == SUPPORT_NO)
edc501d4674dadc304d45a7e1c5b69e207eb8cd4Lennart Poettering return 0;
edc501d4674dadc304d45a7e1c5b69e207eb8cd4Lennart Poettering
edc501d4674dadc304d45a7e1c5b69e207eb8cd4Lennart Poettering r = manager_llmnr_ipv4_udp_fd(m);
edc501d4674dadc304d45a7e1c5b69e207eb8cd4Lennart Poettering if (r == -EADDRINUSE)
edc501d4674dadc304d45a7e1c5b69e207eb8cd4Lennart Poettering goto eaddrinuse;
edc501d4674dadc304d45a7e1c5b69e207eb8cd4Lennart Poettering if (r < 0)
edc501d4674dadc304d45a7e1c5b69e207eb8cd4Lennart Poettering return r;
edc501d4674dadc304d45a7e1c5b69e207eb8cd4Lennart Poettering
edc501d4674dadc304d45a7e1c5b69e207eb8cd4Lennart Poettering r = manager_llmnr_ipv4_tcp_fd(m);
edc501d4674dadc304d45a7e1c5b69e207eb8cd4Lennart Poettering if (r == -EADDRINUSE)
edc501d4674dadc304d45a7e1c5b69e207eb8cd4Lennart Poettering goto eaddrinuse;
edc501d4674dadc304d45a7e1c5b69e207eb8cd4Lennart Poettering if (r < 0)
edc501d4674dadc304d45a7e1c5b69e207eb8cd4Lennart Poettering return r;
edc501d4674dadc304d45a7e1c5b69e207eb8cd4Lennart Poettering
90ab504273a7f186ebb76e6acfb778b4e0d7c91bLennart Poettering if (socket_ipv6_is_supported()) {
90ab504273a7f186ebb76e6acfb778b4e0d7c91bLennart Poettering r = manager_llmnr_ipv6_udp_fd(m);
90ab504273a7f186ebb76e6acfb778b4e0d7c91bLennart Poettering if (r == -EADDRINUSE)
90ab504273a7f186ebb76e6acfb778b4e0d7c91bLennart Poettering goto eaddrinuse;
90ab504273a7f186ebb76e6acfb778b4e0d7c91bLennart Poettering if (r < 0)
90ab504273a7f186ebb76e6acfb778b4e0d7c91bLennart Poettering return r;
90ab504273a7f186ebb76e6acfb778b4e0d7c91bLennart Poettering
90ab504273a7f186ebb76e6acfb778b4e0d7c91bLennart Poettering r = manager_llmnr_ipv6_tcp_fd(m);
90ab504273a7f186ebb76e6acfb778b4e0d7c91bLennart Poettering if (r == -EADDRINUSE)
90ab504273a7f186ebb76e6acfb778b4e0d7c91bLennart Poettering goto eaddrinuse;
90ab504273a7f186ebb76e6acfb778b4e0d7c91bLennart Poettering if (r < 0)
90ab504273a7f186ebb76e6acfb778b4e0d7c91bLennart Poettering return r;
90ab504273a7f186ebb76e6acfb778b4e0d7c91bLennart Poettering }
edc501d4674dadc304d45a7e1c5b69e207eb8cd4Lennart Poettering
edc501d4674dadc304d45a7e1c5b69e207eb8cd4Lennart Poettering return 0;
edc501d4674dadc304d45a7e1c5b69e207eb8cd4Lennart Poettering
edc501d4674dadc304d45a7e1c5b69e207eb8cd4Lennart Poetteringeaddrinuse:
c4147df156835513c43260a14fc9f7af177f737fLennart Poettering log_warning("There appears to be another LLMNR responder running. Turning off LLMNR support.");
edc501d4674dadc304d45a7e1c5b69e207eb8cd4Lennart Poettering m->llmnr_support = SUPPORT_NO;
edc501d4674dadc304d45a7e1c5b69e207eb8cd4Lennart Poettering manager_llmnr_stop(m);
90ab504273a7f186ebb76e6acfb778b4e0d7c91bLennart Poettering
edc501d4674dadc304d45a7e1c5b69e207eb8cd4Lennart Poettering return 0;
edc501d4674dadc304d45a7e1c5b69e207eb8cd4Lennart Poettering}
edc501d4674dadc304d45a7e1c5b69e207eb8cd4Lennart Poettering
091a364c802e34a58f3260c9cb5db9b75c62215cTom Gundersenint manager_new(Manager **ret) {
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering _cleanup_(manager_freep) Manager *m = NULL;
091a364c802e34a58f3260c9cb5db9b75c62215cTom Gundersen int r;
091a364c802e34a58f3260c9cb5db9b75c62215cTom Gundersen
c92e531c82a9815ec349aa1bf31236b86b2d5311Lennart Poettering assert(ret);
c92e531c82a9815ec349aa1bf31236b86b2d5311Lennart Poettering
091a364c802e34a58f3260c9cb5db9b75c62215cTom Gundersen m = new0(Manager, 1);
091a364c802e34a58f3260c9cb5db9b75c62215cTom Gundersen if (!m)
091a364c802e34a58f3260c9cb5db9b75c62215cTom Gundersen return -ENOMEM;
091a364c802e34a58f3260c9cb5db9b75c62215cTom Gundersen
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering m->dns_ipv4_fd = m->dns_ipv6_fd = -1;
1716f6dcf54d4c181c2e2558e3d5414f54c8d9caLennart Poettering m->llmnr_ipv4_udp_fd = m->llmnr_ipv6_udp_fd = -1;
623a4c97b9175f95c4b1c6fc34e36c56f1e4ddbfLennart Poettering m->llmnr_ipv4_tcp_fd = m->llmnr_ipv6_tcp_fd = -1;
eb60f9cd4e93ff5016dc1b5486fd1b7e1565fd92Lennart Poettering m->hostname_fd = -1;
1716f6dcf54d4c181c2e2558e3d5414f54c8d9caLennart Poettering
4e945a6f7971fd7d1f6b2c62ee3afdaff3c95ce4Lennart Poettering m->llmnr_support = SUPPORT_YES;
5cb36f41f01cf4b1f4395abfffd1b33116591e58Lennart Poettering m->read_resolv_conf = true;
091a364c802e34a58f3260c9cb5db9b75c62215cTom Gundersen
4e945a6f7971fd7d1f6b2c62ee3afdaff3c95ce4Lennart Poettering r = manager_parse_dns_server(m, DNS_SERVER_FALLBACK, DNS_SERVERS);
091a364c802e34a58f3260c9cb5db9b75c62215cTom Gundersen if (r < 0)
091a364c802e34a58f3260c9cb5db9b75c62215cTom Gundersen return r;
091a364c802e34a58f3260c9cb5db9b75c62215cTom Gundersen
091a364c802e34a58f3260c9cb5db9b75c62215cTom Gundersen r = sd_event_default(&m->event);
091a364c802e34a58f3260c9cb5db9b75c62215cTom Gundersen if (r < 0)
091a364c802e34a58f3260c9cb5db9b75c62215cTom Gundersen return r;
091a364c802e34a58f3260c9cb5db9b75c62215cTom Gundersen
091a364c802e34a58f3260c9cb5db9b75c62215cTom Gundersen sd_event_add_signal(m->event, NULL, SIGTERM, NULL, NULL);
091a364c802e34a58f3260c9cb5db9b75c62215cTom Gundersen sd_event_add_signal(m->event, NULL, SIGINT, NULL, NULL);
091a364c802e34a58f3260c9cb5db9b75c62215cTom Gundersen
091a364c802e34a58f3260c9cb5db9b75c62215cTom Gundersen sd_event_set_watchdog(m->event, true);
091a364c802e34a58f3260c9cb5db9b75c62215cTom Gundersen
eb60f9cd4e93ff5016dc1b5486fd1b7e1565fd92Lennart Poettering r = manager_watch_hostname(m);
eb60f9cd4e93ff5016dc1b5486fd1b7e1565fd92Lennart Poettering if (r < 0)
eb60f9cd4e93ff5016dc1b5486fd1b7e1565fd92Lennart Poettering return r;
eb60f9cd4e93ff5016dc1b5486fd1b7e1565fd92Lennart Poettering
1716f6dcf54d4c181c2e2558e3d5414f54c8d9caLennart Poettering r = dns_scope_new(m, &m->unicast_scope, NULL, DNS_PROTOCOL_DNS, AF_UNSPEC);
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering if (r < 0)
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering return r;
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering r = manager_network_monitor_listen(m);
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering if (r < 0)
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering return r;
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering r = manager_rtnl_listen(m);
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering if (r < 0)
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering return r;
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering r = manager_connect_bus(m);
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering if (r < 0)
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering return r;
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering
091a364c802e34a58f3260c9cb5db9b75c62215cTom Gundersen *ret = m;
091a364c802e34a58f3260c9cb5db9b75c62215cTom Gundersen m = NULL;
091a364c802e34a58f3260c9cb5db9b75c62215cTom Gundersen
091a364c802e34a58f3260c9cb5db9b75c62215cTom Gundersen return 0;
091a364c802e34a58f3260c9cb5db9b75c62215cTom Gundersen}
091a364c802e34a58f3260c9cb5db9b75c62215cTom Gundersen
edc501d4674dadc304d45a7e1c5b69e207eb8cd4Lennart Poetteringint manager_start(Manager *m) {
edc501d4674dadc304d45a7e1c5b69e207eb8cd4Lennart Poettering int r;
edc501d4674dadc304d45a7e1c5b69e207eb8cd4Lennart Poettering
edc501d4674dadc304d45a7e1c5b69e207eb8cd4Lennart Poettering assert(m);
edc501d4674dadc304d45a7e1c5b69e207eb8cd4Lennart Poettering
edc501d4674dadc304d45a7e1c5b69e207eb8cd4Lennart Poettering r = manager_llmnr_start(m);
edc501d4674dadc304d45a7e1c5b69e207eb8cd4Lennart Poettering if (r < 0)
edc501d4674dadc304d45a7e1c5b69e207eb8cd4Lennart Poettering return r;
edc501d4674dadc304d45a7e1c5b69e207eb8cd4Lennart Poettering
edc501d4674dadc304d45a7e1c5b69e207eb8cd4Lennart Poettering return 0;
edc501d4674dadc304d45a7e1c5b69e207eb8cd4Lennart Poettering}
edc501d4674dadc304d45a7e1c5b69e207eb8cd4Lennart Poettering
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart PoetteringManager *manager_free(Manager *m) {
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering Link *l;
091a364c802e34a58f3260c9cb5db9b75c62215cTom Gundersen
091a364c802e34a58f3260c9cb5db9b75c62215cTom Gundersen if (!m)
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering return NULL;
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering while ((l = hashmap_first(m->links)))
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering link_free(l);
f0e1546763304aedc90e91d70dab9eeb7c966cf8Lennart Poettering
f0e1546763304aedc90e91d70dab9eeb7c966cf8Lennart Poettering while (m->dns_queries)
f0e1546763304aedc90e91d70dab9eeb7c966cf8Lennart Poettering dns_query_free(m->dns_queries);
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering dns_scope_free(m->unicast_scope);
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering
3e684349c2cead2e6fd2f816c34eb17daba23a49Lennart Poettering manager_flush_dns_servers(m, DNS_SERVER_SYSTEM);
3e684349c2cead2e6fd2f816c34eb17daba23a49Lennart Poettering manager_flush_dns_servers(m, DNS_SERVER_FALLBACK);
091a364c802e34a58f3260c9cb5db9b75c62215cTom Gundersen
f0e1546763304aedc90e91d70dab9eeb7c966cf8Lennart Poettering hashmap_free(m->links);
f0e1546763304aedc90e91d70dab9eeb7c966cf8Lennart Poettering hashmap_free(m->dns_transactions);
f0e1546763304aedc90e91d70dab9eeb7c966cf8Lennart Poettering
096b6773886bd7a0c8c97aa684b0b67dfae58355Lennart Poettering sd_event_source_unref(m->network_event_source);
096b6773886bd7a0c8c97aa684b0b67dfae58355Lennart Poettering sd_network_monitor_unref(m->network_monitor);
091a364c802e34a58f3260c9cb5db9b75c62215cTom Gundersen
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering sd_event_source_unref(m->dns_ipv4_event_source);
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering sd_event_source_unref(m->dns_ipv6_event_source);
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering safe_close(m->dns_ipv4_fd);
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering safe_close(m->dns_ipv6_fd);
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering
edc501d4674dadc304d45a7e1c5b69e207eb8cd4Lennart Poettering manager_llmnr_stop(m);
623a4c97b9175f95c4b1c6fc34e36c56f1e4ddbfLennart Poettering
902bb5d8abb2a7d258741828d212ca549ab16950Lennart Poettering sd_bus_slot_unref(m->prepare_for_sleep_slot);
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering sd_event_source_unref(m->bus_retry_event_source);
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering sd_bus_unref(m->bus);
091a364c802e34a58f3260c9cb5db9b75c62215cTom Gundersen
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering sd_event_unref(m->event);
623a4c97b9175f95c4b1c6fc34e36c56f1e4ddbfLennart Poettering
623a4c97b9175f95c4b1c6fc34e36c56f1e4ddbfLennart Poettering dns_resource_key_unref(m->host_ipv4_key);
623a4c97b9175f95c4b1c6fc34e36c56f1e4ddbfLennart Poettering dns_resource_key_unref(m->host_ipv6_key);
eb60f9cd4e93ff5016dc1b5486fd1b7e1565fd92Lennart Poettering
eb60f9cd4e93ff5016dc1b5486fd1b7e1565fd92Lennart Poettering safe_close(m->hostname_fd);
eb60f9cd4e93ff5016dc1b5486fd1b7e1565fd92Lennart Poettering sd_event_source_unref(m->hostname_event_source);
623a4c97b9175f95c4b1c6fc34e36c56f1e4ddbfLennart Poettering free(m->hostname);
eb60f9cd4e93ff5016dc1b5486fd1b7e1565fd92Lennart Poettering
091a364c802e34a58f3260c9cb5db9b75c62215cTom Gundersen free(m);
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering return NULL;
091a364c802e34a58f3260c9cb5db9b75c62215cTom Gundersen}
091a364c802e34a58f3260c9cb5db9b75c62215cTom Gundersen
5cb36f41f01cf4b1f4395abfffd1b33116591e58Lennart Poetteringint manager_read_resolv_conf(Manager *m) {
5cb36f41f01cf4b1f4395abfffd1b33116591e58Lennart Poettering _cleanup_fclose_ FILE *f = NULL;
5cb36f41f01cf4b1f4395abfffd1b33116591e58Lennart Poettering struct stat st, own;
5cb36f41f01cf4b1f4395abfffd1b33116591e58Lennart Poettering char line[LINE_MAX];
5cb36f41f01cf4b1f4395abfffd1b33116591e58Lennart Poettering DnsServer *s, *nx;
5cb36f41f01cf4b1f4395abfffd1b33116591e58Lennart Poettering usec_t t;
5cb36f41f01cf4b1f4395abfffd1b33116591e58Lennart Poettering int r;
5cb36f41f01cf4b1f4395abfffd1b33116591e58Lennart Poettering
5cb36f41f01cf4b1f4395abfffd1b33116591e58Lennart Poettering assert(m);
5cb36f41f01cf4b1f4395abfffd1b33116591e58Lennart Poettering
5cb36f41f01cf4b1f4395abfffd1b33116591e58Lennart Poettering /* Reads the system /etc/resolv.conf, if it exists and is not
5cb36f41f01cf4b1f4395abfffd1b33116591e58Lennart Poettering * symlinked to our own resolv.conf instance */
5cb36f41f01cf4b1f4395abfffd1b33116591e58Lennart Poettering
5cb36f41f01cf4b1f4395abfffd1b33116591e58Lennart Poettering if (!m->read_resolv_conf)
5cb36f41f01cf4b1f4395abfffd1b33116591e58Lennart Poettering return 0;
5cb36f41f01cf4b1f4395abfffd1b33116591e58Lennart Poettering
5cb36f41f01cf4b1f4395abfffd1b33116591e58Lennart Poettering r = stat("/etc/resolv.conf", &st);
5cb36f41f01cf4b1f4395abfffd1b33116591e58Lennart Poettering if (r < 0) {
5cb36f41f01cf4b1f4395abfffd1b33116591e58Lennart Poettering if (errno != ENOENT)
56f64d95763a799ba4475daf44d8e9f72a1bd474Michal Schmidt log_warning_errno(errno, "Failed to open /etc/resolv.conf: %m");
5cb36f41f01cf4b1f4395abfffd1b33116591e58Lennart Poettering r = -errno;
5cb36f41f01cf4b1f4395abfffd1b33116591e58Lennart Poettering goto clear;
5cb36f41f01cf4b1f4395abfffd1b33116591e58Lennart Poettering }
5cb36f41f01cf4b1f4395abfffd1b33116591e58Lennart Poettering
5cb36f41f01cf4b1f4395abfffd1b33116591e58Lennart Poettering /* Have we already seen the file? */
5cb36f41f01cf4b1f4395abfffd1b33116591e58Lennart Poettering t = timespec_load(&st.st_mtim);
5cb36f41f01cf4b1f4395abfffd1b33116591e58Lennart Poettering if (t == m->resolv_conf_mtime)
5cb36f41f01cf4b1f4395abfffd1b33116591e58Lennart Poettering return 0;
5cb36f41f01cf4b1f4395abfffd1b33116591e58Lennart Poettering
5cb36f41f01cf4b1f4395abfffd1b33116591e58Lennart Poettering m->resolv_conf_mtime = t;
5cb36f41f01cf4b1f4395abfffd1b33116591e58Lennart Poettering
5cb36f41f01cf4b1f4395abfffd1b33116591e58Lennart Poettering /* Is it symlinked to our own file? */
5cb36f41f01cf4b1f4395abfffd1b33116591e58Lennart Poettering if (stat("/run/systemd/resolve/resolv.conf", &own) >= 0 &&
5cb36f41f01cf4b1f4395abfffd1b33116591e58Lennart Poettering st.st_dev == own.st_dev &&
5cb36f41f01cf4b1f4395abfffd1b33116591e58Lennart Poettering st.st_ino == own.st_ino) {
5cb36f41f01cf4b1f4395abfffd1b33116591e58Lennart Poettering r = 0;
5cb36f41f01cf4b1f4395abfffd1b33116591e58Lennart Poettering goto clear;
5cb36f41f01cf4b1f4395abfffd1b33116591e58Lennart Poettering }
5cb36f41f01cf4b1f4395abfffd1b33116591e58Lennart Poettering
5cb36f41f01cf4b1f4395abfffd1b33116591e58Lennart Poettering f = fopen("/etc/resolv.conf", "re");
5cb36f41f01cf4b1f4395abfffd1b33116591e58Lennart Poettering if (!f) {
5cb36f41f01cf4b1f4395abfffd1b33116591e58Lennart Poettering if (errno != ENOENT)
56f64d95763a799ba4475daf44d8e9f72a1bd474Michal Schmidt log_warning_errno(errno, "Failed to open /etc/resolv.conf: %m");
5cb36f41f01cf4b1f4395abfffd1b33116591e58Lennart Poettering r = -errno;
5cb36f41f01cf4b1f4395abfffd1b33116591e58Lennart Poettering goto clear;
5cb36f41f01cf4b1f4395abfffd1b33116591e58Lennart Poettering }
5cb36f41f01cf4b1f4395abfffd1b33116591e58Lennart Poettering
5cb36f41f01cf4b1f4395abfffd1b33116591e58Lennart Poettering if (fstat(fileno(f), &st) < 0) {
56f64d95763a799ba4475daf44d8e9f72a1bd474Michal Schmidt log_error_errno(errno, "Failed to stat open file: %m");
5cb36f41f01cf4b1f4395abfffd1b33116591e58Lennart Poettering r = -errno;
5cb36f41f01cf4b1f4395abfffd1b33116591e58Lennart Poettering goto clear;
5cb36f41f01cf4b1f4395abfffd1b33116591e58Lennart Poettering }
5cb36f41f01cf4b1f4395abfffd1b33116591e58Lennart Poettering
5cb36f41f01cf4b1f4395abfffd1b33116591e58Lennart Poettering LIST_FOREACH(servers, s, m->dns_servers)
5cb36f41f01cf4b1f4395abfffd1b33116591e58Lennart Poettering s->marked = true;
5cb36f41f01cf4b1f4395abfffd1b33116591e58Lennart Poettering
5cb36f41f01cf4b1f4395abfffd1b33116591e58Lennart Poettering FOREACH_LINE(line, f, r = -errno; goto clear) {
5cb36f41f01cf4b1f4395abfffd1b33116591e58Lennart Poettering union in_addr_union address;
5cb36f41f01cf4b1f4395abfffd1b33116591e58Lennart Poettering int family;
5cb36f41f01cf4b1f4395abfffd1b33116591e58Lennart Poettering char *l;
5cb36f41f01cf4b1f4395abfffd1b33116591e58Lennart Poettering const char *a;
5cb36f41f01cf4b1f4395abfffd1b33116591e58Lennart Poettering
5cb36f41f01cf4b1f4395abfffd1b33116591e58Lennart Poettering truncate_nl(line);
5cb36f41f01cf4b1f4395abfffd1b33116591e58Lennart Poettering
5cb36f41f01cf4b1f4395abfffd1b33116591e58Lennart Poettering l = strstrip(line);
5cb36f41f01cf4b1f4395abfffd1b33116591e58Lennart Poettering if (*l == '#' || *l == ';')
5cb36f41f01cf4b1f4395abfffd1b33116591e58Lennart Poettering continue;
5cb36f41f01cf4b1f4395abfffd1b33116591e58Lennart Poettering
5cb36f41f01cf4b1f4395abfffd1b33116591e58Lennart Poettering a = first_word(l, "nameserver");
5cb36f41f01cf4b1f4395abfffd1b33116591e58Lennart Poettering if (!a)
5cb36f41f01cf4b1f4395abfffd1b33116591e58Lennart Poettering continue;
5cb36f41f01cf4b1f4395abfffd1b33116591e58Lennart Poettering
5cb36f41f01cf4b1f4395abfffd1b33116591e58Lennart Poettering r = in_addr_from_string_auto(a, &family, &address);
5cb36f41f01cf4b1f4395abfffd1b33116591e58Lennart Poettering if (r < 0) {
5cb36f41f01cf4b1f4395abfffd1b33116591e58Lennart Poettering log_warning("Failed to parse name server %s.", a);
5cb36f41f01cf4b1f4395abfffd1b33116591e58Lennart Poettering continue;
5cb36f41f01cf4b1f4395abfffd1b33116591e58Lennart Poettering }
5cb36f41f01cf4b1f4395abfffd1b33116591e58Lennart Poettering
5cb36f41f01cf4b1f4395abfffd1b33116591e58Lennart Poettering LIST_FOREACH(servers, s, m->dns_servers)
5cb36f41f01cf4b1f4395abfffd1b33116591e58Lennart Poettering if (s->family == family && in_addr_equal(family, &s->address, &address) > 0)
5cb36f41f01cf4b1f4395abfffd1b33116591e58Lennart Poettering break;
5cb36f41f01cf4b1f4395abfffd1b33116591e58Lennart Poettering
5cb36f41f01cf4b1f4395abfffd1b33116591e58Lennart Poettering if (s)
5cb36f41f01cf4b1f4395abfffd1b33116591e58Lennart Poettering s->marked = false;
5cb36f41f01cf4b1f4395abfffd1b33116591e58Lennart Poettering else {
5cb36f41f01cf4b1f4395abfffd1b33116591e58Lennart Poettering r = dns_server_new(m, NULL, DNS_SERVER_SYSTEM, NULL, family, &address);
5cb36f41f01cf4b1f4395abfffd1b33116591e58Lennart Poettering if (r < 0)
5cb36f41f01cf4b1f4395abfffd1b33116591e58Lennart Poettering goto clear;
5cb36f41f01cf4b1f4395abfffd1b33116591e58Lennart Poettering }
5cb36f41f01cf4b1f4395abfffd1b33116591e58Lennart Poettering }
5cb36f41f01cf4b1f4395abfffd1b33116591e58Lennart Poettering
5cb36f41f01cf4b1f4395abfffd1b33116591e58Lennart Poettering LIST_FOREACH_SAFE(servers, s, nx, m->dns_servers)
5cb36f41f01cf4b1f4395abfffd1b33116591e58Lennart Poettering if (s->marked)
5cb36f41f01cf4b1f4395abfffd1b33116591e58Lennart Poettering dns_server_free(s);
5cb36f41f01cf4b1f4395abfffd1b33116591e58Lennart Poettering
36a03ca2a8952ca1acb29fbe796210c27ff71affLennart Poettering /* Whenever /etc/resolv.conf changes, start using the first
36a03ca2a8952ca1acb29fbe796210c27ff71affLennart Poettering * DNS server of it. This is useful to deal with broken
36a03ca2a8952ca1acb29fbe796210c27ff71affLennart Poettering * network managing implementations (like NetworkManager),
36a03ca2a8952ca1acb29fbe796210c27ff71affLennart Poettering * that when connecting to a VPN place both the VPN DNS
36a03ca2a8952ca1acb29fbe796210c27ff71affLennart Poettering * servers and the local ones in /etc/resolv.conf. Without
36a03ca2a8952ca1acb29fbe796210c27ff71affLennart Poettering * resetting the DNS server to use back to the first entry we
36a03ca2a8952ca1acb29fbe796210c27ff71affLennart Poettering * will continue to use the local one thus being unable to
36a03ca2a8952ca1acb29fbe796210c27ff71affLennart Poettering * resolve VPN domains. */
36a03ca2a8952ca1acb29fbe796210c27ff71affLennart Poettering manager_set_dns_server(m, m->dns_servers);
36a03ca2a8952ca1acb29fbe796210c27ff71affLennart Poettering
5cb36f41f01cf4b1f4395abfffd1b33116591e58Lennart Poettering return 0;
5cb36f41f01cf4b1f4395abfffd1b33116591e58Lennart Poettering
5cb36f41f01cf4b1f4395abfffd1b33116591e58Lennart Poetteringclear:
5cb36f41f01cf4b1f4395abfffd1b33116591e58Lennart Poettering while (m->dns_servers)
5cb36f41f01cf4b1f4395abfffd1b33116591e58Lennart Poettering dns_server_free(m->dns_servers);
5cb36f41f01cf4b1f4395abfffd1b33116591e58Lennart Poettering
5cb36f41f01cf4b1f4395abfffd1b33116591e58Lennart Poettering return r;
5cb36f41f01cf4b1f4395abfffd1b33116591e58Lennart Poettering}
5cb36f41f01cf4b1f4395abfffd1b33116591e58Lennart Poettering
bda2c408f8a739c19161818bcc842107f60652a2Tom Gundersenstatic void write_resolv_conf_server(DnsServer *s, FILE *f, unsigned *count) {
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering _cleanup_free_ char *t = NULL;
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering int r;
091a364c802e34a58f3260c9cb5db9b75c62215cTom Gundersen
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering assert(s);
091a364c802e34a58f3260c9cb5db9b75c62215cTom Gundersen assert(f);
091a364c802e34a58f3260c9cb5db9b75c62215cTom Gundersen assert(count);
091a364c802e34a58f3260c9cb5db9b75c62215cTom Gundersen
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering r = in_addr_to_string(s->family, &s->address, &t);
4e945a6f7971fd7d1f6b2c62ee3afdaff3c95ce4Lennart Poettering if (r < 0) {
da927ba997d68401563b927f92e6e40e021a8e5cMichal Schmidt log_warning_errno(r, "Invalid DNS address. Ignoring: %m");
091a364c802e34a58f3260c9cb5db9b75c62215cTom Gundersen return;
091a364c802e34a58f3260c9cb5db9b75c62215cTom Gundersen }
091a364c802e34a58f3260c9cb5db9b75c62215cTom Gundersen
091a364c802e34a58f3260c9cb5db9b75c62215cTom Gundersen if (*count == MAXNS)
87f5a19343acf8ba697acc5a62bdb1a2b8c9eda3Lennart Poettering fputs("# Too many DNS servers configured, the following entries may be ignored.\n", f);
091a364c802e34a58f3260c9cb5db9b75c62215cTom Gundersen
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering fprintf(f, "nameserver %s\n", t);
091a364c802e34a58f3260c9cb5db9b75c62215cTom Gundersen (*count) ++;
091a364c802e34a58f3260c9cb5db9b75c62215cTom Gundersen}
091a364c802e34a58f3260c9cb5db9b75c62215cTom Gundersen
bda2c408f8a739c19161818bcc842107f60652a2Tom Gundersenstatic void write_resolv_conf_search(const char *domain, FILE *f,
a9feff3d774eaa1cc1b59189e8f344c01e69f888Tom Gundersen unsigned *count, unsigned *length) {
bda2c408f8a739c19161818bcc842107f60652a2Tom Gundersen assert(domain);
bda2c408f8a739c19161818bcc842107f60652a2Tom Gundersen assert(f);
bda2c408f8a739c19161818bcc842107f60652a2Tom Gundersen assert(length);
bda2c408f8a739c19161818bcc842107f60652a2Tom Gundersen
bda2c408f8a739c19161818bcc842107f60652a2Tom Gundersen if (*count >= MAXDNSRCH ||
bda2c408f8a739c19161818bcc842107f60652a2Tom Gundersen *length + strlen(domain) > 256) {
bda2c408f8a739c19161818bcc842107f60652a2Tom Gundersen if (*count == MAXDNSRCH)
bda2c408f8a739c19161818bcc842107f60652a2Tom Gundersen fputs(" # Too many search domains configured, remaining ones ignored.", f);
bda2c408f8a739c19161818bcc842107f60652a2Tom Gundersen if (*length <= 256)
bda2c408f8a739c19161818bcc842107f60652a2Tom Gundersen fputs(" # Total length of all search domains is too long, remaining ones ignored.", f);
bda2c408f8a739c19161818bcc842107f60652a2Tom Gundersen
bda2c408f8a739c19161818bcc842107f60652a2Tom Gundersen return;
bda2c408f8a739c19161818bcc842107f60652a2Tom Gundersen }
bda2c408f8a739c19161818bcc842107f60652a2Tom Gundersen
bda2c408f8a739c19161818bcc842107f60652a2Tom Gundersen fprintf(f, " %s", domain);
bda2c408f8a739c19161818bcc842107f60652a2Tom Gundersen
bda2c408f8a739c19161818bcc842107f60652a2Tom Gundersen (*length) += strlen(domain);
bda2c408f8a739c19161818bcc842107f60652a2Tom Gundersen (*count) ++;
bda2c408f8a739c19161818bcc842107f60652a2Tom Gundersen}
bda2c408f8a739c19161818bcc842107f60652a2Tom Gundersen
4713135eae4f7b6b670a98476fe413edfa1d9f41Zbigniew Jędrzejewski-Szmekstatic int write_resolv_conf_contents(FILE *f, Set *dns, Set *domains) {
4713135eae4f7b6b670a98476fe413edfa1d9f41Zbigniew Jędrzejewski-Szmek Iterator i;
4713135eae4f7b6b670a98476fe413edfa1d9f41Zbigniew Jędrzejewski-Szmek
4713135eae4f7b6b670a98476fe413edfa1d9f41Zbigniew Jędrzejewski-Szmek fputs("# This file is managed by systemd-resolved(8). Do not edit.\n#\n"
4713135eae4f7b6b670a98476fe413edfa1d9f41Zbigniew Jędrzejewski-Szmek "# Third party programs must not access this file directly, but\n"
4713135eae4f7b6b670a98476fe413edfa1d9f41Zbigniew Jędrzejewski-Szmek "# only through the symlink at /etc/resolv.conf. To manage\n"
4713135eae4f7b6b670a98476fe413edfa1d9f41Zbigniew Jędrzejewski-Szmek "# resolv.conf(5) in a different way, replace the symlink by a\n"
4713135eae4f7b6b670a98476fe413edfa1d9f41Zbigniew Jędrzejewski-Szmek "# static file or a different symlink.\n\n", f);
4713135eae4f7b6b670a98476fe413edfa1d9f41Zbigniew Jędrzejewski-Szmek
4713135eae4f7b6b670a98476fe413edfa1d9f41Zbigniew Jędrzejewski-Szmek if (set_isempty(dns))
4713135eae4f7b6b670a98476fe413edfa1d9f41Zbigniew Jędrzejewski-Szmek fputs("# No DNS servers known.\n", f);
4713135eae4f7b6b670a98476fe413edfa1d9f41Zbigniew Jędrzejewski-Szmek else {
4713135eae4f7b6b670a98476fe413edfa1d9f41Zbigniew Jędrzejewski-Szmek DnsServer *s;
4713135eae4f7b6b670a98476fe413edfa1d9f41Zbigniew Jędrzejewski-Szmek unsigned count = 0;
4713135eae4f7b6b670a98476fe413edfa1d9f41Zbigniew Jędrzejewski-Szmek
4713135eae4f7b6b670a98476fe413edfa1d9f41Zbigniew Jędrzejewski-Szmek SET_FOREACH(s, dns, i)
4713135eae4f7b6b670a98476fe413edfa1d9f41Zbigniew Jędrzejewski-Szmek write_resolv_conf_server(s, f, &count);
4713135eae4f7b6b670a98476fe413edfa1d9f41Zbigniew Jędrzejewski-Szmek }
4713135eae4f7b6b670a98476fe413edfa1d9f41Zbigniew Jędrzejewski-Szmek
4713135eae4f7b6b670a98476fe413edfa1d9f41Zbigniew Jędrzejewski-Szmek if (!set_isempty(domains)) {
4713135eae4f7b6b670a98476fe413edfa1d9f41Zbigniew Jędrzejewski-Szmek unsigned length = 0, count = 0;
4713135eae4f7b6b670a98476fe413edfa1d9f41Zbigniew Jędrzejewski-Szmek char *domain;
4713135eae4f7b6b670a98476fe413edfa1d9f41Zbigniew Jędrzejewski-Szmek
4713135eae4f7b6b670a98476fe413edfa1d9f41Zbigniew Jędrzejewski-Szmek fputs("search", f);
4713135eae4f7b6b670a98476fe413edfa1d9f41Zbigniew Jędrzejewski-Szmek SET_FOREACH(domain, domains, i)
4713135eae4f7b6b670a98476fe413edfa1d9f41Zbigniew Jędrzejewski-Szmek write_resolv_conf_search(domain, f, &count, &length);
4713135eae4f7b6b670a98476fe413edfa1d9f41Zbigniew Jędrzejewski-Szmek fputs("\n", f);
4713135eae4f7b6b670a98476fe413edfa1d9f41Zbigniew Jędrzejewski-Szmek }
4713135eae4f7b6b670a98476fe413edfa1d9f41Zbigniew Jędrzejewski-Szmek
4713135eae4f7b6b670a98476fe413edfa1d9f41Zbigniew Jędrzejewski-Szmek return fflush_and_check(f);
4713135eae4f7b6b670a98476fe413edfa1d9f41Zbigniew Jędrzejewski-Szmek}
4713135eae4f7b6b670a98476fe413edfa1d9f41Zbigniew Jędrzejewski-Szmek
4713135eae4f7b6b670a98476fe413edfa1d9f41Zbigniew Jędrzejewski-Szmek
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poetteringint manager_write_resolv_conf(Manager *m) {
4e945a6f7971fd7d1f6b2c62ee3afdaff3c95ce4Lennart Poettering static const char path[] = "/run/systemd/resolve/resolv.conf";
091a364c802e34a58f3260c9cb5db9b75c62215cTom Gundersen _cleanup_free_ char *temp_path = NULL;
091a364c802e34a58f3260c9cb5db9b75c62215cTom Gundersen _cleanup_fclose_ FILE *f = NULL;
bda2c408f8a739c19161818bcc842107f60652a2Tom Gundersen _cleanup_set_free_ Set *dns = NULL, *domains = NULL;
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering DnsServer *s;
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering Iterator i;
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering Link *l;
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering int r;
091a364c802e34a58f3260c9cb5db9b75c62215cTom Gundersen
091a364c802e34a58f3260c9cb5db9b75c62215cTom Gundersen assert(m);
091a364c802e34a58f3260c9cb5db9b75c62215cTom Gundersen
5cb36f41f01cf4b1f4395abfffd1b33116591e58Lennart Poettering /* Read the system /etc/resolv.conf first */
5cb36f41f01cf4b1f4395abfffd1b33116591e58Lennart Poettering manager_read_resolv_conf(m);
5cb36f41f01cf4b1f4395abfffd1b33116591e58Lennart Poettering
87f5a19343acf8ba697acc5a62bdb1a2b8c9eda3Lennart Poettering /* Add the full list to a set, to filter out duplicates */
d5099efc47d4e6ac60816b5381a5f607ab03f06eMichal Schmidt dns = set_new(&dns_server_hash_ops);
87f5a19343acf8ba697acc5a62bdb1a2b8c9eda3Lennart Poettering if (!dns)
87f5a19343acf8ba697acc5a62bdb1a2b8c9eda3Lennart Poettering return -ENOMEM;
87f5a19343acf8ba697acc5a62bdb1a2b8c9eda3Lennart Poettering
d5099efc47d4e6ac60816b5381a5f607ab03f06eMichal Schmidt domains = set_new(&dns_name_hash_ops);
bda2c408f8a739c19161818bcc842107f60652a2Tom Gundersen if (!domains)
bda2c408f8a739c19161818bcc842107f60652a2Tom Gundersen return -ENOMEM;
bda2c408f8a739c19161818bcc842107f60652a2Tom Gundersen
87f5a19343acf8ba697acc5a62bdb1a2b8c9eda3Lennart Poettering /* First add the system-wide servers */
87f5a19343acf8ba697acc5a62bdb1a2b8c9eda3Lennart Poettering LIST_FOREACH(servers, s, m->dns_servers) {
87f5a19343acf8ba697acc5a62bdb1a2b8c9eda3Lennart Poettering r = set_put(dns, s);
87f5a19343acf8ba697acc5a62bdb1a2b8c9eda3Lennart Poettering if (r == -EEXIST)
87f5a19343acf8ba697acc5a62bdb1a2b8c9eda3Lennart Poettering continue;
87f5a19343acf8ba697acc5a62bdb1a2b8c9eda3Lennart Poettering if (r < 0)
87f5a19343acf8ba697acc5a62bdb1a2b8c9eda3Lennart Poettering return r;
87f5a19343acf8ba697acc5a62bdb1a2b8c9eda3Lennart Poettering }
87f5a19343acf8ba697acc5a62bdb1a2b8c9eda3Lennart Poettering
bda2c408f8a739c19161818bcc842107f60652a2Tom Gundersen /* Then, add the per-link servers and domains */
bda2c408f8a739c19161818bcc842107f60652a2Tom Gundersen HASHMAP_FOREACH(l, m->links, i) {
bda2c408f8a739c19161818bcc842107f60652a2Tom Gundersen char **domain;
bda2c408f8a739c19161818bcc842107f60652a2Tom Gundersen
87f5a19343acf8ba697acc5a62bdb1a2b8c9eda3Lennart Poettering LIST_FOREACH(servers, s, l->dns_servers) {
87f5a19343acf8ba697acc5a62bdb1a2b8c9eda3Lennart Poettering r = set_put(dns, s);
87f5a19343acf8ba697acc5a62bdb1a2b8c9eda3Lennart Poettering if (r == -EEXIST)
87f5a19343acf8ba697acc5a62bdb1a2b8c9eda3Lennart Poettering continue;
87f5a19343acf8ba697acc5a62bdb1a2b8c9eda3Lennart Poettering if (r < 0)
87f5a19343acf8ba697acc5a62bdb1a2b8c9eda3Lennart Poettering return r;
87f5a19343acf8ba697acc5a62bdb1a2b8c9eda3Lennart Poettering }
87f5a19343acf8ba697acc5a62bdb1a2b8c9eda3Lennart Poettering
bda2c408f8a739c19161818bcc842107f60652a2Tom Gundersen if (!l->unicast_scope)
bda2c408f8a739c19161818bcc842107f60652a2Tom Gundersen continue;
bda2c408f8a739c19161818bcc842107f60652a2Tom Gundersen
bda2c408f8a739c19161818bcc842107f60652a2Tom Gundersen STRV_FOREACH(domain, l->unicast_scope->domains) {
bda2c408f8a739c19161818bcc842107f60652a2Tom Gundersen r = set_put(domains, *domain);
bda2c408f8a739c19161818bcc842107f60652a2Tom Gundersen if (r == -EEXIST)
bda2c408f8a739c19161818bcc842107f60652a2Tom Gundersen continue;
bda2c408f8a739c19161818bcc842107f60652a2Tom Gundersen if (r < 0)
bda2c408f8a739c19161818bcc842107f60652a2Tom Gundersen return r;
bda2c408f8a739c19161818bcc842107f60652a2Tom Gundersen }
bda2c408f8a739c19161818bcc842107f60652a2Tom Gundersen }
bda2c408f8a739c19161818bcc842107f60652a2Tom Gundersen
87f5a19343acf8ba697acc5a62bdb1a2b8c9eda3Lennart Poettering /* If we found nothing, add the fallback servers */
87f5a19343acf8ba697acc5a62bdb1a2b8c9eda3Lennart Poettering if (set_isempty(dns)) {
87f5a19343acf8ba697acc5a62bdb1a2b8c9eda3Lennart Poettering LIST_FOREACH(servers, s, m->fallback_dns_servers) {
87f5a19343acf8ba697acc5a62bdb1a2b8c9eda3Lennart Poettering r = set_put(dns, s);
87f5a19343acf8ba697acc5a62bdb1a2b8c9eda3Lennart Poettering if (r == -EEXIST)
87f5a19343acf8ba697acc5a62bdb1a2b8c9eda3Lennart Poettering continue;
87f5a19343acf8ba697acc5a62bdb1a2b8c9eda3Lennart Poettering if (r < 0)
87f5a19343acf8ba697acc5a62bdb1a2b8c9eda3Lennart Poettering return r;
87f5a19343acf8ba697acc5a62bdb1a2b8c9eda3Lennart Poettering }
87f5a19343acf8ba697acc5a62bdb1a2b8c9eda3Lennart Poettering }
87f5a19343acf8ba697acc5a62bdb1a2b8c9eda3Lennart Poettering
a5a807e63a50314e190e9166d8a453cd8dd258e3Zbigniew Jędrzejewski-Szmek r = fopen_temporary_label(path, path, &f, &temp_path);
091a364c802e34a58f3260c9cb5db9b75c62215cTom Gundersen if (r < 0)
091a364c802e34a58f3260c9cb5db9b75c62215cTom Gundersen return r;
091a364c802e34a58f3260c9cb5db9b75c62215cTom Gundersen
091a364c802e34a58f3260c9cb5db9b75c62215cTom Gundersen fchmod(fileno(f), 0644);
091a364c802e34a58f3260c9cb5db9b75c62215cTom Gundersen
4713135eae4f7b6b670a98476fe413edfa1d9f41Zbigniew Jędrzejewski-Szmek r = write_resolv_conf_contents(f, dns, domains);
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering if (r < 0)
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering goto fail;
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering if (rename(temp_path, path) < 0) {
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering r = -errno;
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering goto fail;
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering }
091a364c802e34a58f3260c9cb5db9b75c62215cTom Gundersen
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering return 0;
091a364c802e34a58f3260c9cb5db9b75c62215cTom Gundersen
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poetteringfail:
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering unlink(path);
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering unlink(temp_path);
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering return r;
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering}
091a364c802e34a58f3260c9cb5db9b75c62215cTom Gundersen
1716f6dcf54d4c181c2e2558e3d5414f54c8d9caLennart Poetteringint manager_recv(Manager *m, int fd, DnsProtocol protocol, DnsPacket **ret) {
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering _cleanup_(dns_packet_unrefp) DnsPacket *p = NULL;
1716f6dcf54d4c181c2e2558e3d5414f54c8d9caLennart Poettering union {
1716f6dcf54d4c181c2e2558e3d5414f54c8d9caLennart Poettering struct cmsghdr header; /* For alignment */
40a1eebde6be7ac3f1885147fc24e06ad1da260cDavid Herrmann uint8_t buffer[CMSG_SPACE(MAXSIZE(struct in_pktinfo, struct in6_pktinfo))
1716f6dcf54d4c181c2e2558e3d5414f54c8d9caLennart Poettering + CMSG_SPACE(int) /* ttl/hoplimit */
623a4c97b9175f95c4b1c6fc34e36c56f1e4ddbfLennart Poettering + EXTRA_CMSG_SPACE /* kernel appears to require extra buffer space */];
1716f6dcf54d4c181c2e2558e3d5414f54c8d9caLennart Poettering } control;
1716f6dcf54d4c181c2e2558e3d5414f54c8d9caLennart Poettering union sockaddr_union sa;
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering struct msghdr mh = {};
1716f6dcf54d4c181c2e2558e3d5414f54c8d9caLennart Poettering struct cmsghdr *cmsg;
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering struct iovec iov;
1716f6dcf54d4c181c2e2558e3d5414f54c8d9caLennart Poettering int ms = 0, r;
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering ssize_t l;
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering assert(m);
1716f6dcf54d4c181c2e2558e3d5414f54c8d9caLennart Poettering assert(fd >= 0);
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering assert(ret);
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering r = ioctl(fd, FIONREAD, &ms);
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering if (r < 0)
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering return -errno;
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering if (ms < 0)
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering return -EIO;
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering
1716f6dcf54d4c181c2e2558e3d5414f54c8d9caLennart Poettering r = dns_packet_new(&p, protocol, ms);
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering if (r < 0)
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering return r;
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering iov.iov_base = DNS_PACKET_DATA(p);
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering iov.iov_len = p->allocated;
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering
1716f6dcf54d4c181c2e2558e3d5414f54c8d9caLennart Poettering mh.msg_name = &sa.sa;
1716f6dcf54d4c181c2e2558e3d5414f54c8d9caLennart Poettering mh.msg_namelen = sizeof(sa);
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering mh.msg_iov = &iov;
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering mh.msg_iovlen = 1;
1716f6dcf54d4c181c2e2558e3d5414f54c8d9caLennart Poettering mh.msg_control = &control;
1716f6dcf54d4c181c2e2558e3d5414f54c8d9caLennart Poettering mh.msg_controllen = sizeof(control);
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering
a38d99451f2bf8026ec51aee91662292e823c6a8Lennart Poettering l = recvmsg(fd, &mh, 0);
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering if (l < 0) {
ad867662936a4c7ab2c7116d804c272338801231Lennart Poettering if (errno == EAGAIN || errno == EINTR)
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering return 0;
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering return -errno;
091a364c802e34a58f3260c9cb5db9b75c62215cTom Gundersen }
091a364c802e34a58f3260c9cb5db9b75c62215cTom Gundersen
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering if (l <= 0)
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering return -EIO;
091a364c802e34a58f3260c9cb5db9b75c62215cTom Gundersen
1716f6dcf54d4c181c2e2558e3d5414f54c8d9caLennart Poettering assert(!(mh.msg_flags & MSG_CTRUNC));
1716f6dcf54d4c181c2e2558e3d5414f54c8d9caLennart Poettering assert(!(mh.msg_flags & MSG_TRUNC));
1716f6dcf54d4c181c2e2558e3d5414f54c8d9caLennart Poettering
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering p->size = (size_t) l;
091a364c802e34a58f3260c9cb5db9b75c62215cTom Gundersen
1716f6dcf54d4c181c2e2558e3d5414f54c8d9caLennart Poettering p->family = sa.sa.sa_family;
623a4c97b9175f95c4b1c6fc34e36c56f1e4ddbfLennart Poettering p->ipproto = IPPROTO_UDP;
623a4c97b9175f95c4b1c6fc34e36c56f1e4ddbfLennart Poettering if (p->family == AF_INET) {
1716f6dcf54d4c181c2e2558e3d5414f54c8d9caLennart Poettering p->sender.in = sa.in.sin_addr;
623a4c97b9175f95c4b1c6fc34e36c56f1e4ddbfLennart Poettering p->sender_port = be16toh(sa.in.sin_port);
623a4c97b9175f95c4b1c6fc34e36c56f1e4ddbfLennart Poettering } else if (p->family == AF_INET6) {
1716f6dcf54d4c181c2e2558e3d5414f54c8d9caLennart Poettering p->sender.in6 = sa.in6.sin6_addr;
623a4c97b9175f95c4b1c6fc34e36c56f1e4ddbfLennart Poettering p->sender_port = be16toh(sa.in6.sin6_port);
623a4c97b9175f95c4b1c6fc34e36c56f1e4ddbfLennart Poettering p->ifindex = sa.in6.sin6_scope_id;
623a4c97b9175f95c4b1c6fc34e36c56f1e4ddbfLennart Poettering } else
1716f6dcf54d4c181c2e2558e3d5414f54c8d9caLennart Poettering return -EAFNOSUPPORT;
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering
1716f6dcf54d4c181c2e2558e3d5414f54c8d9caLennart Poettering for (cmsg = CMSG_FIRSTHDR(&mh); cmsg; cmsg = CMSG_NXTHDR(&mh, cmsg)) {
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering
1716f6dcf54d4c181c2e2558e3d5414f54c8d9caLennart Poettering if (cmsg->cmsg_level == IPPROTO_IPV6) {
1716f6dcf54d4c181c2e2558e3d5414f54c8d9caLennart Poettering assert(p->family == AF_INET6);
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering
1716f6dcf54d4c181c2e2558e3d5414f54c8d9caLennart Poettering switch (cmsg->cmsg_type) {
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering
1716f6dcf54d4c181c2e2558e3d5414f54c8d9caLennart Poettering case IPV6_PKTINFO: {
1716f6dcf54d4c181c2e2558e3d5414f54c8d9caLennart Poettering struct in6_pktinfo *i = (struct in6_pktinfo*) CMSG_DATA(cmsg);
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering
623a4c97b9175f95c4b1c6fc34e36c56f1e4ddbfLennart Poettering if (p->ifindex <= 0)
623a4c97b9175f95c4b1c6fc34e36c56f1e4ddbfLennart Poettering p->ifindex = i->ipi6_ifindex;
623a4c97b9175f95c4b1c6fc34e36c56f1e4ddbfLennart Poettering
1716f6dcf54d4c181c2e2558e3d5414f54c8d9caLennart Poettering p->destination.in6 = i->ipi6_addr;
1716f6dcf54d4c181c2e2558e3d5414f54c8d9caLennart Poettering break;
1716f6dcf54d4c181c2e2558e3d5414f54c8d9caLennart Poettering }
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering
1716f6dcf54d4c181c2e2558e3d5414f54c8d9caLennart Poettering case IPV6_HOPLIMIT:
1716f6dcf54d4c181c2e2558e3d5414f54c8d9caLennart Poettering p->ttl = *(int *) CMSG_DATA(cmsg);
1716f6dcf54d4c181c2e2558e3d5414f54c8d9caLennart Poettering break;
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering
1716f6dcf54d4c181c2e2558e3d5414f54c8d9caLennart Poettering }
1716f6dcf54d4c181c2e2558e3d5414f54c8d9caLennart Poettering } else if (cmsg->cmsg_level == IPPROTO_IP) {
1716f6dcf54d4c181c2e2558e3d5414f54c8d9caLennart Poettering assert(p->family == AF_INET);
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering
1716f6dcf54d4c181c2e2558e3d5414f54c8d9caLennart Poettering switch (cmsg->cmsg_type) {
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering
1716f6dcf54d4c181c2e2558e3d5414f54c8d9caLennart Poettering case IP_PKTINFO: {
1716f6dcf54d4c181c2e2558e3d5414f54c8d9caLennart Poettering struct in_pktinfo *i = (struct in_pktinfo*) CMSG_DATA(cmsg);
091a364c802e34a58f3260c9cb5db9b75c62215cTom Gundersen
623a4c97b9175f95c4b1c6fc34e36c56f1e4ddbfLennart Poettering if (p->ifindex <= 0)
623a4c97b9175f95c4b1c6fc34e36c56f1e4ddbfLennart Poettering p->ifindex = i->ipi_ifindex;
623a4c97b9175f95c4b1c6fc34e36c56f1e4ddbfLennart Poettering
1716f6dcf54d4c181c2e2558e3d5414f54c8d9caLennart Poettering p->destination.in = i->ipi_addr;
1716f6dcf54d4c181c2e2558e3d5414f54c8d9caLennart Poettering break;
1716f6dcf54d4c181c2e2558e3d5414f54c8d9caLennart Poettering }
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering
623a4c97b9175f95c4b1c6fc34e36c56f1e4ddbfLennart Poettering case IP_TTL:
1716f6dcf54d4c181c2e2558e3d5414f54c8d9caLennart Poettering p->ttl = *(int *) CMSG_DATA(cmsg);
1716f6dcf54d4c181c2e2558e3d5414f54c8d9caLennart Poettering break;
1716f6dcf54d4c181c2e2558e3d5414f54c8d9caLennart Poettering }
1716f6dcf54d4c181c2e2558e3d5414f54c8d9caLennart Poettering }
1716f6dcf54d4c181c2e2558e3d5414f54c8d9caLennart Poettering }
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering
623a4c97b9175f95c4b1c6fc34e36c56f1e4ddbfLennart Poettering /* The Linux kernel sets the interface index to the loopback
623a4c97b9175f95c4b1c6fc34e36c56f1e4ddbfLennart Poettering * device if the packet came from the local host since it
623a4c97b9175f95c4b1c6fc34e36c56f1e4ddbfLennart Poettering * avoids the routing table in such a case. Let's unset the
623a4c97b9175f95c4b1c6fc34e36c56f1e4ddbfLennart Poettering * interface index in such a case. */
a5f035960006556beab51c42e6948985635e261aLennart Poettering if (p->ifindex == LOOPBACK_IFINDEX)
623a4c97b9175f95c4b1c6fc34e36c56f1e4ddbfLennart Poettering p->ifindex = 0;
623a4c97b9175f95c4b1c6fc34e36c56f1e4ddbfLennart Poettering
623a4c97b9175f95c4b1c6fc34e36c56f1e4ddbfLennart Poettering /* If we don't know the interface index still, we look for the
623a4c97b9175f95c4b1c6fc34e36c56f1e4ddbfLennart Poettering * first local interface with a matching address. Yuck! */
623a4c97b9175f95c4b1c6fc34e36c56f1e4ddbfLennart Poettering if (p->ifindex <= 0)
623a4c97b9175f95c4b1c6fc34e36c56f1e4ddbfLennart Poettering p->ifindex = manager_find_ifindex(m, p->family, &p->destination);
623a4c97b9175f95c4b1c6fc34e36c56f1e4ddbfLennart Poettering
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering *ret = p;
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering p = NULL;
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering return 1;
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering}
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering
1716f6dcf54d4c181c2e2558e3d5414f54c8d9caLennart Poetteringstatic int on_dns_packet(sd_event_source *s, int fd, uint32_t revents, void *userdata) {
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering _cleanup_(dns_packet_unrefp) DnsPacket *p = NULL;
ec2c5e4398f9d65e5dfe61530f2556224733d1e6Lennart Poettering DnsTransaction *t = NULL;
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering Manager *m = userdata;
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering int r;
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering
1716f6dcf54d4c181c2e2558e3d5414f54c8d9caLennart Poettering r = manager_recv(m, fd, DNS_PROTOCOL_DNS, &p);
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering if (r <= 0)
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering return r;
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering
623a4c97b9175f95c4b1c6fc34e36c56f1e4ddbfLennart Poettering if (dns_packet_validate_reply(p) > 0) {
ec2c5e4398f9d65e5dfe61530f2556224733d1e6Lennart Poettering t = hashmap_get(m->dns_transactions, UINT_TO_PTR(DNS_PACKET_ID(p)));
1716f6dcf54d4c181c2e2558e3d5414f54c8d9caLennart Poettering if (!t)
1716f6dcf54d4c181c2e2558e3d5414f54c8d9caLennart Poettering return 0;
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering
ec2c5e4398f9d65e5dfe61530f2556224733d1e6Lennart Poettering dns_transaction_process_reply(t, p);
623a4c97b9175f95c4b1c6fc34e36c56f1e4ddbfLennart Poettering
1716f6dcf54d4c181c2e2558e3d5414f54c8d9caLennart Poettering } else
623a4c97b9175f95c4b1c6fc34e36c56f1e4ddbfLennart Poettering log_debug("Invalid DNS packet.");
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering
ad867662936a4c7ab2c7116d804c272338801231Lennart Poettering return 0;
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering}
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poetteringint manager_dns_ipv4_fd(Manager *m) {
1716f6dcf54d4c181c2e2558e3d5414f54c8d9caLennart Poettering const int one = 1;
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering int r;
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering
091a364c802e34a58f3260c9cb5db9b75c62215cTom Gundersen assert(m);
091a364c802e34a58f3260c9cb5db9b75c62215cTom Gundersen
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering if (m->dns_ipv4_fd >= 0)
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering return m->dns_ipv4_fd;
091a364c802e34a58f3260c9cb5db9b75c62215cTom Gundersen
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering m->dns_ipv4_fd = socket(AF_INET, SOCK_DGRAM|SOCK_CLOEXEC|SOCK_NONBLOCK, 0);
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering if (m->dns_ipv4_fd < 0)
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering return -errno;
091a364c802e34a58f3260c9cb5db9b75c62215cTom Gundersen
1716f6dcf54d4c181c2e2558e3d5414f54c8d9caLennart Poettering r = setsockopt(m->dns_ipv4_fd, IPPROTO_IP, IP_PKTINFO, &one, sizeof(one));
1716f6dcf54d4c181c2e2558e3d5414f54c8d9caLennart Poettering if (r < 0) {
1716f6dcf54d4c181c2e2558e3d5414f54c8d9caLennart Poettering r = -errno;
1716f6dcf54d4c181c2e2558e3d5414f54c8d9caLennart Poettering goto fail;
1716f6dcf54d4c181c2e2558e3d5414f54c8d9caLennart Poettering }
1716f6dcf54d4c181c2e2558e3d5414f54c8d9caLennart Poettering
1716f6dcf54d4c181c2e2558e3d5414f54c8d9caLennart Poettering r = sd_event_add_io(m->event, &m->dns_ipv4_event_source, m->dns_ipv4_fd, EPOLLIN, on_dns_packet, m);
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering if (r < 0)
1716f6dcf54d4c181c2e2558e3d5414f54c8d9caLennart Poettering goto fail;
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering return m->dns_ipv4_fd;
1716f6dcf54d4c181c2e2558e3d5414f54c8d9caLennart Poettering
1716f6dcf54d4c181c2e2558e3d5414f54c8d9caLennart Poetteringfail:
1716f6dcf54d4c181c2e2558e3d5414f54c8d9caLennart Poettering m->dns_ipv4_fd = safe_close(m->dns_ipv4_fd);
1716f6dcf54d4c181c2e2558e3d5414f54c8d9caLennart Poettering return r;
091a364c802e34a58f3260c9cb5db9b75c62215cTom Gundersen}
091a364c802e34a58f3260c9cb5db9b75c62215cTom Gundersen
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poetteringint manager_dns_ipv6_fd(Manager *m) {
1716f6dcf54d4c181c2e2558e3d5414f54c8d9caLennart Poettering const int one = 1;
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering int r;
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering assert(m);
091a364c802e34a58f3260c9cb5db9b75c62215cTom Gundersen
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering if (m->dns_ipv6_fd >= 0)
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering return m->dns_ipv6_fd;
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering m->dns_ipv6_fd = socket(AF_INET6, SOCK_DGRAM|SOCK_CLOEXEC|SOCK_NONBLOCK, 0);
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering if (m->dns_ipv6_fd < 0)
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering return -errno;
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering
1716f6dcf54d4c181c2e2558e3d5414f54c8d9caLennart Poettering r = setsockopt(m->dns_ipv6_fd, IPPROTO_IPV6, IPV6_RECVPKTINFO, &one, sizeof(one));
1716f6dcf54d4c181c2e2558e3d5414f54c8d9caLennart Poettering if (r < 0) {
1716f6dcf54d4c181c2e2558e3d5414f54c8d9caLennart Poettering r = -errno;
1716f6dcf54d4c181c2e2558e3d5414f54c8d9caLennart Poettering goto fail;
1716f6dcf54d4c181c2e2558e3d5414f54c8d9caLennart Poettering }
1716f6dcf54d4c181c2e2558e3d5414f54c8d9caLennart Poettering
1716f6dcf54d4c181c2e2558e3d5414f54c8d9caLennart Poettering r = sd_event_add_io(m->event, &m->dns_ipv6_event_source, m->dns_ipv6_fd, EPOLLIN, on_dns_packet, m);
091a364c802e34a58f3260c9cb5db9b75c62215cTom Gundersen if (r < 0)
1716f6dcf54d4c181c2e2558e3d5414f54c8d9caLennart Poettering goto fail;
091a364c802e34a58f3260c9cb5db9b75c62215cTom Gundersen
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering return m->dns_ipv6_fd;
1716f6dcf54d4c181c2e2558e3d5414f54c8d9caLennart Poettering
1716f6dcf54d4c181c2e2558e3d5414f54c8d9caLennart Poetteringfail:
1716f6dcf54d4c181c2e2558e3d5414f54c8d9caLennart Poettering m->dns_ipv6_fd = safe_close(m->dns_ipv6_fd);
1716f6dcf54d4c181c2e2558e3d5414f54c8d9caLennart Poettering return r;
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering}
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poetteringstatic int sendmsg_loop(int fd, struct msghdr *mh, int flags) {
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering int r;
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering assert(fd >= 0);
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering assert(mh);
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering for (;;) {
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering if (sendmsg(fd, mh, flags) >= 0)
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering return 0;
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering if (errno == EINTR)
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering continue;
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering if (errno != EAGAIN)
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering return -errno;
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering r = fd_wait_for_event(fd, POLLOUT, SEND_TIMEOUT_USEC);
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering if (r < 0)
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering return r;
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering if (r == 0)
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering return -ETIMEDOUT;
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering }
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering}
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering
623a4c97b9175f95c4b1c6fc34e36c56f1e4ddbfLennart Poetteringstatic int manager_ipv4_send(Manager *m, int fd, int ifindex, const struct in_addr *addr, uint16_t port, DnsPacket *p) {
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering union sockaddr_union sa = {
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering .in.sin_family = AF_INET,
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering };
1716f6dcf54d4c181c2e2558e3d5414f54c8d9caLennart Poettering union {
1716f6dcf54d4c181c2e2558e3d5414f54c8d9caLennart Poettering struct cmsghdr header; /* For alignment */
1716f6dcf54d4c181c2e2558e3d5414f54c8d9caLennart Poettering uint8_t buffer[CMSG_SPACE(sizeof(struct in_pktinfo))];
1716f6dcf54d4c181c2e2558e3d5414f54c8d9caLennart Poettering } control;
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering struct msghdr mh = {};
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering struct iovec iov;
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering assert(m);
1716f6dcf54d4c181c2e2558e3d5414f54c8d9caLennart Poettering assert(fd >= 0);
1716f6dcf54d4c181c2e2558e3d5414f54c8d9caLennart Poettering assert(addr);
1716f6dcf54d4c181c2e2558e3d5414f54c8d9caLennart Poettering assert(port > 0);
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering assert(p);
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering iov.iov_base = DNS_PACKET_DATA(p);
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering iov.iov_len = p->size;
091a364c802e34a58f3260c9cb5db9b75c62215cTom Gundersen
1716f6dcf54d4c181c2e2558e3d5414f54c8d9caLennart Poettering sa.in.sin_addr = *addr;
1716f6dcf54d4c181c2e2558e3d5414f54c8d9caLennart Poettering sa.in.sin_port = htobe16(port),
091a364c802e34a58f3260c9cb5db9b75c62215cTom Gundersen
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering mh.msg_iov = &iov;
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering mh.msg_iovlen = 1;
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering mh.msg_name = &sa.sa;
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering mh.msg_namelen = sizeof(sa.in);
091a364c802e34a58f3260c9cb5db9b75c62215cTom Gundersen
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering if (ifindex > 0) {
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering struct cmsghdr *cmsg;
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering struct in_pktinfo *pi;
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering zero(control);
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering
1716f6dcf54d4c181c2e2558e3d5414f54c8d9caLennart Poettering mh.msg_control = &control;
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering mh.msg_controllen = CMSG_LEN(sizeof(struct in_pktinfo));
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering cmsg = CMSG_FIRSTHDR(&mh);
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering cmsg->cmsg_len = mh.msg_controllen;
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering cmsg->cmsg_level = IPPROTO_IP;
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering cmsg->cmsg_type = IP_PKTINFO;
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering pi = (struct in_pktinfo*) CMSG_DATA(cmsg);
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering pi->ipi_ifindex = ifindex;
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering }
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering return sendmsg_loop(fd, &mh, 0);
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering}
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering
623a4c97b9175f95c4b1c6fc34e36c56f1e4ddbfLennart Poetteringstatic int manager_ipv6_send(Manager *m, int fd, int ifindex, const struct in6_addr *addr, uint16_t port, DnsPacket *p) {
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering union sockaddr_union sa = {
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering .in6.sin6_family = AF_INET6,
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering };
1716f6dcf54d4c181c2e2558e3d5414f54c8d9caLennart Poettering union {
1716f6dcf54d4c181c2e2558e3d5414f54c8d9caLennart Poettering struct cmsghdr header; /* For alignment */
1716f6dcf54d4c181c2e2558e3d5414f54c8d9caLennart Poettering uint8_t buffer[CMSG_SPACE(sizeof(struct in6_pktinfo))];
1716f6dcf54d4c181c2e2558e3d5414f54c8d9caLennart Poettering } control;
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering struct msghdr mh = {};
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering struct iovec iov;
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering assert(m);
1716f6dcf54d4c181c2e2558e3d5414f54c8d9caLennart Poettering assert(fd >= 0);
1716f6dcf54d4c181c2e2558e3d5414f54c8d9caLennart Poettering assert(addr);
1716f6dcf54d4c181c2e2558e3d5414f54c8d9caLennart Poettering assert(port > 0);
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering assert(p);
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering iov.iov_base = DNS_PACKET_DATA(p);
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering iov.iov_len = p->size;
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering
1716f6dcf54d4c181c2e2558e3d5414f54c8d9caLennart Poettering sa.in6.sin6_addr = *addr;
1716f6dcf54d4c181c2e2558e3d5414f54c8d9caLennart Poettering sa.in6.sin6_port = htobe16(port),
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering sa.in6.sin6_scope_id = ifindex;
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering mh.msg_iov = &iov;
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering mh.msg_iovlen = 1;
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering mh.msg_name = &sa.sa;
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering mh.msg_namelen = sizeof(sa.in6);
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering if (ifindex > 0) {
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering struct cmsghdr *cmsg;
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering struct in6_pktinfo *pi;
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering zero(control);
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering
1716f6dcf54d4c181c2e2558e3d5414f54c8d9caLennart Poettering mh.msg_control = &control;
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering mh.msg_controllen = CMSG_LEN(sizeof(struct in6_pktinfo));
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering cmsg = CMSG_FIRSTHDR(&mh);
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering cmsg->cmsg_len = mh.msg_controllen;
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering cmsg->cmsg_level = IPPROTO_IPV6;
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering cmsg->cmsg_type = IPV6_PKTINFO;
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering pi = (struct in6_pktinfo*) CMSG_DATA(cmsg);
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering pi->ipi6_ifindex = ifindex;
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering }
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering return sendmsg_loop(fd, &mh, 0);
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering}
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering
623a4c97b9175f95c4b1c6fc34e36c56f1e4ddbfLennart Poetteringint manager_send(Manager *m, int fd, int ifindex, int family, const union in_addr_union *addr, uint16_t port, DnsPacket *p) {
1716f6dcf54d4c181c2e2558e3d5414f54c8d9caLennart Poettering assert(m);
1716f6dcf54d4c181c2e2558e3d5414f54c8d9caLennart Poettering assert(fd >= 0);
1716f6dcf54d4c181c2e2558e3d5414f54c8d9caLennart Poettering assert(addr);
1716f6dcf54d4c181c2e2558e3d5414f54c8d9caLennart Poettering assert(port > 0);
1716f6dcf54d4c181c2e2558e3d5414f54c8d9caLennart Poettering assert(p);
1716f6dcf54d4c181c2e2558e3d5414f54c8d9caLennart Poettering
a2a416f768e2aa7db5b975cd50eb19237cac9cceLennart Poettering log_debug("Sending %s packet with id %u on interface %i/%s", DNS_PACKET_QR(p) ? "response" : "query", DNS_PACKET_ID(p), ifindex, af_to_name(family));
a2a416f768e2aa7db5b975cd50eb19237cac9cceLennart Poettering
1716f6dcf54d4c181c2e2558e3d5414f54c8d9caLennart Poettering if (family == AF_INET)
1716f6dcf54d4c181c2e2558e3d5414f54c8d9caLennart Poettering return manager_ipv4_send(m, fd, ifindex, &addr->in, port, p);
1716f6dcf54d4c181c2e2558e3d5414f54c8d9caLennart Poettering else if (family == AF_INET6)
1716f6dcf54d4c181c2e2558e3d5414f54c8d9caLennart Poettering return manager_ipv6_send(m, fd, ifindex, &addr->in6, port, p);
1716f6dcf54d4c181c2e2558e3d5414f54c8d9caLennart Poettering
1716f6dcf54d4c181c2e2558e3d5414f54c8d9caLennart Poettering return -EAFNOSUPPORT;
1716f6dcf54d4c181c2e2558e3d5414f54c8d9caLennart Poettering}
1716f6dcf54d4c181c2e2558e3d5414f54c8d9caLennart Poettering
2c27fbca2d88214bd305272308a370a962818f1eLennart PoetteringDnsServer* manager_find_dns_server(Manager *m, int family, const union in_addr_union *in_addr) {
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering DnsServer *s;
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering assert(m);
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering assert(in_addr);
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering
4e945a6f7971fd7d1f6b2c62ee3afdaff3c95ce4Lennart Poettering LIST_FOREACH(servers, s, m->dns_servers)
5cb36f41f01cf4b1f4395abfffd1b33116591e58Lennart Poettering if (s->family == family && in_addr_equal(family, &s->address, in_addr) > 0)
2c27fbca2d88214bd305272308a370a962818f1eLennart Poettering return s;
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering
4e945a6f7971fd7d1f6b2c62ee3afdaff3c95ce4Lennart Poettering LIST_FOREACH(servers, s, m->fallback_dns_servers)
5cb36f41f01cf4b1f4395abfffd1b33116591e58Lennart Poettering if (s->family == family && in_addr_equal(family, &s->address, in_addr) > 0)
2c27fbca2d88214bd305272308a370a962818f1eLennart Poettering return s;
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering
2c27fbca2d88214bd305272308a370a962818f1eLennart Poettering return NULL;
4e945a6f7971fd7d1f6b2c62ee3afdaff3c95ce4Lennart Poettering}
4e945a6f7971fd7d1f6b2c62ee3afdaff3c95ce4Lennart Poettering
2c27fbca2d88214bd305272308a370a962818f1eLennart PoetteringDnsServer *manager_set_dns_server(Manager *m, DnsServer *s) {
4e945a6f7971fd7d1f6b2c62ee3afdaff3c95ce4Lennart Poettering assert(m);
4e945a6f7971fd7d1f6b2c62ee3afdaff3c95ce4Lennart Poettering
4e945a6f7971fd7d1f6b2c62ee3afdaff3c95ce4Lennart Poettering if (m->current_dns_server == s)
4e945a6f7971fd7d1f6b2c62ee3afdaff3c95ce4Lennart Poettering return s;
4e945a6f7971fd7d1f6b2c62ee3afdaff3c95ce4Lennart Poettering
4e945a6f7971fd7d1f6b2c62ee3afdaff3c95ce4Lennart Poettering if (s) {
4e945a6f7971fd7d1f6b2c62ee3afdaff3c95ce4Lennart Poettering _cleanup_free_ char *ip = NULL;
4e945a6f7971fd7d1f6b2c62ee3afdaff3c95ce4Lennart Poettering
4e945a6f7971fd7d1f6b2c62ee3afdaff3c95ce4Lennart Poettering in_addr_to_string(s->family, &s->address, &ip);
4e945a6f7971fd7d1f6b2c62ee3afdaff3c95ce4Lennart Poettering log_info("Switching to system DNS server %s.", strna(ip));
2c27fbca2d88214bd305272308a370a962818f1eLennart Poettering }
4e945a6f7971fd7d1f6b2c62ee3afdaff3c95ce4Lennart Poettering
4e945a6f7971fd7d1f6b2c62ee3afdaff3c95ce4Lennart Poettering m->current_dns_server = s;
2c27fbca2d88214bd305272308a370a962818f1eLennart Poettering
2c27fbca2d88214bd305272308a370a962818f1eLennart Poettering if (m->unicast_scope)
2c27fbca2d88214bd305272308a370a962818f1eLennart Poettering dns_cache_flush(&m->unicast_scope->cache);
2c27fbca2d88214bd305272308a370a962818f1eLennart Poettering
4e945a6f7971fd7d1f6b2c62ee3afdaff3c95ce4Lennart Poettering return s;
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering}
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart PoetteringDnsServer *manager_get_dns_server(Manager *m) {
4e945a6f7971fd7d1f6b2c62ee3afdaff3c95ce4Lennart Poettering Link *l;
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering assert(m);
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering
5cb36f41f01cf4b1f4395abfffd1b33116591e58Lennart Poettering /* Try to read updates resolv.conf */
5cb36f41f01cf4b1f4395abfffd1b33116591e58Lennart Poettering manager_read_resolv_conf(m);
5cb36f41f01cf4b1f4395abfffd1b33116591e58Lennart Poettering
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering if (!m->current_dns_server)
4e945a6f7971fd7d1f6b2c62ee3afdaff3c95ce4Lennart Poettering manager_set_dns_server(m, m->dns_servers);
4e945a6f7971fd7d1f6b2c62ee3afdaff3c95ce4Lennart Poettering
4e945a6f7971fd7d1f6b2c62ee3afdaff3c95ce4Lennart Poettering if (!m->current_dns_server) {
4e945a6f7971fd7d1f6b2c62ee3afdaff3c95ce4Lennart Poettering bool found = false;
4e945a6f7971fd7d1f6b2c62ee3afdaff3c95ce4Lennart Poettering Iterator i;
4e945a6f7971fd7d1f6b2c62ee3afdaff3c95ce4Lennart Poettering
4e945a6f7971fd7d1f6b2c62ee3afdaff3c95ce4Lennart Poettering /* No DNS servers configured, let's see if there are
4e945a6f7971fd7d1f6b2c62ee3afdaff3c95ce4Lennart Poettering * any on any links. If not, we use the fallback
4e945a6f7971fd7d1f6b2c62ee3afdaff3c95ce4Lennart Poettering * servers */
4e945a6f7971fd7d1f6b2c62ee3afdaff3c95ce4Lennart Poettering
4e945a6f7971fd7d1f6b2c62ee3afdaff3c95ce4Lennart Poettering HASHMAP_FOREACH(l, m->links, i)
4e945a6f7971fd7d1f6b2c62ee3afdaff3c95ce4Lennart Poettering if (l->dns_servers) {
4e945a6f7971fd7d1f6b2c62ee3afdaff3c95ce4Lennart Poettering found = true;
4e945a6f7971fd7d1f6b2c62ee3afdaff3c95ce4Lennart Poettering break;
4e945a6f7971fd7d1f6b2c62ee3afdaff3c95ce4Lennart Poettering }
4e945a6f7971fd7d1f6b2c62ee3afdaff3c95ce4Lennart Poettering
4e945a6f7971fd7d1f6b2c62ee3afdaff3c95ce4Lennart Poettering if (!found)
4e945a6f7971fd7d1f6b2c62ee3afdaff3c95ce4Lennart Poettering manager_set_dns_server(m, m->fallback_dns_servers);
4e945a6f7971fd7d1f6b2c62ee3afdaff3c95ce4Lennart Poettering }
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering return m->current_dns_server;
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering}
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poetteringvoid manager_next_dns_server(Manager *m) {
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering assert(m);
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering
4e945a6f7971fd7d1f6b2c62ee3afdaff3c95ce4Lennart Poettering /* If there's currently no DNS server set, then the next
4e945a6f7971fd7d1f6b2c62ee3afdaff3c95ce4Lennart Poettering * manager_get_dns_server() will find one */
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering if (!m->current_dns_server)
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering return;
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering
4e945a6f7971fd7d1f6b2c62ee3afdaff3c95ce4Lennart Poettering /* Change to the next one */
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering if (m->current_dns_server->servers_next) {
4e945a6f7971fd7d1f6b2c62ee3afdaff3c95ce4Lennart Poettering manager_set_dns_server(m, m->current_dns_server->servers_next);
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering return;
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering }
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering
4e945a6f7971fd7d1f6b2c62ee3afdaff3c95ce4Lennart Poettering /* If there was no next one, then start from the beginning of
4e945a6f7971fd7d1f6b2c62ee3afdaff3c95ce4Lennart Poettering * the list */
4e945a6f7971fd7d1f6b2c62ee3afdaff3c95ce4Lennart Poettering if (m->current_dns_server->type == DNS_SERVER_FALLBACK)
4e945a6f7971fd7d1f6b2c62ee3afdaff3c95ce4Lennart Poettering manager_set_dns_server(m, m->fallback_dns_servers);
4e945a6f7971fd7d1f6b2c62ee3afdaff3c95ce4Lennart Poettering else
4e945a6f7971fd7d1f6b2c62ee3afdaff3c95ce4Lennart Poettering manager_set_dns_server(m, m->dns_servers);
091a364c802e34a58f3260c9cb5db9b75c62215cTom Gundersen}
e1c959948c0e31d6997bcdfbabfbd077784b2baeLennart Poettering
e1c959948c0e31d6997bcdfbabfbd077784b2baeLennart Poetteringuint32_t manager_find_mtu(Manager *m) {
e1c959948c0e31d6997bcdfbabfbd077784b2baeLennart Poettering uint32_t mtu = 0;
e1c959948c0e31d6997bcdfbabfbd077784b2baeLennart Poettering Link *l;
e1c959948c0e31d6997bcdfbabfbd077784b2baeLennart Poettering Iterator i;
e1c959948c0e31d6997bcdfbabfbd077784b2baeLennart Poettering
e1c959948c0e31d6997bcdfbabfbd077784b2baeLennart Poettering /* If we don't know on which link a DNS packet would be
e1c959948c0e31d6997bcdfbabfbd077784b2baeLennart Poettering * delivered, let's find the largest MTU that works on all
e1c959948c0e31d6997bcdfbabfbd077784b2baeLennart Poettering * interfaces we know of */
e1c959948c0e31d6997bcdfbabfbd077784b2baeLennart Poettering
e1c959948c0e31d6997bcdfbabfbd077784b2baeLennart Poettering HASHMAP_FOREACH(l, m->links, i) {
e1c959948c0e31d6997bcdfbabfbd077784b2baeLennart Poettering if (l->mtu <= 0)
e1c959948c0e31d6997bcdfbabfbd077784b2baeLennart Poettering continue;
e1c959948c0e31d6997bcdfbabfbd077784b2baeLennart Poettering
e1c959948c0e31d6997bcdfbabfbd077784b2baeLennart Poettering if (mtu <= 0 || l->mtu < mtu)
e1c959948c0e31d6997bcdfbabfbd077784b2baeLennart Poettering mtu = l->mtu;
e1c959948c0e31d6997bcdfbabfbd077784b2baeLennart Poettering }
e1c959948c0e31d6997bcdfbabfbd077784b2baeLennart Poettering
e1c959948c0e31d6997bcdfbabfbd077784b2baeLennart Poettering return mtu;
e1c959948c0e31d6997bcdfbabfbd077784b2baeLennart Poettering}
1716f6dcf54d4c181c2e2558e3d5414f54c8d9caLennart Poettering
1716f6dcf54d4c181c2e2558e3d5414f54c8d9caLennart Poetteringstatic int on_llmnr_packet(sd_event_source *s, int fd, uint32_t revents, void *userdata) {
1716f6dcf54d4c181c2e2558e3d5414f54c8d9caLennart Poettering _cleanup_(dns_packet_unrefp) DnsPacket *p = NULL;
ec2c5e4398f9d65e5dfe61530f2556224733d1e6Lennart Poettering DnsTransaction *t = NULL;
1716f6dcf54d4c181c2e2558e3d5414f54c8d9caLennart Poettering Manager *m = userdata;
a407657425a3e47fd2b559cd3bc800f791303f63Lennart Poettering DnsScope *scope;
1716f6dcf54d4c181c2e2558e3d5414f54c8d9caLennart Poettering int r;
1716f6dcf54d4c181c2e2558e3d5414f54c8d9caLennart Poettering
1716f6dcf54d4c181c2e2558e3d5414f54c8d9caLennart Poettering r = manager_recv(m, fd, DNS_PROTOCOL_LLMNR, &p);
1716f6dcf54d4c181c2e2558e3d5414f54c8d9caLennart Poettering if (r <= 0)
1716f6dcf54d4c181c2e2558e3d5414f54c8d9caLennart Poettering return r;
1716f6dcf54d4c181c2e2558e3d5414f54c8d9caLennart Poettering
a407657425a3e47fd2b559cd3bc800f791303f63Lennart Poettering scope = manager_find_scope(m, p);
a407657425a3e47fd2b559cd3bc800f791303f63Lennart Poettering if (!scope) {
a407657425a3e47fd2b559cd3bc800f791303f63Lennart Poettering log_warning("Got LLMNR UDP packet on unknown scope. Ignoring.");
a407657425a3e47fd2b559cd3bc800f791303f63Lennart Poettering return 0;
a407657425a3e47fd2b559cd3bc800f791303f63Lennart Poettering }
a407657425a3e47fd2b559cd3bc800f791303f63Lennart Poettering
623a4c97b9175f95c4b1c6fc34e36c56f1e4ddbfLennart Poettering if (dns_packet_validate_reply(p) > 0) {
a2a416f768e2aa7db5b975cd50eb19237cac9cceLennart Poettering log_debug("Got reply packet for id %u", DNS_PACKET_ID(p));
a2a416f768e2aa7db5b975cd50eb19237cac9cceLennart Poettering
a407657425a3e47fd2b559cd3bc800f791303f63Lennart Poettering dns_scope_check_conflicts(scope, p);
623a4c97b9175f95c4b1c6fc34e36c56f1e4ddbfLennart Poettering
a407657425a3e47fd2b559cd3bc800f791303f63Lennart Poettering t = hashmap_get(m->dns_transactions, UINT_TO_PTR(DNS_PACKET_ID(p)));
a407657425a3e47fd2b559cd3bc800f791303f63Lennart Poettering if (t)
a407657425a3e47fd2b559cd3bc800f791303f63Lennart Poettering dns_transaction_process_reply(t, p);
623a4c97b9175f95c4b1c6fc34e36c56f1e4ddbfLennart Poettering
a407657425a3e47fd2b559cd3bc800f791303f63Lennart Poettering } else if (dns_packet_validate_query(p) > 0) {
a407657425a3e47fd2b559cd3bc800f791303f63Lennart Poettering log_debug("Got query packet for id %u", DNS_PACKET_ID(p));
623a4c97b9175f95c4b1c6fc34e36c56f1e4ddbfLennart Poettering
a407657425a3e47fd2b559cd3bc800f791303f63Lennart Poettering dns_scope_process_query(scope, NULL, p);
623a4c97b9175f95c4b1c6fc34e36c56f1e4ddbfLennart Poettering } else
a407657425a3e47fd2b559cd3bc800f791303f63Lennart Poettering log_debug("Invalid LLMNR UDP packet.");
1716f6dcf54d4c181c2e2558e3d5414f54c8d9caLennart Poettering
1716f6dcf54d4c181c2e2558e3d5414f54c8d9caLennart Poettering return 0;
1716f6dcf54d4c181c2e2558e3d5414f54c8d9caLennart Poettering}
1716f6dcf54d4c181c2e2558e3d5414f54c8d9caLennart Poettering
1716f6dcf54d4c181c2e2558e3d5414f54c8d9caLennart Poetteringint manager_llmnr_ipv4_udp_fd(Manager *m) {
1716f6dcf54d4c181c2e2558e3d5414f54c8d9caLennart Poettering union sockaddr_union sa = {
1716f6dcf54d4c181c2e2558e3d5414f54c8d9caLennart Poettering .in.sin_family = AF_INET,
1716f6dcf54d4c181c2e2558e3d5414f54c8d9caLennart Poettering .in.sin_port = htobe16(5355),
1716f6dcf54d4c181c2e2558e3d5414f54c8d9caLennart Poettering };
bf3f1271e2cc0c22b11c8a805a997578dabe9191Lennart Poettering static const int one = 1, pmtu = IP_PMTUDISC_DONT, ttl = 255;
1716f6dcf54d4c181c2e2558e3d5414f54c8d9caLennart Poettering int r;
1716f6dcf54d4c181c2e2558e3d5414f54c8d9caLennart Poettering
1716f6dcf54d4c181c2e2558e3d5414f54c8d9caLennart Poettering assert(m);
1716f6dcf54d4c181c2e2558e3d5414f54c8d9caLennart Poettering
1716f6dcf54d4c181c2e2558e3d5414f54c8d9caLennart Poettering if (m->llmnr_ipv4_udp_fd >= 0)
1716f6dcf54d4c181c2e2558e3d5414f54c8d9caLennart Poettering return m->llmnr_ipv4_udp_fd;
1716f6dcf54d4c181c2e2558e3d5414f54c8d9caLennart Poettering
1716f6dcf54d4c181c2e2558e3d5414f54c8d9caLennart Poettering m->llmnr_ipv4_udp_fd = socket(AF_INET, SOCK_DGRAM|SOCK_CLOEXEC|SOCK_NONBLOCK, 0);
1716f6dcf54d4c181c2e2558e3d5414f54c8d9caLennart Poettering if (m->llmnr_ipv4_udp_fd < 0)
1716f6dcf54d4c181c2e2558e3d5414f54c8d9caLennart Poettering return -errno;
1716f6dcf54d4c181c2e2558e3d5414f54c8d9caLennart Poettering
bf3f1271e2cc0c22b11c8a805a997578dabe9191Lennart Poettering /* RFC 4795, section 2.5 recommends setting the TTL of UDP packets to 255. */
bf3f1271e2cc0c22b11c8a805a997578dabe9191Lennart Poettering r = setsockopt(m->llmnr_ipv4_udp_fd, IPPROTO_IP, IP_TTL, &ttl, sizeof(ttl));
1716f6dcf54d4c181c2e2558e3d5414f54c8d9caLennart Poettering if (r < 0) {
1716f6dcf54d4c181c2e2558e3d5414f54c8d9caLennart Poettering r = -errno;
1716f6dcf54d4c181c2e2558e3d5414f54c8d9caLennart Poettering goto fail;
1716f6dcf54d4c181c2e2558e3d5414f54c8d9caLennart Poettering }
1716f6dcf54d4c181c2e2558e3d5414f54c8d9caLennart Poettering
bf3f1271e2cc0c22b11c8a805a997578dabe9191Lennart Poettering r = setsockopt(m->llmnr_ipv4_udp_fd, IPPROTO_IP, IP_MULTICAST_TTL, &ttl, sizeof(ttl));
1716f6dcf54d4c181c2e2558e3d5414f54c8d9caLennart Poettering if (r < 0) {
1716f6dcf54d4c181c2e2558e3d5414f54c8d9caLennart Poettering r = -errno;
1716f6dcf54d4c181c2e2558e3d5414f54c8d9caLennart Poettering goto fail;
1716f6dcf54d4c181c2e2558e3d5414f54c8d9caLennart Poettering }
1716f6dcf54d4c181c2e2558e3d5414f54c8d9caLennart Poettering
1716f6dcf54d4c181c2e2558e3d5414f54c8d9caLennart Poettering r = setsockopt(m->llmnr_ipv4_udp_fd, IPPROTO_IP, IP_MULTICAST_LOOP, &one, sizeof(one));
1716f6dcf54d4c181c2e2558e3d5414f54c8d9caLennart Poettering if (r < 0) {
1716f6dcf54d4c181c2e2558e3d5414f54c8d9caLennart Poettering r = -errno;
1716f6dcf54d4c181c2e2558e3d5414f54c8d9caLennart Poettering goto fail;
1716f6dcf54d4c181c2e2558e3d5414f54c8d9caLennart Poettering }
1716f6dcf54d4c181c2e2558e3d5414f54c8d9caLennart Poettering
1716f6dcf54d4c181c2e2558e3d5414f54c8d9caLennart Poettering r = setsockopt(m->llmnr_ipv4_udp_fd, SOL_SOCKET, SO_REUSEADDR, &one, sizeof(one));
1716f6dcf54d4c181c2e2558e3d5414f54c8d9caLennart Poettering if (r < 0) {
1716f6dcf54d4c181c2e2558e3d5414f54c8d9caLennart Poettering r = -errno;
1716f6dcf54d4c181c2e2558e3d5414f54c8d9caLennart Poettering goto fail;
1716f6dcf54d4c181c2e2558e3d5414f54c8d9caLennart Poettering }
1716f6dcf54d4c181c2e2558e3d5414f54c8d9caLennart Poettering
1716f6dcf54d4c181c2e2558e3d5414f54c8d9caLennart Poettering r = setsockopt(m->llmnr_ipv4_udp_fd, IPPROTO_IP, IP_PKTINFO, &one, sizeof(one));
1716f6dcf54d4c181c2e2558e3d5414f54c8d9caLennart Poettering if (r < 0) {
1716f6dcf54d4c181c2e2558e3d5414f54c8d9caLennart Poettering r = -errno;
1716f6dcf54d4c181c2e2558e3d5414f54c8d9caLennart Poettering goto fail;
1716f6dcf54d4c181c2e2558e3d5414f54c8d9caLennart Poettering }
1716f6dcf54d4c181c2e2558e3d5414f54c8d9caLennart Poettering
1716f6dcf54d4c181c2e2558e3d5414f54c8d9caLennart Poettering r = setsockopt(m->llmnr_ipv4_udp_fd, IPPROTO_IP, IP_RECVTTL, &one, sizeof(one));
1716f6dcf54d4c181c2e2558e3d5414f54c8d9caLennart Poettering if (r < 0) {
1716f6dcf54d4c181c2e2558e3d5414f54c8d9caLennart Poettering r = -errno;
1716f6dcf54d4c181c2e2558e3d5414f54c8d9caLennart Poettering goto fail;
1716f6dcf54d4c181c2e2558e3d5414f54c8d9caLennart Poettering }
1716f6dcf54d4c181c2e2558e3d5414f54c8d9caLennart Poettering
1716f6dcf54d4c181c2e2558e3d5414f54c8d9caLennart Poettering /* Disable Don't-Fragment bit in the IP header */
1716f6dcf54d4c181c2e2558e3d5414f54c8d9caLennart Poettering r = setsockopt(m->llmnr_ipv4_udp_fd, IPPROTO_IP, IP_MTU_DISCOVER, &pmtu, sizeof(pmtu));
1716f6dcf54d4c181c2e2558e3d5414f54c8d9caLennart Poettering if (r < 0) {
1716f6dcf54d4c181c2e2558e3d5414f54c8d9caLennart Poettering r = -errno;
1716f6dcf54d4c181c2e2558e3d5414f54c8d9caLennart Poettering goto fail;
1716f6dcf54d4c181c2e2558e3d5414f54c8d9caLennart Poettering }
1716f6dcf54d4c181c2e2558e3d5414f54c8d9caLennart Poettering
1716f6dcf54d4c181c2e2558e3d5414f54c8d9caLennart Poettering r = bind(m->llmnr_ipv4_udp_fd, &sa.sa, sizeof(sa.in));
1716f6dcf54d4c181c2e2558e3d5414f54c8d9caLennart Poettering if (r < 0) {
1716f6dcf54d4c181c2e2558e3d5414f54c8d9caLennart Poettering r = -errno;
1716f6dcf54d4c181c2e2558e3d5414f54c8d9caLennart Poettering goto fail;
1716f6dcf54d4c181c2e2558e3d5414f54c8d9caLennart Poettering }
1716f6dcf54d4c181c2e2558e3d5414f54c8d9caLennart Poettering
1716f6dcf54d4c181c2e2558e3d5414f54c8d9caLennart Poettering r = sd_event_add_io(m->event, &m->llmnr_ipv4_udp_event_source, m->llmnr_ipv4_udp_fd, EPOLLIN, on_llmnr_packet, m);
1716f6dcf54d4c181c2e2558e3d5414f54c8d9caLennart Poettering if (r < 0)
1716f6dcf54d4c181c2e2558e3d5414f54c8d9caLennart Poettering goto fail;
1716f6dcf54d4c181c2e2558e3d5414f54c8d9caLennart Poettering
1716f6dcf54d4c181c2e2558e3d5414f54c8d9caLennart Poettering return m->llmnr_ipv4_udp_fd;
1716f6dcf54d4c181c2e2558e3d5414f54c8d9caLennart Poettering
1716f6dcf54d4c181c2e2558e3d5414f54c8d9caLennart Poetteringfail:
1716f6dcf54d4c181c2e2558e3d5414f54c8d9caLennart Poettering m->llmnr_ipv4_udp_fd = safe_close(m->llmnr_ipv4_udp_fd);
1716f6dcf54d4c181c2e2558e3d5414f54c8d9caLennart Poettering return r;
1716f6dcf54d4c181c2e2558e3d5414f54c8d9caLennart Poettering}
1716f6dcf54d4c181c2e2558e3d5414f54c8d9caLennart Poettering
1716f6dcf54d4c181c2e2558e3d5414f54c8d9caLennart Poetteringint manager_llmnr_ipv6_udp_fd(Manager *m) {
1716f6dcf54d4c181c2e2558e3d5414f54c8d9caLennart Poettering union sockaddr_union sa = {
1716f6dcf54d4c181c2e2558e3d5414f54c8d9caLennart Poettering .in6.sin6_family = AF_INET6,
1716f6dcf54d4c181c2e2558e3d5414f54c8d9caLennart Poettering .in6.sin6_port = htobe16(5355),
1716f6dcf54d4c181c2e2558e3d5414f54c8d9caLennart Poettering };
bf3f1271e2cc0c22b11c8a805a997578dabe9191Lennart Poettering static const int one = 1, ttl = 255;
1716f6dcf54d4c181c2e2558e3d5414f54c8d9caLennart Poettering int r;
1716f6dcf54d4c181c2e2558e3d5414f54c8d9caLennart Poettering
1716f6dcf54d4c181c2e2558e3d5414f54c8d9caLennart Poettering assert(m);
1716f6dcf54d4c181c2e2558e3d5414f54c8d9caLennart Poettering
1716f6dcf54d4c181c2e2558e3d5414f54c8d9caLennart Poettering if (m->llmnr_ipv6_udp_fd >= 0)
1716f6dcf54d4c181c2e2558e3d5414f54c8d9caLennart Poettering return m->llmnr_ipv6_udp_fd;
1716f6dcf54d4c181c2e2558e3d5414f54c8d9caLennart Poettering
1716f6dcf54d4c181c2e2558e3d5414f54c8d9caLennart Poettering m->llmnr_ipv6_udp_fd = socket(AF_INET6, SOCK_DGRAM|SOCK_CLOEXEC|SOCK_NONBLOCK, 0);
1716f6dcf54d4c181c2e2558e3d5414f54c8d9caLennart Poettering if (m->llmnr_ipv6_udp_fd < 0)
1716f6dcf54d4c181c2e2558e3d5414f54c8d9caLennart Poettering return -errno;
1716f6dcf54d4c181c2e2558e3d5414f54c8d9caLennart Poettering
bf3f1271e2cc0c22b11c8a805a997578dabe9191Lennart Poettering r = setsockopt(m->llmnr_ipv6_udp_fd, IPPROTO_IPV6, IPV6_UNICAST_HOPS, &ttl, sizeof(ttl));
1716f6dcf54d4c181c2e2558e3d5414f54c8d9caLennart Poettering if (r < 0) {
1716f6dcf54d4c181c2e2558e3d5414f54c8d9caLennart Poettering r = -errno;
1716f6dcf54d4c181c2e2558e3d5414f54c8d9caLennart Poettering goto fail;
1716f6dcf54d4c181c2e2558e3d5414f54c8d9caLennart Poettering }
1716f6dcf54d4c181c2e2558e3d5414f54c8d9caLennart Poettering
bf3f1271e2cc0c22b11c8a805a997578dabe9191Lennart Poettering /* RFC 4795, section 2.5 recommends setting the TTL of UDP packets to 255. */
bf3f1271e2cc0c22b11c8a805a997578dabe9191Lennart Poettering r = setsockopt(m->llmnr_ipv6_udp_fd, IPPROTO_IPV6, IPV6_MULTICAST_HOPS, &ttl, sizeof(ttl));
1716f6dcf54d4c181c2e2558e3d5414f54c8d9caLennart Poettering if (r < 0) {
1716f6dcf54d4c181c2e2558e3d5414f54c8d9caLennart Poettering r = -errno;
1716f6dcf54d4c181c2e2558e3d5414f54c8d9caLennart Poettering goto fail;
1716f6dcf54d4c181c2e2558e3d5414f54c8d9caLennart Poettering }
1716f6dcf54d4c181c2e2558e3d5414f54c8d9caLennart Poettering
1716f6dcf54d4c181c2e2558e3d5414f54c8d9caLennart Poettering r = setsockopt(m->llmnr_ipv6_udp_fd, IPPROTO_IPV6, IPV6_MULTICAST_LOOP, &one, sizeof(one));
1716f6dcf54d4c181c2e2558e3d5414f54c8d9caLennart Poettering if (r < 0) {
1716f6dcf54d4c181c2e2558e3d5414f54c8d9caLennart Poettering r = -errno;
1716f6dcf54d4c181c2e2558e3d5414f54c8d9caLennart Poettering goto fail;
1716f6dcf54d4c181c2e2558e3d5414f54c8d9caLennart Poettering }
1716f6dcf54d4c181c2e2558e3d5414f54c8d9caLennart Poettering
1716f6dcf54d4c181c2e2558e3d5414f54c8d9caLennart Poettering r = setsockopt(m->llmnr_ipv6_udp_fd, IPPROTO_IPV6, IPV6_V6ONLY, &one, sizeof(one));
1716f6dcf54d4c181c2e2558e3d5414f54c8d9caLennart Poettering if (r < 0) {
1716f6dcf54d4c181c2e2558e3d5414f54c8d9caLennart Poettering r = -errno;
1716f6dcf54d4c181c2e2558e3d5414f54c8d9caLennart Poettering goto fail;
1716f6dcf54d4c181c2e2558e3d5414f54c8d9caLennart Poettering }
1716f6dcf54d4c181c2e2558e3d5414f54c8d9caLennart Poettering
1716f6dcf54d4c181c2e2558e3d5414f54c8d9caLennart Poettering r = setsockopt(m->llmnr_ipv6_udp_fd, SOL_SOCKET, SO_REUSEADDR, &one, sizeof(one));
1716f6dcf54d4c181c2e2558e3d5414f54c8d9caLennart Poettering if (r < 0) {
1716f6dcf54d4c181c2e2558e3d5414f54c8d9caLennart Poettering r = -errno;
1716f6dcf54d4c181c2e2558e3d5414f54c8d9caLennart Poettering goto fail;
1716f6dcf54d4c181c2e2558e3d5414f54c8d9caLennart Poettering }
1716f6dcf54d4c181c2e2558e3d5414f54c8d9caLennart Poettering
1716f6dcf54d4c181c2e2558e3d5414f54c8d9caLennart Poettering r = setsockopt(m->llmnr_ipv6_udp_fd, IPPROTO_IPV6, IPV6_RECVPKTINFO, &one, sizeof(one));
1716f6dcf54d4c181c2e2558e3d5414f54c8d9caLennart Poettering if (r < 0) {
1716f6dcf54d4c181c2e2558e3d5414f54c8d9caLennart Poettering r = -errno;
1716f6dcf54d4c181c2e2558e3d5414f54c8d9caLennart Poettering goto fail;
1716f6dcf54d4c181c2e2558e3d5414f54c8d9caLennart Poettering }
1716f6dcf54d4c181c2e2558e3d5414f54c8d9caLennart Poettering
1716f6dcf54d4c181c2e2558e3d5414f54c8d9caLennart Poettering r = setsockopt(m->llmnr_ipv6_udp_fd, IPPROTO_IPV6, IPV6_RECVHOPLIMIT, &one, sizeof(one));
1716f6dcf54d4c181c2e2558e3d5414f54c8d9caLennart Poettering if (r < 0) {
1716f6dcf54d4c181c2e2558e3d5414f54c8d9caLennart Poettering r = -errno;
1716f6dcf54d4c181c2e2558e3d5414f54c8d9caLennart Poettering goto fail;
1716f6dcf54d4c181c2e2558e3d5414f54c8d9caLennart Poettering }
1716f6dcf54d4c181c2e2558e3d5414f54c8d9caLennart Poettering
1716f6dcf54d4c181c2e2558e3d5414f54c8d9caLennart Poettering r = bind(m->llmnr_ipv6_udp_fd, &sa.sa, sizeof(sa.in6));
1716f6dcf54d4c181c2e2558e3d5414f54c8d9caLennart Poettering if (r < 0) {
1716f6dcf54d4c181c2e2558e3d5414f54c8d9caLennart Poettering r = -errno;
1716f6dcf54d4c181c2e2558e3d5414f54c8d9caLennart Poettering goto fail;
1716f6dcf54d4c181c2e2558e3d5414f54c8d9caLennart Poettering }
1716f6dcf54d4c181c2e2558e3d5414f54c8d9caLennart Poettering
1716f6dcf54d4c181c2e2558e3d5414f54c8d9caLennart Poettering r = sd_event_add_io(m->event, &m->llmnr_ipv6_udp_event_source, m->llmnr_ipv6_udp_fd, EPOLLIN, on_llmnr_packet, m);
1716f6dcf54d4c181c2e2558e3d5414f54c8d9caLennart Poettering if (r < 0) {
1716f6dcf54d4c181c2e2558e3d5414f54c8d9caLennart Poettering r = -errno;
1716f6dcf54d4c181c2e2558e3d5414f54c8d9caLennart Poettering goto fail;
1716f6dcf54d4c181c2e2558e3d5414f54c8d9caLennart Poettering }
1716f6dcf54d4c181c2e2558e3d5414f54c8d9caLennart Poettering
1716f6dcf54d4c181c2e2558e3d5414f54c8d9caLennart Poettering return m->llmnr_ipv6_udp_fd;
1716f6dcf54d4c181c2e2558e3d5414f54c8d9caLennart Poettering
1716f6dcf54d4c181c2e2558e3d5414f54c8d9caLennart Poetteringfail:
1716f6dcf54d4c181c2e2558e3d5414f54c8d9caLennart Poettering m->llmnr_ipv6_udp_fd = safe_close(m->llmnr_ipv6_udp_fd);
1716f6dcf54d4c181c2e2558e3d5414f54c8d9caLennart Poettering return r;
1716f6dcf54d4c181c2e2558e3d5414f54c8d9caLennart Poettering}
623a4c97b9175f95c4b1c6fc34e36c56f1e4ddbfLennart Poettering
623a4c97b9175f95c4b1c6fc34e36c56f1e4ddbfLennart Poetteringstatic int on_llmnr_stream_packet(DnsStream *s) {
a407657425a3e47fd2b559cd3bc800f791303f63Lennart Poettering DnsScope *scope;
623a4c97b9175f95c4b1c6fc34e36c56f1e4ddbfLennart Poettering
a407657425a3e47fd2b559cd3bc800f791303f63Lennart Poettering assert(s);
623a4c97b9175f95c4b1c6fc34e36c56f1e4ddbfLennart Poettering
a407657425a3e47fd2b559cd3bc800f791303f63Lennart Poettering scope = manager_find_scope(s->manager, s->read_packet);
a407657425a3e47fd2b559cd3bc800f791303f63Lennart Poettering if (!scope) {
a407657425a3e47fd2b559cd3bc800f791303f63Lennart Poettering log_warning("Got LLMNR TCP packet on unknown scope. Ignroing.");
a407657425a3e47fd2b559cd3bc800f791303f63Lennart Poettering return 0;
a407657425a3e47fd2b559cd3bc800f791303f63Lennart Poettering }
623a4c97b9175f95c4b1c6fc34e36c56f1e4ddbfLennart Poettering
a407657425a3e47fd2b559cd3bc800f791303f63Lennart Poettering if (dns_packet_validate_query(s->read_packet) > 0) {
a407657425a3e47fd2b559cd3bc800f791303f63Lennart Poettering log_debug("Got query packet for id %u", DNS_PACKET_ID(s->read_packet));
623a4c97b9175f95c4b1c6fc34e36c56f1e4ddbfLennart Poettering
a407657425a3e47fd2b559cd3bc800f791303f63Lennart Poettering dns_scope_process_query(scope, s, s->read_packet);
623a4c97b9175f95c4b1c6fc34e36c56f1e4ddbfLennart Poettering
a407657425a3e47fd2b559cd3bc800f791303f63Lennart Poettering /* If no reply packet was set, we free the stream */
a407657425a3e47fd2b559cd3bc800f791303f63Lennart Poettering if (s->write_packet)
a407657425a3e47fd2b559cd3bc800f791303f63Lennart Poettering return 0;
a407657425a3e47fd2b559cd3bc800f791303f63Lennart Poettering } else
a407657425a3e47fd2b559cd3bc800f791303f63Lennart Poettering log_debug("Invalid LLMNR TCP packet.");
623a4c97b9175f95c4b1c6fc34e36c56f1e4ddbfLennart Poettering
623a4c97b9175f95c4b1c6fc34e36c56f1e4ddbfLennart Poettering dns_stream_free(s);
623a4c97b9175f95c4b1c6fc34e36c56f1e4ddbfLennart Poettering return 0;
623a4c97b9175f95c4b1c6fc34e36c56f1e4ddbfLennart Poettering}
623a4c97b9175f95c4b1c6fc34e36c56f1e4ddbfLennart Poettering
623a4c97b9175f95c4b1c6fc34e36c56f1e4ddbfLennart Poetteringstatic int on_llmnr_stream(sd_event_source *s, int fd, uint32_t revents, void *userdata) {
623a4c97b9175f95c4b1c6fc34e36c56f1e4ddbfLennart Poettering DnsStream *stream;
623a4c97b9175f95c4b1c6fc34e36c56f1e4ddbfLennart Poettering Manager *m = userdata;
623a4c97b9175f95c4b1c6fc34e36c56f1e4ddbfLennart Poettering int cfd, r;
623a4c97b9175f95c4b1c6fc34e36c56f1e4ddbfLennart Poettering
623a4c97b9175f95c4b1c6fc34e36c56f1e4ddbfLennart Poettering cfd = accept4(fd, NULL, NULL, SOCK_NONBLOCK|SOCK_CLOEXEC);
623a4c97b9175f95c4b1c6fc34e36c56f1e4ddbfLennart Poettering if (cfd < 0) {
623a4c97b9175f95c4b1c6fc34e36c56f1e4ddbfLennart Poettering if (errno == EAGAIN || errno == EINTR)
623a4c97b9175f95c4b1c6fc34e36c56f1e4ddbfLennart Poettering return 0;
623a4c97b9175f95c4b1c6fc34e36c56f1e4ddbfLennart Poettering
623a4c97b9175f95c4b1c6fc34e36c56f1e4ddbfLennart Poettering return -errno;
623a4c97b9175f95c4b1c6fc34e36c56f1e4ddbfLennart Poettering }
623a4c97b9175f95c4b1c6fc34e36c56f1e4ddbfLennart Poettering
623a4c97b9175f95c4b1c6fc34e36c56f1e4ddbfLennart Poettering r = dns_stream_new(m, &stream, DNS_PROTOCOL_LLMNR, cfd);
623a4c97b9175f95c4b1c6fc34e36c56f1e4ddbfLennart Poettering if (r < 0) {
623a4c97b9175f95c4b1c6fc34e36c56f1e4ddbfLennart Poettering safe_close(cfd);
623a4c97b9175f95c4b1c6fc34e36c56f1e4ddbfLennart Poettering return r;
623a4c97b9175f95c4b1c6fc34e36c56f1e4ddbfLennart Poettering }
623a4c97b9175f95c4b1c6fc34e36c56f1e4ddbfLennart Poettering
623a4c97b9175f95c4b1c6fc34e36c56f1e4ddbfLennart Poettering stream->on_packet = on_llmnr_stream_packet;
623a4c97b9175f95c4b1c6fc34e36c56f1e4ddbfLennart Poettering return 0;
623a4c97b9175f95c4b1c6fc34e36c56f1e4ddbfLennart Poettering}
623a4c97b9175f95c4b1c6fc34e36c56f1e4ddbfLennart Poettering
623a4c97b9175f95c4b1c6fc34e36c56f1e4ddbfLennart Poetteringint manager_llmnr_ipv4_tcp_fd(Manager *m) {
623a4c97b9175f95c4b1c6fc34e36c56f1e4ddbfLennart Poettering union sockaddr_union sa = {
623a4c97b9175f95c4b1c6fc34e36c56f1e4ddbfLennart Poettering .in.sin_family = AF_INET,
623a4c97b9175f95c4b1c6fc34e36c56f1e4ddbfLennart Poettering .in.sin_port = htobe16(5355),
623a4c97b9175f95c4b1c6fc34e36c56f1e4ddbfLennart Poettering };
623a4c97b9175f95c4b1c6fc34e36c56f1e4ddbfLennart Poettering static const int one = 1, pmtu = IP_PMTUDISC_DONT;
623a4c97b9175f95c4b1c6fc34e36c56f1e4ddbfLennart Poettering int r;
623a4c97b9175f95c4b1c6fc34e36c56f1e4ddbfLennart Poettering
623a4c97b9175f95c4b1c6fc34e36c56f1e4ddbfLennart Poettering assert(m);
623a4c97b9175f95c4b1c6fc34e36c56f1e4ddbfLennart Poettering
623a4c97b9175f95c4b1c6fc34e36c56f1e4ddbfLennart Poettering if (m->llmnr_ipv4_tcp_fd >= 0)
623a4c97b9175f95c4b1c6fc34e36c56f1e4ddbfLennart Poettering return m->llmnr_ipv4_tcp_fd;
623a4c97b9175f95c4b1c6fc34e36c56f1e4ddbfLennart Poettering
623a4c97b9175f95c4b1c6fc34e36c56f1e4ddbfLennart Poettering m->llmnr_ipv4_tcp_fd = socket(AF_INET, SOCK_STREAM|SOCK_CLOEXEC|SOCK_NONBLOCK, 0);
623a4c97b9175f95c4b1c6fc34e36c56f1e4ddbfLennart Poettering if (m->llmnr_ipv4_tcp_fd < 0)
623a4c97b9175f95c4b1c6fc34e36c56f1e4ddbfLennart Poettering return -errno;
623a4c97b9175f95c4b1c6fc34e36c56f1e4ddbfLennart Poettering
bf3f1271e2cc0c22b11c8a805a997578dabe9191Lennart Poettering /* RFC 4795, section 2.5. requires setting the TTL of TCP streams to 1 */
623a4c97b9175f95c4b1c6fc34e36c56f1e4ddbfLennart Poettering r = setsockopt(m->llmnr_ipv4_tcp_fd, IPPROTO_IP, IP_TTL, &one, sizeof(one));
623a4c97b9175f95c4b1c6fc34e36c56f1e4ddbfLennart Poettering if (r < 0) {
623a4c97b9175f95c4b1c6fc34e36c56f1e4ddbfLennart Poettering r = -errno;
623a4c97b9175f95c4b1c6fc34e36c56f1e4ddbfLennart Poettering goto fail;
623a4c97b9175f95c4b1c6fc34e36c56f1e4ddbfLennart Poettering }
623a4c97b9175f95c4b1c6fc34e36c56f1e4ddbfLennart Poettering
623a4c97b9175f95c4b1c6fc34e36c56f1e4ddbfLennart Poettering r = setsockopt(m->llmnr_ipv4_tcp_fd, SOL_SOCKET, SO_REUSEADDR, &one, sizeof(one));
623a4c97b9175f95c4b1c6fc34e36c56f1e4ddbfLennart Poettering if (r < 0) {
623a4c97b9175f95c4b1c6fc34e36c56f1e4ddbfLennart Poettering r = -errno;
623a4c97b9175f95c4b1c6fc34e36c56f1e4ddbfLennart Poettering goto fail;
623a4c97b9175f95c4b1c6fc34e36c56f1e4ddbfLennart Poettering }
623a4c97b9175f95c4b1c6fc34e36c56f1e4ddbfLennart Poettering
623a4c97b9175f95c4b1c6fc34e36c56f1e4ddbfLennart Poettering r = setsockopt(m->llmnr_ipv4_tcp_fd, IPPROTO_IP, IP_PKTINFO, &one, sizeof(one));
623a4c97b9175f95c4b1c6fc34e36c56f1e4ddbfLennart Poettering if (r < 0) {
623a4c97b9175f95c4b1c6fc34e36c56f1e4ddbfLennart Poettering r = -errno;
623a4c97b9175f95c4b1c6fc34e36c56f1e4ddbfLennart Poettering goto fail;
623a4c97b9175f95c4b1c6fc34e36c56f1e4ddbfLennart Poettering }
623a4c97b9175f95c4b1c6fc34e36c56f1e4ddbfLennart Poettering
623a4c97b9175f95c4b1c6fc34e36c56f1e4ddbfLennart Poettering r = setsockopt(m->llmnr_ipv4_tcp_fd, IPPROTO_IP, IP_RECVTTL, &one, sizeof(one));
623a4c97b9175f95c4b1c6fc34e36c56f1e4ddbfLennart Poettering if (r < 0) {
623a4c97b9175f95c4b1c6fc34e36c56f1e4ddbfLennart Poettering r = -errno;
623a4c97b9175f95c4b1c6fc34e36c56f1e4ddbfLennart Poettering goto fail;
623a4c97b9175f95c4b1c6fc34e36c56f1e4ddbfLennart Poettering }
623a4c97b9175f95c4b1c6fc34e36c56f1e4ddbfLennart Poettering
623a4c97b9175f95c4b1c6fc34e36c56f1e4ddbfLennart Poettering /* Disable Don't-Fragment bit in the IP header */
623a4c97b9175f95c4b1c6fc34e36c56f1e4ddbfLennart Poettering r = setsockopt(m->llmnr_ipv4_tcp_fd, IPPROTO_IP, IP_MTU_DISCOVER, &pmtu, sizeof(pmtu));
623a4c97b9175f95c4b1c6fc34e36c56f1e4ddbfLennart Poettering if (r < 0) {
623a4c97b9175f95c4b1c6fc34e36c56f1e4ddbfLennart Poettering r = -errno;
623a4c97b9175f95c4b1c6fc34e36c56f1e4ddbfLennart Poettering goto fail;
623a4c97b9175f95c4b1c6fc34e36c56f1e4ddbfLennart Poettering }
623a4c97b9175f95c4b1c6fc34e36c56f1e4ddbfLennart Poettering
623a4c97b9175f95c4b1c6fc34e36c56f1e4ddbfLennart Poettering r = bind(m->llmnr_ipv4_tcp_fd, &sa.sa, sizeof(sa.in));
623a4c97b9175f95c4b1c6fc34e36c56f1e4ddbfLennart Poettering if (r < 0) {
623a4c97b9175f95c4b1c6fc34e36c56f1e4ddbfLennart Poettering r = -errno;
623a4c97b9175f95c4b1c6fc34e36c56f1e4ddbfLennart Poettering goto fail;
623a4c97b9175f95c4b1c6fc34e36c56f1e4ddbfLennart Poettering }
623a4c97b9175f95c4b1c6fc34e36c56f1e4ddbfLennart Poettering
623a4c97b9175f95c4b1c6fc34e36c56f1e4ddbfLennart Poettering r = listen(m->llmnr_ipv4_tcp_fd, SOMAXCONN);
623a4c97b9175f95c4b1c6fc34e36c56f1e4ddbfLennart Poettering if (r < 0) {
623a4c97b9175f95c4b1c6fc34e36c56f1e4ddbfLennart Poettering r = -errno;
623a4c97b9175f95c4b1c6fc34e36c56f1e4ddbfLennart Poettering goto fail;
623a4c97b9175f95c4b1c6fc34e36c56f1e4ddbfLennart Poettering }
623a4c97b9175f95c4b1c6fc34e36c56f1e4ddbfLennart Poettering
623a4c97b9175f95c4b1c6fc34e36c56f1e4ddbfLennart Poettering r = sd_event_add_io(m->event, &m->llmnr_ipv4_tcp_event_source, m->llmnr_ipv4_tcp_fd, EPOLLIN, on_llmnr_stream, m);
623a4c97b9175f95c4b1c6fc34e36c56f1e4ddbfLennart Poettering if (r < 0)
623a4c97b9175f95c4b1c6fc34e36c56f1e4ddbfLennart Poettering goto fail;
623a4c97b9175f95c4b1c6fc34e36c56f1e4ddbfLennart Poettering
623a4c97b9175f95c4b1c6fc34e36c56f1e4ddbfLennart Poettering return m->llmnr_ipv4_tcp_fd;
623a4c97b9175f95c4b1c6fc34e36c56f1e4ddbfLennart Poettering
623a4c97b9175f95c4b1c6fc34e36c56f1e4ddbfLennart Poetteringfail:
623a4c97b9175f95c4b1c6fc34e36c56f1e4ddbfLennart Poettering m->llmnr_ipv4_tcp_fd = safe_close(m->llmnr_ipv4_tcp_fd);
623a4c97b9175f95c4b1c6fc34e36c56f1e4ddbfLennart Poettering return r;
623a4c97b9175f95c4b1c6fc34e36c56f1e4ddbfLennart Poettering}
623a4c97b9175f95c4b1c6fc34e36c56f1e4ddbfLennart Poettering
623a4c97b9175f95c4b1c6fc34e36c56f1e4ddbfLennart Poetteringint manager_llmnr_ipv6_tcp_fd(Manager *m) {
623a4c97b9175f95c4b1c6fc34e36c56f1e4ddbfLennart Poettering union sockaddr_union sa = {
623a4c97b9175f95c4b1c6fc34e36c56f1e4ddbfLennart Poettering .in6.sin6_family = AF_INET6,
623a4c97b9175f95c4b1c6fc34e36c56f1e4ddbfLennart Poettering .in6.sin6_port = htobe16(5355),
623a4c97b9175f95c4b1c6fc34e36c56f1e4ddbfLennart Poettering };
623a4c97b9175f95c4b1c6fc34e36c56f1e4ddbfLennart Poettering static const int one = 1;
623a4c97b9175f95c4b1c6fc34e36c56f1e4ddbfLennart Poettering int r;
623a4c97b9175f95c4b1c6fc34e36c56f1e4ddbfLennart Poettering
623a4c97b9175f95c4b1c6fc34e36c56f1e4ddbfLennart Poettering assert(m);
623a4c97b9175f95c4b1c6fc34e36c56f1e4ddbfLennart Poettering
623a4c97b9175f95c4b1c6fc34e36c56f1e4ddbfLennart Poettering if (m->llmnr_ipv6_tcp_fd >= 0)
623a4c97b9175f95c4b1c6fc34e36c56f1e4ddbfLennart Poettering return m->llmnr_ipv6_tcp_fd;
623a4c97b9175f95c4b1c6fc34e36c56f1e4ddbfLennart Poettering
623a4c97b9175f95c4b1c6fc34e36c56f1e4ddbfLennart Poettering m->llmnr_ipv6_tcp_fd = socket(AF_INET6, SOCK_STREAM|SOCK_CLOEXEC|SOCK_NONBLOCK, 0);
623a4c97b9175f95c4b1c6fc34e36c56f1e4ddbfLennart Poettering if (m->llmnr_ipv6_tcp_fd < 0)
623a4c97b9175f95c4b1c6fc34e36c56f1e4ddbfLennart Poettering return -errno;
623a4c97b9175f95c4b1c6fc34e36c56f1e4ddbfLennart Poettering
bf3f1271e2cc0c22b11c8a805a997578dabe9191Lennart Poettering /* RFC 4795, section 2.5. requires setting the TTL of TCP streams to 1 */
623a4c97b9175f95c4b1c6fc34e36c56f1e4ddbfLennart Poettering r = setsockopt(m->llmnr_ipv6_tcp_fd, IPPROTO_IPV6, IPV6_UNICAST_HOPS, &one, sizeof(one));
623a4c97b9175f95c4b1c6fc34e36c56f1e4ddbfLennart Poettering if (r < 0) {
623a4c97b9175f95c4b1c6fc34e36c56f1e4ddbfLennart Poettering r = -errno;
623a4c97b9175f95c4b1c6fc34e36c56f1e4ddbfLennart Poettering goto fail;
623a4c97b9175f95c4b1c6fc34e36c56f1e4ddbfLennart Poettering }
623a4c97b9175f95c4b1c6fc34e36c56f1e4ddbfLennart Poettering
623a4c97b9175f95c4b1c6fc34e36c56f1e4ddbfLennart Poettering r = setsockopt(m->llmnr_ipv6_tcp_fd, IPPROTO_IPV6, IPV6_V6ONLY, &one, sizeof(one));
623a4c97b9175f95c4b1c6fc34e36c56f1e4ddbfLennart Poettering if (r < 0) {
623a4c97b9175f95c4b1c6fc34e36c56f1e4ddbfLennart Poettering r = -errno;
623a4c97b9175f95c4b1c6fc34e36c56f1e4ddbfLennart Poettering goto fail;
623a4c97b9175f95c4b1c6fc34e36c56f1e4ddbfLennart Poettering }
623a4c97b9175f95c4b1c6fc34e36c56f1e4ddbfLennart Poettering
623a4c97b9175f95c4b1c6fc34e36c56f1e4ddbfLennart Poettering r = setsockopt(m->llmnr_ipv6_tcp_fd, SOL_SOCKET, SO_REUSEADDR, &one, sizeof(one));
623a4c97b9175f95c4b1c6fc34e36c56f1e4ddbfLennart Poettering if (r < 0) {
623a4c97b9175f95c4b1c6fc34e36c56f1e4ddbfLennart Poettering r = -errno;
623a4c97b9175f95c4b1c6fc34e36c56f1e4ddbfLennart Poettering goto fail;
623a4c97b9175f95c4b1c6fc34e36c56f1e4ddbfLennart Poettering }
623a4c97b9175f95c4b1c6fc34e36c56f1e4ddbfLennart Poettering
623a4c97b9175f95c4b1c6fc34e36c56f1e4ddbfLennart Poettering r = setsockopt(m->llmnr_ipv6_tcp_fd, IPPROTO_IPV6, IPV6_RECVPKTINFO, &one, sizeof(one));
623a4c97b9175f95c4b1c6fc34e36c56f1e4ddbfLennart Poettering if (r < 0) {
623a4c97b9175f95c4b1c6fc34e36c56f1e4ddbfLennart Poettering r = -errno;
623a4c97b9175f95c4b1c6fc34e36c56f1e4ddbfLennart Poettering goto fail;
623a4c97b9175f95c4b1c6fc34e36c56f1e4ddbfLennart Poettering }
623a4c97b9175f95c4b1c6fc34e36c56f1e4ddbfLennart Poettering
623a4c97b9175f95c4b1c6fc34e36c56f1e4ddbfLennart Poettering r = setsockopt(m->llmnr_ipv6_tcp_fd, IPPROTO_IPV6, IPV6_RECVHOPLIMIT, &one, sizeof(one));
623a4c97b9175f95c4b1c6fc34e36c56f1e4ddbfLennart Poettering if (r < 0) {
623a4c97b9175f95c4b1c6fc34e36c56f1e4ddbfLennart Poettering r = -errno;
623a4c97b9175f95c4b1c6fc34e36c56f1e4ddbfLennart Poettering goto fail;
623a4c97b9175f95c4b1c6fc34e36c56f1e4ddbfLennart Poettering }
623a4c97b9175f95c4b1c6fc34e36c56f1e4ddbfLennart Poettering
623a4c97b9175f95c4b1c6fc34e36c56f1e4ddbfLennart Poettering r = bind(m->llmnr_ipv6_tcp_fd, &sa.sa, sizeof(sa.in6));
623a4c97b9175f95c4b1c6fc34e36c56f1e4ddbfLennart Poettering if (r < 0) {
623a4c97b9175f95c4b1c6fc34e36c56f1e4ddbfLennart Poettering r = -errno;
623a4c97b9175f95c4b1c6fc34e36c56f1e4ddbfLennart Poettering goto fail;
623a4c97b9175f95c4b1c6fc34e36c56f1e4ddbfLennart Poettering }
623a4c97b9175f95c4b1c6fc34e36c56f1e4ddbfLennart Poettering
623a4c97b9175f95c4b1c6fc34e36c56f1e4ddbfLennart Poettering r = listen(m->llmnr_ipv6_tcp_fd, SOMAXCONN);
623a4c97b9175f95c4b1c6fc34e36c56f1e4ddbfLennart Poettering if (r < 0) {
623a4c97b9175f95c4b1c6fc34e36c56f1e4ddbfLennart Poettering r = -errno;
623a4c97b9175f95c4b1c6fc34e36c56f1e4ddbfLennart Poettering goto fail;
623a4c97b9175f95c4b1c6fc34e36c56f1e4ddbfLennart Poettering }
623a4c97b9175f95c4b1c6fc34e36c56f1e4ddbfLennart Poettering
623a4c97b9175f95c4b1c6fc34e36c56f1e4ddbfLennart Poettering r = sd_event_add_io(m->event, &m->llmnr_ipv6_tcp_event_source, m->llmnr_ipv6_tcp_fd, EPOLLIN, on_llmnr_stream, m);
623a4c97b9175f95c4b1c6fc34e36c56f1e4ddbfLennart Poettering if (r < 0) {
623a4c97b9175f95c4b1c6fc34e36c56f1e4ddbfLennart Poettering r = -errno;
623a4c97b9175f95c4b1c6fc34e36c56f1e4ddbfLennart Poettering goto fail;
623a4c97b9175f95c4b1c6fc34e36c56f1e4ddbfLennart Poettering }
623a4c97b9175f95c4b1c6fc34e36c56f1e4ddbfLennart Poettering
623a4c97b9175f95c4b1c6fc34e36c56f1e4ddbfLennart Poettering return m->llmnr_ipv6_tcp_fd;
623a4c97b9175f95c4b1c6fc34e36c56f1e4ddbfLennart Poettering
623a4c97b9175f95c4b1c6fc34e36c56f1e4ddbfLennart Poetteringfail:
623a4c97b9175f95c4b1c6fc34e36c56f1e4ddbfLennart Poettering m->llmnr_ipv6_tcp_fd = safe_close(m->llmnr_ipv6_tcp_fd);
623a4c97b9175f95c4b1c6fc34e36c56f1e4ddbfLennart Poettering return r;
623a4c97b9175f95c4b1c6fc34e36c56f1e4ddbfLennart Poettering}
623a4c97b9175f95c4b1c6fc34e36c56f1e4ddbfLennart Poettering
623a4c97b9175f95c4b1c6fc34e36c56f1e4ddbfLennart Poetteringint manager_find_ifindex(Manager *m, int family, const union in_addr_union *in_addr) {
ec2c5e4398f9d65e5dfe61530f2556224733d1e6Lennart Poettering LinkAddress *a;
ec2c5e4398f9d65e5dfe61530f2556224733d1e6Lennart Poettering
ec2c5e4398f9d65e5dfe61530f2556224733d1e6Lennart Poettering assert(m);
ec2c5e4398f9d65e5dfe61530f2556224733d1e6Lennart Poettering
4e945a6f7971fd7d1f6b2c62ee3afdaff3c95ce4Lennart Poettering a = manager_find_link_address(m, family, in_addr);
ec2c5e4398f9d65e5dfe61530f2556224733d1e6Lennart Poettering if (a)
ec2c5e4398f9d65e5dfe61530f2556224733d1e6Lennart Poettering return a->link->ifindex;
ec2c5e4398f9d65e5dfe61530f2556224733d1e6Lennart Poettering
ec2c5e4398f9d65e5dfe61530f2556224733d1e6Lennart Poettering return 0;
ec2c5e4398f9d65e5dfe61530f2556224733d1e6Lennart Poettering}
ec2c5e4398f9d65e5dfe61530f2556224733d1e6Lennart Poettering
eb60f9cd4e93ff5016dc1b5486fd1b7e1565fd92Lennart Poetteringvoid manager_refresh_rrs(Manager *m) {
eb60f9cd4e93ff5016dc1b5486fd1b7e1565fd92Lennart Poettering Iterator i;
eb60f9cd4e93ff5016dc1b5486fd1b7e1565fd92Lennart Poettering Link *l;
eb60f9cd4e93ff5016dc1b5486fd1b7e1565fd92Lennart Poettering
eb60f9cd4e93ff5016dc1b5486fd1b7e1565fd92Lennart Poettering assert(m);
eb60f9cd4e93ff5016dc1b5486fd1b7e1565fd92Lennart Poettering
eb60f9cd4e93ff5016dc1b5486fd1b7e1565fd92Lennart Poettering m->host_ipv4_key = dns_resource_key_unref(m->host_ipv4_key);
eb60f9cd4e93ff5016dc1b5486fd1b7e1565fd92Lennart Poettering m->host_ipv6_key = dns_resource_key_unref(m->host_ipv6_key);
eb60f9cd4e93ff5016dc1b5486fd1b7e1565fd92Lennart Poettering
eb60f9cd4e93ff5016dc1b5486fd1b7e1565fd92Lennart Poettering HASHMAP_FOREACH(l, m->links, i) {
eb60f9cd4e93ff5016dc1b5486fd1b7e1565fd92Lennart Poettering link_add_rrs(l, true);
eb60f9cd4e93ff5016dc1b5486fd1b7e1565fd92Lennart Poettering link_add_rrs(l, false);
eb60f9cd4e93ff5016dc1b5486fd1b7e1565fd92Lennart Poettering }
eb60f9cd4e93ff5016dc1b5486fd1b7e1565fd92Lennart Poettering}
eb60f9cd4e93ff5016dc1b5486fd1b7e1565fd92Lennart Poettering
ec2c5e4398f9d65e5dfe61530f2556224733d1e6Lennart Poetteringint manager_next_hostname(Manager *m) {
ec2c5e4398f9d65e5dfe61530f2556224733d1e6Lennart Poettering const char *p;
556a22945fcc88ca27ae7ecc46c9bb2727e37895Lennart Poettering uint64_t u, a;
ec2c5e4398f9d65e5dfe61530f2556224733d1e6Lennart Poettering char *h;
623a4c97b9175f95c4b1c6fc34e36c56f1e4ddbfLennart Poettering
623a4c97b9175f95c4b1c6fc34e36c56f1e4ddbfLennart Poettering assert(m);
623a4c97b9175f95c4b1c6fc34e36c56f1e4ddbfLennart Poettering
ec2c5e4398f9d65e5dfe61530f2556224733d1e6Lennart Poettering p = strchr(m->hostname, 0);
ec2c5e4398f9d65e5dfe61530f2556224733d1e6Lennart Poettering assert(p);
ec2c5e4398f9d65e5dfe61530f2556224733d1e6Lennart Poettering
ec2c5e4398f9d65e5dfe61530f2556224733d1e6Lennart Poettering while (p > m->hostname) {
ec2c5e4398f9d65e5dfe61530f2556224733d1e6Lennart Poettering if (!strchr("0123456789", p[-1]))
ec2c5e4398f9d65e5dfe61530f2556224733d1e6Lennart Poettering break;
ec2c5e4398f9d65e5dfe61530f2556224733d1e6Lennart Poettering
ec2c5e4398f9d65e5dfe61530f2556224733d1e6Lennart Poettering p--;
ec2c5e4398f9d65e5dfe61530f2556224733d1e6Lennart Poettering }
ec2c5e4398f9d65e5dfe61530f2556224733d1e6Lennart Poettering
ec2c5e4398f9d65e5dfe61530f2556224733d1e6Lennart Poettering if (*p == 0 || safe_atou64(p, &u) < 0 || u <= 0)
ec2c5e4398f9d65e5dfe61530f2556224733d1e6Lennart Poettering u = 1;
ec2c5e4398f9d65e5dfe61530f2556224733d1e6Lennart Poettering
556a22945fcc88ca27ae7ecc46c9bb2727e37895Lennart Poettering /* Add a random number to the old value. This way we can avoid
556a22945fcc88ca27ae7ecc46c9bb2727e37895Lennart Poettering * that two hosts pick the same hostname, win on IPv4 and lose
556a22945fcc88ca27ae7ecc46c9bb2727e37895Lennart Poettering * on IPv6 (or vice versa), and pick the same hostname
556a22945fcc88ca27ae7ecc46c9bb2727e37895Lennart Poettering * replacement hostname, ad infinitum. We still want the
556a22945fcc88ca27ae7ecc46c9bb2727e37895Lennart Poettering * numbers to go up monotonically, hence we just add a random
556a22945fcc88ca27ae7ecc46c9bb2727e37895Lennart Poettering * value 1..10 */
556a22945fcc88ca27ae7ecc46c9bb2727e37895Lennart Poettering
556a22945fcc88ca27ae7ecc46c9bb2727e37895Lennart Poettering random_bytes(&a, sizeof(a));
556a22945fcc88ca27ae7ecc46c9bb2727e37895Lennart Poettering u += 1 + a % 10;
ec2c5e4398f9d65e5dfe61530f2556224733d1e6Lennart Poettering
ec2c5e4398f9d65e5dfe61530f2556224733d1e6Lennart Poettering if (asprintf(&h, "%.*s%" PRIu64, (int) (p - m->hostname), m->hostname, u) < 0)
ec2c5e4398f9d65e5dfe61530f2556224733d1e6Lennart Poettering return -ENOMEM;
ec2c5e4398f9d65e5dfe61530f2556224733d1e6Lennart Poettering
eb60f9cd4e93ff5016dc1b5486fd1b7e1565fd92Lennart Poettering log_info("Hostname conflict, changing published hostname from '%s' to '%s'.", m->hostname, h);
ec2c5e4398f9d65e5dfe61530f2556224733d1e6Lennart Poettering
ec2c5e4398f9d65e5dfe61530f2556224733d1e6Lennart Poettering free(m->hostname);
ec2c5e4398f9d65e5dfe61530f2556224733d1e6Lennart Poettering m->hostname = h;
ec2c5e4398f9d65e5dfe61530f2556224733d1e6Lennart Poettering
eb60f9cd4e93ff5016dc1b5486fd1b7e1565fd92Lennart Poettering manager_refresh_rrs(m);
623a4c97b9175f95c4b1c6fc34e36c56f1e4ddbfLennart Poettering
623a4c97b9175f95c4b1c6fc34e36c56f1e4ddbfLennart Poettering return 0;
623a4c97b9175f95c4b1c6fc34e36c56f1e4ddbfLennart Poettering}
ec2c5e4398f9d65e5dfe61530f2556224733d1e6Lennart Poettering
4e945a6f7971fd7d1f6b2c62ee3afdaff3c95ce4Lennart PoetteringLinkAddress* manager_find_link_address(Manager *m, int family, const union in_addr_union *in_addr) {
ec2c5e4398f9d65e5dfe61530f2556224733d1e6Lennart Poettering Iterator i;
ec2c5e4398f9d65e5dfe61530f2556224733d1e6Lennart Poettering Link *l;
ec2c5e4398f9d65e5dfe61530f2556224733d1e6Lennart Poettering
ec2c5e4398f9d65e5dfe61530f2556224733d1e6Lennart Poettering assert(m);
ec2c5e4398f9d65e5dfe61530f2556224733d1e6Lennart Poettering
ec2c5e4398f9d65e5dfe61530f2556224733d1e6Lennart Poettering HASHMAP_FOREACH(l, m->links, i) {
ec2c5e4398f9d65e5dfe61530f2556224733d1e6Lennart Poettering LinkAddress *a;
ec2c5e4398f9d65e5dfe61530f2556224733d1e6Lennart Poettering
ec2c5e4398f9d65e5dfe61530f2556224733d1e6Lennart Poettering a = link_find_address(l, family, in_addr);
ec2c5e4398f9d65e5dfe61530f2556224733d1e6Lennart Poettering if (a)
ec2c5e4398f9d65e5dfe61530f2556224733d1e6Lennart Poettering return a;
ec2c5e4398f9d65e5dfe61530f2556224733d1e6Lennart Poettering }
ec2c5e4398f9d65e5dfe61530f2556224733d1e6Lennart Poettering
ec2c5e4398f9d65e5dfe61530f2556224733d1e6Lennart Poettering return NULL;
ec2c5e4398f9d65e5dfe61530f2556224733d1e6Lennart Poettering}
ec2c5e4398f9d65e5dfe61530f2556224733d1e6Lennart Poettering
a407657425a3e47fd2b559cd3bc800f791303f63Lennart Poetteringbool manager_our_packet(Manager *m, DnsPacket *p) {
ec2c5e4398f9d65e5dfe61530f2556224733d1e6Lennart Poettering assert(m);
ec2c5e4398f9d65e5dfe61530f2556224733d1e6Lennart Poettering assert(p);
ec2c5e4398f9d65e5dfe61530f2556224733d1e6Lennart Poettering
4e945a6f7971fd7d1f6b2c62ee3afdaff3c95ce4Lennart Poettering return !!manager_find_link_address(m, p->family, &p->sender);
ec2c5e4398f9d65e5dfe61530f2556224733d1e6Lennart Poettering}
4e945a6f7971fd7d1f6b2c62ee3afdaff3c95ce4Lennart Poettering
a407657425a3e47fd2b559cd3bc800f791303f63Lennart PoetteringDnsScope* manager_find_scope(Manager *m, DnsPacket *p) {
a407657425a3e47fd2b559cd3bc800f791303f63Lennart Poettering Link *l;
a407657425a3e47fd2b559cd3bc800f791303f63Lennart Poettering
a407657425a3e47fd2b559cd3bc800f791303f63Lennart Poettering assert(m);
a407657425a3e47fd2b559cd3bc800f791303f63Lennart Poettering assert(p);
a407657425a3e47fd2b559cd3bc800f791303f63Lennart Poettering
a407657425a3e47fd2b559cd3bc800f791303f63Lennart Poettering l = hashmap_get(m->links, INT_TO_PTR(p->ifindex));
a407657425a3e47fd2b559cd3bc800f791303f63Lennart Poettering if (!l)
a407657425a3e47fd2b559cd3bc800f791303f63Lennart Poettering return NULL;
a407657425a3e47fd2b559cd3bc800f791303f63Lennart Poettering
a407657425a3e47fd2b559cd3bc800f791303f63Lennart Poettering if (p->protocol == DNS_PROTOCOL_LLMNR) {
a407657425a3e47fd2b559cd3bc800f791303f63Lennart Poettering if (p->family == AF_INET)
a407657425a3e47fd2b559cd3bc800f791303f63Lennart Poettering return l->llmnr_ipv4_scope;
a407657425a3e47fd2b559cd3bc800f791303f63Lennart Poettering else if (p->family == AF_INET6)
a407657425a3e47fd2b559cd3bc800f791303f63Lennart Poettering return l->llmnr_ipv6_scope;
a407657425a3e47fd2b559cd3bc800f791303f63Lennart Poettering }
a407657425a3e47fd2b559cd3bc800f791303f63Lennart Poettering
a407657425a3e47fd2b559cd3bc800f791303f63Lennart Poettering return NULL;
a407657425a3e47fd2b559cd3bc800f791303f63Lennart Poettering}
a407657425a3e47fd2b559cd3bc800f791303f63Lennart Poettering
902bb5d8abb2a7d258741828d212ca549ab16950Lennart Poetteringvoid manager_verify_all(Manager *m) {
902bb5d8abb2a7d258741828d212ca549ab16950Lennart Poettering DnsScope *s;
902bb5d8abb2a7d258741828d212ca549ab16950Lennart Poettering
902bb5d8abb2a7d258741828d212ca549ab16950Lennart Poettering assert(m);
902bb5d8abb2a7d258741828d212ca549ab16950Lennart Poettering
902bb5d8abb2a7d258741828d212ca549ab16950Lennart Poettering LIST_FOREACH(scopes, s, m->dns_scopes)
902bb5d8abb2a7d258741828d212ca549ab16950Lennart Poettering dns_zone_verify_all(&s->zone);
902bb5d8abb2a7d258741828d212ca549ab16950Lennart Poettering}
902bb5d8abb2a7d258741828d212ca549ab16950Lennart Poettering
3e684349c2cead2e6fd2f816c34eb17daba23a49Lennart Poetteringvoid manager_flush_dns_servers(Manager *m, DnsServerType t) {
3e684349c2cead2e6fd2f816c34eb17daba23a49Lennart Poettering assert(m);
3e684349c2cead2e6fd2f816c34eb17daba23a49Lennart Poettering
3e684349c2cead2e6fd2f816c34eb17daba23a49Lennart Poettering if (t == DNS_SERVER_SYSTEM)
3e684349c2cead2e6fd2f816c34eb17daba23a49Lennart Poettering while (m->dns_servers)
3e684349c2cead2e6fd2f816c34eb17daba23a49Lennart Poettering dns_server_free(m->dns_servers);
3e684349c2cead2e6fd2f816c34eb17daba23a49Lennart Poettering
3e684349c2cead2e6fd2f816c34eb17daba23a49Lennart Poettering if (t == DNS_SERVER_FALLBACK)
3e684349c2cead2e6fd2f816c34eb17daba23a49Lennart Poettering while (m->fallback_dns_servers)
3e684349c2cead2e6fd2f816c34eb17daba23a49Lennart Poettering dns_server_free(m->fallback_dns_servers);
3e684349c2cead2e6fd2f816c34eb17daba23a49Lennart Poettering}
3e684349c2cead2e6fd2f816c34eb17daba23a49Lennart Poettering
4e945a6f7971fd7d1f6b2c62ee3afdaff3c95ce4Lennart Poetteringstatic const char* const support_table[_SUPPORT_MAX] = {
4e945a6f7971fd7d1f6b2c62ee3afdaff3c95ce4Lennart Poettering [SUPPORT_NO] = "no",
4e945a6f7971fd7d1f6b2c62ee3afdaff3c95ce4Lennart Poettering [SUPPORT_YES] = "yes",
4e945a6f7971fd7d1f6b2c62ee3afdaff3c95ce4Lennart Poettering [SUPPORT_RESOLVE] = "resolve",
4e945a6f7971fd7d1f6b2c62ee3afdaff3c95ce4Lennart Poettering};
4e945a6f7971fd7d1f6b2c62ee3afdaff3c95ce4Lennart PoetteringDEFINE_STRING_TABLE_LOOKUP(support, Support);