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