dd0bc0f1414cc1d0fa73a29470bd14944e4942d3Lennart Poettering/***
dd0bc0f1414cc1d0fa73a29470bd14944e4942d3Lennart Poettering This file is part of systemd.
dd0bc0f1414cc1d0fa73a29470bd14944e4942d3Lennart Poettering
dd0bc0f1414cc1d0fa73a29470bd14944e4942d3Lennart Poettering Copyright 2016 Lennart Poettering
dd0bc0f1414cc1d0fa73a29470bd14944e4942d3Lennart Poettering
dd0bc0f1414cc1d0fa73a29470bd14944e4942d3Lennart Poettering systemd is free software; you can redistribute it and/or modify it
dd0bc0f1414cc1d0fa73a29470bd14944e4942d3Lennart Poettering under the terms of the GNU Lesser General Public License as published by
dd0bc0f1414cc1d0fa73a29470bd14944e4942d3Lennart Poettering the Free Software Foundation; either version 2.1 of the License, or
dd0bc0f1414cc1d0fa73a29470bd14944e4942d3Lennart Poettering (at your option) any later version.
dd0bc0f1414cc1d0fa73a29470bd14944e4942d3Lennart Poettering
dd0bc0f1414cc1d0fa73a29470bd14944e4942d3Lennart Poettering systemd is distributed in the hope that it will be useful, but
dd0bc0f1414cc1d0fa73a29470bd14944e4942d3Lennart Poettering WITHOUT ANY WARRANTY; without even the implied warranty of
dd0bc0f1414cc1d0fa73a29470bd14944e4942d3Lennart Poettering MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
dd0bc0f1414cc1d0fa73a29470bd14944e4942d3Lennart Poettering Lesser General Public License for more details.
dd0bc0f1414cc1d0fa73a29470bd14944e4942d3Lennart Poettering
dd0bc0f1414cc1d0fa73a29470bd14944e4942d3Lennart Poettering You should have received a copy of the GNU Lesser General Public License
dd0bc0f1414cc1d0fa73a29470bd14944e4942d3Lennart Poettering along with systemd; If not, see <http://www.gnu.org/licenses/>.
dd0bc0f1414cc1d0fa73a29470bd14944e4942d3Lennart Poettering***/
dd0bc0f1414cc1d0fa73a29470bd14944e4942d3Lennart Poettering
dd0bc0f1414cc1d0fa73a29470bd14944e4942d3Lennart Poettering#include "fd-util.h"
dd0bc0f1414cc1d0fa73a29470bd14944e4942d3Lennart Poettering#include "fileio.h"
dd0bc0f1414cc1d0fa73a29470bd14944e4942d3Lennart Poettering#include "hostname-util.h"
dd0bc0f1414cc1d0fa73a29470bd14944e4942d3Lennart Poettering#include "resolved-etc-hosts.h"
dd0bc0f1414cc1d0fa73a29470bd14944e4942d3Lennart Poettering#include "resolved-dns-synthesize.h"
dd0bc0f1414cc1d0fa73a29470bd14944e4942d3Lennart Poettering#include "string-util.h"
dd0bc0f1414cc1d0fa73a29470bd14944e4942d3Lennart Poettering#include "strv.h"
dd0bc0f1414cc1d0fa73a29470bd14944e4942d3Lennart Poettering#include "time-util.h"
dd0bc0f1414cc1d0fa73a29470bd14944e4942d3Lennart Poettering
dd0bc0f1414cc1d0fa73a29470bd14944e4942d3Lennart Poettering/* Recheck /etc/hosts at most once every 2s */
dd0bc0f1414cc1d0fa73a29470bd14944e4942d3Lennart Poettering#define ETC_HOSTS_RECHECK_USEC (2*USEC_PER_SEC)
dd0bc0f1414cc1d0fa73a29470bd14944e4942d3Lennart Poettering
dd0bc0f1414cc1d0fa73a29470bd14944e4942d3Lennart Poetteringtypedef struct EtcHostsItem {
dd0bc0f1414cc1d0fa73a29470bd14944e4942d3Lennart Poettering int family;
dd0bc0f1414cc1d0fa73a29470bd14944e4942d3Lennart Poettering union in_addr_union address;
dd0bc0f1414cc1d0fa73a29470bd14944e4942d3Lennart Poettering
dd0bc0f1414cc1d0fa73a29470bd14944e4942d3Lennart Poettering char **names;
dd0bc0f1414cc1d0fa73a29470bd14944e4942d3Lennart Poettering} EtcHostsItem;
dd0bc0f1414cc1d0fa73a29470bd14944e4942d3Lennart Poettering
dd0bc0f1414cc1d0fa73a29470bd14944e4942d3Lennart Poetteringtypedef struct EtcHostsItemByName {
dd0bc0f1414cc1d0fa73a29470bd14944e4942d3Lennart Poettering char *name;
dd0bc0f1414cc1d0fa73a29470bd14944e4942d3Lennart Poettering
dd0bc0f1414cc1d0fa73a29470bd14944e4942d3Lennart Poettering EtcHostsItem **items;
dd0bc0f1414cc1d0fa73a29470bd14944e4942d3Lennart Poettering size_t n_items, n_allocated;
dd0bc0f1414cc1d0fa73a29470bd14944e4942d3Lennart Poettering} EtcHostsItemByName;
dd0bc0f1414cc1d0fa73a29470bd14944e4942d3Lennart Poettering
dd0bc0f1414cc1d0fa73a29470bd14944e4942d3Lennart Poetteringvoid manager_etc_hosts_flush(Manager *m) {
dd0bc0f1414cc1d0fa73a29470bd14944e4942d3Lennart Poettering EtcHostsItem *item;
dd0bc0f1414cc1d0fa73a29470bd14944e4942d3Lennart Poettering EtcHostsItemByName *bn;
dd0bc0f1414cc1d0fa73a29470bd14944e4942d3Lennart Poettering
dd0bc0f1414cc1d0fa73a29470bd14944e4942d3Lennart Poettering while ((item = set_steal_first(m->etc_hosts_by_address))) {
dd0bc0f1414cc1d0fa73a29470bd14944e4942d3Lennart Poettering strv_free(item->names);
dd0bc0f1414cc1d0fa73a29470bd14944e4942d3Lennart Poettering free(item);
dd0bc0f1414cc1d0fa73a29470bd14944e4942d3Lennart Poettering }
dd0bc0f1414cc1d0fa73a29470bd14944e4942d3Lennart Poettering
dd0bc0f1414cc1d0fa73a29470bd14944e4942d3Lennart Poettering while ((bn = hashmap_steal_first(m->etc_hosts_by_name))) {
dd0bc0f1414cc1d0fa73a29470bd14944e4942d3Lennart Poettering free(bn->name);
dd0bc0f1414cc1d0fa73a29470bd14944e4942d3Lennart Poettering free(bn->items);
dd0bc0f1414cc1d0fa73a29470bd14944e4942d3Lennart Poettering free(bn);
dd0bc0f1414cc1d0fa73a29470bd14944e4942d3Lennart Poettering }
dd0bc0f1414cc1d0fa73a29470bd14944e4942d3Lennart Poettering
dd0bc0f1414cc1d0fa73a29470bd14944e4942d3Lennart Poettering m->etc_hosts_by_address = set_free(m->etc_hosts_by_address);
dd0bc0f1414cc1d0fa73a29470bd14944e4942d3Lennart Poettering m->etc_hosts_by_name = hashmap_free(m->etc_hosts_by_name);
dd0bc0f1414cc1d0fa73a29470bd14944e4942d3Lennart Poettering
dd0bc0f1414cc1d0fa73a29470bd14944e4942d3Lennart Poettering m->etc_hosts_mtime = USEC_INFINITY;
dd0bc0f1414cc1d0fa73a29470bd14944e4942d3Lennart Poettering}
dd0bc0f1414cc1d0fa73a29470bd14944e4942d3Lennart Poettering
dd0bc0f1414cc1d0fa73a29470bd14944e4942d3Lennart Poetteringstatic void etc_hosts_item_hash_func(const void *p, struct siphash *state) {
dd0bc0f1414cc1d0fa73a29470bd14944e4942d3Lennart Poettering const EtcHostsItem *item = p;
dd0bc0f1414cc1d0fa73a29470bd14944e4942d3Lennart Poettering
dd0bc0f1414cc1d0fa73a29470bd14944e4942d3Lennart Poettering siphash24_compress(&item->family, sizeof(item->family), state);
dd0bc0f1414cc1d0fa73a29470bd14944e4942d3Lennart Poettering
dd0bc0f1414cc1d0fa73a29470bd14944e4942d3Lennart Poettering if (item->family == AF_INET)
dd0bc0f1414cc1d0fa73a29470bd14944e4942d3Lennart Poettering siphash24_compress(&item->address.in, sizeof(item->address.in), state);
dd0bc0f1414cc1d0fa73a29470bd14944e4942d3Lennart Poettering else if (item->family == AF_INET6)
dd0bc0f1414cc1d0fa73a29470bd14944e4942d3Lennart Poettering siphash24_compress(&item->address.in6, sizeof(item->address.in6), state);
dd0bc0f1414cc1d0fa73a29470bd14944e4942d3Lennart Poettering}
dd0bc0f1414cc1d0fa73a29470bd14944e4942d3Lennart Poettering
dd0bc0f1414cc1d0fa73a29470bd14944e4942d3Lennart Poetteringstatic int etc_hosts_item_compare_func(const void *a, const void *b) {
dd0bc0f1414cc1d0fa73a29470bd14944e4942d3Lennart Poettering const EtcHostsItem *x = a, *y = b;
dd0bc0f1414cc1d0fa73a29470bd14944e4942d3Lennart Poettering
ec76e139d8ce0a1183ae7639ae31a28e7e90791bThomas Hindoe Paaboel Andersen if (x->family != y->family)
dd0bc0f1414cc1d0fa73a29470bd14944e4942d3Lennart Poettering return x->family - y->family;
dd0bc0f1414cc1d0fa73a29470bd14944e4942d3Lennart Poettering
dd0bc0f1414cc1d0fa73a29470bd14944e4942d3Lennart Poettering if (x->family == AF_INET)
dd0bc0f1414cc1d0fa73a29470bd14944e4942d3Lennart Poettering return memcmp(&x->address.in.s_addr, &y->address.in.s_addr, sizeof(struct in_addr));
dd0bc0f1414cc1d0fa73a29470bd14944e4942d3Lennart Poettering
dd0bc0f1414cc1d0fa73a29470bd14944e4942d3Lennart Poettering if (x->family == AF_INET6)
dd0bc0f1414cc1d0fa73a29470bd14944e4942d3Lennart Poettering return memcmp(&x->address.in6.s6_addr, &y->address.in6.s6_addr, sizeof(struct in6_addr));
dd0bc0f1414cc1d0fa73a29470bd14944e4942d3Lennart Poettering
dd0bc0f1414cc1d0fa73a29470bd14944e4942d3Lennart Poettering return trivial_compare_func(a, b);
dd0bc0f1414cc1d0fa73a29470bd14944e4942d3Lennart Poettering}
dd0bc0f1414cc1d0fa73a29470bd14944e4942d3Lennart Poettering
dd0bc0f1414cc1d0fa73a29470bd14944e4942d3Lennart Poetteringstatic const struct hash_ops etc_hosts_item_ops = {
dd0bc0f1414cc1d0fa73a29470bd14944e4942d3Lennart Poettering .hash = etc_hosts_item_hash_func,
dd0bc0f1414cc1d0fa73a29470bd14944e4942d3Lennart Poettering .compare = etc_hosts_item_compare_func,
dd0bc0f1414cc1d0fa73a29470bd14944e4942d3Lennart Poettering};
dd0bc0f1414cc1d0fa73a29470bd14944e4942d3Lennart Poettering
dd0bc0f1414cc1d0fa73a29470bd14944e4942d3Lennart Poetteringstatic int add_item(Manager *m, int family, const union in_addr_union *address, char **names) {
dd0bc0f1414cc1d0fa73a29470bd14944e4942d3Lennart Poettering
dd0bc0f1414cc1d0fa73a29470bd14944e4942d3Lennart Poettering EtcHostsItem key = {
dd0bc0f1414cc1d0fa73a29470bd14944e4942d3Lennart Poettering .family = family,
dd0bc0f1414cc1d0fa73a29470bd14944e4942d3Lennart Poettering .address = *address,
dd0bc0f1414cc1d0fa73a29470bd14944e4942d3Lennart Poettering };
dd0bc0f1414cc1d0fa73a29470bd14944e4942d3Lennart Poettering EtcHostsItem *item;
dd0bc0f1414cc1d0fa73a29470bd14944e4942d3Lennart Poettering char **n;
dd0bc0f1414cc1d0fa73a29470bd14944e4942d3Lennart Poettering int r;
dd0bc0f1414cc1d0fa73a29470bd14944e4942d3Lennart Poettering
dd0bc0f1414cc1d0fa73a29470bd14944e4942d3Lennart Poettering assert(m);
dd0bc0f1414cc1d0fa73a29470bd14944e4942d3Lennart Poettering assert(address);
dd0bc0f1414cc1d0fa73a29470bd14944e4942d3Lennart Poettering
dd0bc0f1414cc1d0fa73a29470bd14944e4942d3Lennart Poettering r = in_addr_is_null(family, address);
dd0bc0f1414cc1d0fa73a29470bd14944e4942d3Lennart Poettering if (r < 0)
dd0bc0f1414cc1d0fa73a29470bd14944e4942d3Lennart Poettering return r;
dd0bc0f1414cc1d0fa73a29470bd14944e4942d3Lennart Poettering if (r > 0)
dd0bc0f1414cc1d0fa73a29470bd14944e4942d3Lennart Poettering /* This is an 0.0.0.0 or :: item, which we assume means that we shall map the specified hostname to
dd0bc0f1414cc1d0fa73a29470bd14944e4942d3Lennart Poettering * nothing. */
dd0bc0f1414cc1d0fa73a29470bd14944e4942d3Lennart Poettering item = NULL;
dd0bc0f1414cc1d0fa73a29470bd14944e4942d3Lennart Poettering else {
dd0bc0f1414cc1d0fa73a29470bd14944e4942d3Lennart Poettering /* If this is a normal address, then, simply add entry mapping it to the specified names */
dd0bc0f1414cc1d0fa73a29470bd14944e4942d3Lennart Poettering
dd0bc0f1414cc1d0fa73a29470bd14944e4942d3Lennart Poettering item = set_get(m->etc_hosts_by_address, &key);
dd0bc0f1414cc1d0fa73a29470bd14944e4942d3Lennart Poettering if (item) {
dd0bc0f1414cc1d0fa73a29470bd14944e4942d3Lennart Poettering r = strv_extend_strv(&item->names, names, true);
dd0bc0f1414cc1d0fa73a29470bd14944e4942d3Lennart Poettering if (r < 0)
dd0bc0f1414cc1d0fa73a29470bd14944e4942d3Lennart Poettering return log_oom();
dd0bc0f1414cc1d0fa73a29470bd14944e4942d3Lennart Poettering } else {
dd0bc0f1414cc1d0fa73a29470bd14944e4942d3Lennart Poettering
dd0bc0f1414cc1d0fa73a29470bd14944e4942d3Lennart Poettering r = set_ensure_allocated(&m->etc_hosts_by_address, &etc_hosts_item_ops);
dd0bc0f1414cc1d0fa73a29470bd14944e4942d3Lennart Poettering if (r < 0)
dd0bc0f1414cc1d0fa73a29470bd14944e4942d3Lennart Poettering return log_oom();
dd0bc0f1414cc1d0fa73a29470bd14944e4942d3Lennart Poettering
dd0bc0f1414cc1d0fa73a29470bd14944e4942d3Lennart Poettering item = new0(EtcHostsItem, 1);
dd0bc0f1414cc1d0fa73a29470bd14944e4942d3Lennart Poettering if (!item)
dd0bc0f1414cc1d0fa73a29470bd14944e4942d3Lennart Poettering return log_oom();
dd0bc0f1414cc1d0fa73a29470bd14944e4942d3Lennart Poettering
dd0bc0f1414cc1d0fa73a29470bd14944e4942d3Lennart Poettering item->family = family;
dd0bc0f1414cc1d0fa73a29470bd14944e4942d3Lennart Poettering item->address = *address;
dd0bc0f1414cc1d0fa73a29470bd14944e4942d3Lennart Poettering item->names = names;
dd0bc0f1414cc1d0fa73a29470bd14944e4942d3Lennart Poettering
dd0bc0f1414cc1d0fa73a29470bd14944e4942d3Lennart Poettering r = set_put(m->etc_hosts_by_address, item);
dd0bc0f1414cc1d0fa73a29470bd14944e4942d3Lennart Poettering if (r < 0) {
dd0bc0f1414cc1d0fa73a29470bd14944e4942d3Lennart Poettering free(item);
dd0bc0f1414cc1d0fa73a29470bd14944e4942d3Lennart Poettering return log_oom();
dd0bc0f1414cc1d0fa73a29470bd14944e4942d3Lennart Poettering }
dd0bc0f1414cc1d0fa73a29470bd14944e4942d3Lennart Poettering }
dd0bc0f1414cc1d0fa73a29470bd14944e4942d3Lennart Poettering }
dd0bc0f1414cc1d0fa73a29470bd14944e4942d3Lennart Poettering
dd0bc0f1414cc1d0fa73a29470bd14944e4942d3Lennart Poettering STRV_FOREACH(n, names) {
dd0bc0f1414cc1d0fa73a29470bd14944e4942d3Lennart Poettering EtcHostsItemByName *bn;
dd0bc0f1414cc1d0fa73a29470bd14944e4942d3Lennart Poettering
dd0bc0f1414cc1d0fa73a29470bd14944e4942d3Lennart Poettering bn = hashmap_get(m->etc_hosts_by_name, *n);
dd0bc0f1414cc1d0fa73a29470bd14944e4942d3Lennart Poettering if (!bn) {
dd0bc0f1414cc1d0fa73a29470bd14944e4942d3Lennart Poettering r = hashmap_ensure_allocated(&m->etc_hosts_by_name, &dns_name_hash_ops);
dd0bc0f1414cc1d0fa73a29470bd14944e4942d3Lennart Poettering if (r < 0)
dd0bc0f1414cc1d0fa73a29470bd14944e4942d3Lennart Poettering return log_oom();
dd0bc0f1414cc1d0fa73a29470bd14944e4942d3Lennart Poettering
dd0bc0f1414cc1d0fa73a29470bd14944e4942d3Lennart Poettering bn = new0(EtcHostsItemByName, 1);
dd0bc0f1414cc1d0fa73a29470bd14944e4942d3Lennart Poettering if (!bn)
dd0bc0f1414cc1d0fa73a29470bd14944e4942d3Lennart Poettering return log_oom();
dd0bc0f1414cc1d0fa73a29470bd14944e4942d3Lennart Poettering
dd0bc0f1414cc1d0fa73a29470bd14944e4942d3Lennart Poettering bn->name = strdup(*n);
dd0bc0f1414cc1d0fa73a29470bd14944e4942d3Lennart Poettering if (!bn->name) {
dd0bc0f1414cc1d0fa73a29470bd14944e4942d3Lennart Poettering free(bn);
dd0bc0f1414cc1d0fa73a29470bd14944e4942d3Lennart Poettering return log_oom();
dd0bc0f1414cc1d0fa73a29470bd14944e4942d3Lennart Poettering }
dd0bc0f1414cc1d0fa73a29470bd14944e4942d3Lennart Poettering
dd0bc0f1414cc1d0fa73a29470bd14944e4942d3Lennart Poettering r = hashmap_put(m->etc_hosts_by_name, bn->name, bn);
dd0bc0f1414cc1d0fa73a29470bd14944e4942d3Lennart Poettering if (r < 0) {
dd0bc0f1414cc1d0fa73a29470bd14944e4942d3Lennart Poettering free(bn->name);
dd0bc0f1414cc1d0fa73a29470bd14944e4942d3Lennart Poettering free(bn);
dd0bc0f1414cc1d0fa73a29470bd14944e4942d3Lennart Poettering return log_oom();
dd0bc0f1414cc1d0fa73a29470bd14944e4942d3Lennart Poettering }
dd0bc0f1414cc1d0fa73a29470bd14944e4942d3Lennart Poettering }
dd0bc0f1414cc1d0fa73a29470bd14944e4942d3Lennart Poettering
dd0bc0f1414cc1d0fa73a29470bd14944e4942d3Lennart Poettering if (item) {
dd0bc0f1414cc1d0fa73a29470bd14944e4942d3Lennart Poettering if (!GREEDY_REALLOC(bn->items, bn->n_allocated, bn->n_items+1))
dd0bc0f1414cc1d0fa73a29470bd14944e4942d3Lennart Poettering return log_oom();
dd0bc0f1414cc1d0fa73a29470bd14944e4942d3Lennart Poettering
dd0bc0f1414cc1d0fa73a29470bd14944e4942d3Lennart Poettering bn->items[bn->n_items++] = item;
dd0bc0f1414cc1d0fa73a29470bd14944e4942d3Lennart Poettering }
dd0bc0f1414cc1d0fa73a29470bd14944e4942d3Lennart Poettering }
dd0bc0f1414cc1d0fa73a29470bd14944e4942d3Lennart Poettering
dd0bc0f1414cc1d0fa73a29470bd14944e4942d3Lennart Poettering return 0;
dd0bc0f1414cc1d0fa73a29470bd14944e4942d3Lennart Poettering}
dd0bc0f1414cc1d0fa73a29470bd14944e4942d3Lennart Poettering
dd0bc0f1414cc1d0fa73a29470bd14944e4942d3Lennart Poetteringstatic int parse_line(Manager *m, unsigned nr, const char *line) {
dd0bc0f1414cc1d0fa73a29470bd14944e4942d3Lennart Poettering _cleanup_free_ char *address = NULL;
dd0bc0f1414cc1d0fa73a29470bd14944e4942d3Lennart Poettering _cleanup_strv_free_ char **names = NULL;
dd0bc0f1414cc1d0fa73a29470bd14944e4942d3Lennart Poettering union in_addr_union in;
dd0bc0f1414cc1d0fa73a29470bd14944e4942d3Lennart Poettering bool suppressed = false;
dd0bc0f1414cc1d0fa73a29470bd14944e4942d3Lennart Poettering int family, r;
dd0bc0f1414cc1d0fa73a29470bd14944e4942d3Lennart Poettering
dd0bc0f1414cc1d0fa73a29470bd14944e4942d3Lennart Poettering assert(m);
dd0bc0f1414cc1d0fa73a29470bd14944e4942d3Lennart Poettering assert(line);
dd0bc0f1414cc1d0fa73a29470bd14944e4942d3Lennart Poettering
dd0bc0f1414cc1d0fa73a29470bd14944e4942d3Lennart Poettering r = extract_first_word(&line, &address, NULL, EXTRACT_RELAX);
dd0bc0f1414cc1d0fa73a29470bd14944e4942d3Lennart Poettering if (r < 0)
dd0bc0f1414cc1d0fa73a29470bd14944e4942d3Lennart Poettering return log_error_errno(r, "Couldn't extract address, in line /etc/hosts:%u.", nr);
dd0bc0f1414cc1d0fa73a29470bd14944e4942d3Lennart Poettering if (r == 0) {
dd0bc0f1414cc1d0fa73a29470bd14944e4942d3Lennart Poettering log_error("Premature end of line, in line /etc/hosts:%u.", nr);
dd0bc0f1414cc1d0fa73a29470bd14944e4942d3Lennart Poettering return -EINVAL;
dd0bc0f1414cc1d0fa73a29470bd14944e4942d3Lennart Poettering }
dd0bc0f1414cc1d0fa73a29470bd14944e4942d3Lennart Poettering
dd0bc0f1414cc1d0fa73a29470bd14944e4942d3Lennart Poettering r = in_addr_from_string_auto(address, &family, &in);
dd0bc0f1414cc1d0fa73a29470bd14944e4942d3Lennart Poettering if (r < 0)
dd0bc0f1414cc1d0fa73a29470bd14944e4942d3Lennart Poettering return log_error_errno(r, "Address '%s' is invalid, in line /etc/hosts:%u.", address, nr);
dd0bc0f1414cc1d0fa73a29470bd14944e4942d3Lennart Poettering
dd0bc0f1414cc1d0fa73a29470bd14944e4942d3Lennart Poettering for (;;) {
dd0bc0f1414cc1d0fa73a29470bd14944e4942d3Lennart Poettering _cleanup_free_ char *name = NULL;
dd0bc0f1414cc1d0fa73a29470bd14944e4942d3Lennart Poettering
dd0bc0f1414cc1d0fa73a29470bd14944e4942d3Lennart Poettering r = extract_first_word(&line, &name, NULL, EXTRACT_RELAX);
dd0bc0f1414cc1d0fa73a29470bd14944e4942d3Lennart Poettering if (r < 0)
dd0bc0f1414cc1d0fa73a29470bd14944e4942d3Lennart Poettering return log_error_errno(r, "Couldn't extract host name, in line /etc/hosts:%u.", nr);
dd0bc0f1414cc1d0fa73a29470bd14944e4942d3Lennart Poettering if (r == 0)
dd0bc0f1414cc1d0fa73a29470bd14944e4942d3Lennart Poettering break;
dd0bc0f1414cc1d0fa73a29470bd14944e4942d3Lennart Poettering
dd0bc0f1414cc1d0fa73a29470bd14944e4942d3Lennart Poettering r = dns_name_is_valid(name);
dd0bc0f1414cc1d0fa73a29470bd14944e4942d3Lennart Poettering if (r <= 0)
dd0bc0f1414cc1d0fa73a29470bd14944e4942d3Lennart Poettering return log_error_errno(r, "Hostname %s is not valid, ignoring, in line /etc/hosts:%u.", name, nr);
dd0bc0f1414cc1d0fa73a29470bd14944e4942d3Lennart Poettering
dd0bc0f1414cc1d0fa73a29470bd14944e4942d3Lennart Poettering if (is_localhost(name)) {
dd0bc0f1414cc1d0fa73a29470bd14944e4942d3Lennart Poettering /* Suppress the "localhost" line that is often seen */
dd0bc0f1414cc1d0fa73a29470bd14944e4942d3Lennart Poettering suppressed = true;
dd0bc0f1414cc1d0fa73a29470bd14944e4942d3Lennart Poettering continue;
dd0bc0f1414cc1d0fa73a29470bd14944e4942d3Lennart Poettering }
dd0bc0f1414cc1d0fa73a29470bd14944e4942d3Lennart Poettering
dd0bc0f1414cc1d0fa73a29470bd14944e4942d3Lennart Poettering r = strv_push(&names, name);
dd0bc0f1414cc1d0fa73a29470bd14944e4942d3Lennart Poettering if (r < 0)
dd0bc0f1414cc1d0fa73a29470bd14944e4942d3Lennart Poettering return log_oom();
dd0bc0f1414cc1d0fa73a29470bd14944e4942d3Lennart Poettering
dd0bc0f1414cc1d0fa73a29470bd14944e4942d3Lennart Poettering name = NULL;
dd0bc0f1414cc1d0fa73a29470bd14944e4942d3Lennart Poettering }
dd0bc0f1414cc1d0fa73a29470bd14944e4942d3Lennart Poettering
dd0bc0f1414cc1d0fa73a29470bd14944e4942d3Lennart Poettering if (strv_isempty(names)) {
dd0bc0f1414cc1d0fa73a29470bd14944e4942d3Lennart Poettering
dd0bc0f1414cc1d0fa73a29470bd14944e4942d3Lennart Poettering if (suppressed)
dd0bc0f1414cc1d0fa73a29470bd14944e4942d3Lennart Poettering return 0;
dd0bc0f1414cc1d0fa73a29470bd14944e4942d3Lennart Poettering
dd0bc0f1414cc1d0fa73a29470bd14944e4942d3Lennart Poettering log_error("Line is missing any host names, in line /etc/hosts:%u.", nr);
dd0bc0f1414cc1d0fa73a29470bd14944e4942d3Lennart Poettering return -EINVAL;
dd0bc0f1414cc1d0fa73a29470bd14944e4942d3Lennart Poettering }
dd0bc0f1414cc1d0fa73a29470bd14944e4942d3Lennart Poettering
dd0bc0f1414cc1d0fa73a29470bd14944e4942d3Lennart Poettering /* Takes possession of the names strv */
dd0bc0f1414cc1d0fa73a29470bd14944e4942d3Lennart Poettering r = add_item(m, family, &in, names);
dd0bc0f1414cc1d0fa73a29470bd14944e4942d3Lennart Poettering if (r < 0)
dd0bc0f1414cc1d0fa73a29470bd14944e4942d3Lennart Poettering return r;
dd0bc0f1414cc1d0fa73a29470bd14944e4942d3Lennart Poettering
dd0bc0f1414cc1d0fa73a29470bd14944e4942d3Lennart Poettering names = NULL;
dd0bc0f1414cc1d0fa73a29470bd14944e4942d3Lennart Poettering return r;
dd0bc0f1414cc1d0fa73a29470bd14944e4942d3Lennart Poettering}
dd0bc0f1414cc1d0fa73a29470bd14944e4942d3Lennart Poettering
dd0bc0f1414cc1d0fa73a29470bd14944e4942d3Lennart Poetteringint manager_etc_hosts_read(Manager *m) {
dd0bc0f1414cc1d0fa73a29470bd14944e4942d3Lennart Poettering _cleanup_fclose_ FILE *f = NULL;
dd0bc0f1414cc1d0fa73a29470bd14944e4942d3Lennart Poettering char line[LINE_MAX];
dd0bc0f1414cc1d0fa73a29470bd14944e4942d3Lennart Poettering struct stat st;
dd0bc0f1414cc1d0fa73a29470bd14944e4942d3Lennart Poettering usec_t ts;
dd0bc0f1414cc1d0fa73a29470bd14944e4942d3Lennart Poettering unsigned nr = 0;
dd0bc0f1414cc1d0fa73a29470bd14944e4942d3Lennart Poettering int r;
dd0bc0f1414cc1d0fa73a29470bd14944e4942d3Lennart Poettering
dd0bc0f1414cc1d0fa73a29470bd14944e4942d3Lennart Poettering assert_se(sd_event_now(m->event, clock_boottime_or_monotonic(), &ts) >= 0);
dd0bc0f1414cc1d0fa73a29470bd14944e4942d3Lennart Poettering
dd0bc0f1414cc1d0fa73a29470bd14944e4942d3Lennart Poettering /* See if we checked /etc/hosts recently already */
dd0bc0f1414cc1d0fa73a29470bd14944e4942d3Lennart Poettering if (m->etc_hosts_last != USEC_INFINITY && m->etc_hosts_last + ETC_HOSTS_RECHECK_USEC > ts)
dd0bc0f1414cc1d0fa73a29470bd14944e4942d3Lennart Poettering return 0;
dd0bc0f1414cc1d0fa73a29470bd14944e4942d3Lennart Poettering
dd0bc0f1414cc1d0fa73a29470bd14944e4942d3Lennart Poettering m->etc_hosts_last = ts;
dd0bc0f1414cc1d0fa73a29470bd14944e4942d3Lennart Poettering
dd0bc0f1414cc1d0fa73a29470bd14944e4942d3Lennart Poettering if (m->etc_hosts_mtime != USEC_INFINITY) {
dd0bc0f1414cc1d0fa73a29470bd14944e4942d3Lennart Poettering if (stat("/etc/hosts", &st) < 0) {
dd0bc0f1414cc1d0fa73a29470bd14944e4942d3Lennart Poettering if (errno == ENOENT) {
dd0bc0f1414cc1d0fa73a29470bd14944e4942d3Lennart Poettering r = 0;
dd0bc0f1414cc1d0fa73a29470bd14944e4942d3Lennart Poettering goto clear;
dd0bc0f1414cc1d0fa73a29470bd14944e4942d3Lennart Poettering }
dd0bc0f1414cc1d0fa73a29470bd14944e4942d3Lennart Poettering
dd0bc0f1414cc1d0fa73a29470bd14944e4942d3Lennart Poettering return log_error_errno(errno, "Failed to stat /etc/hosts: %m");
dd0bc0f1414cc1d0fa73a29470bd14944e4942d3Lennart Poettering }
dd0bc0f1414cc1d0fa73a29470bd14944e4942d3Lennart Poettering
dd0bc0f1414cc1d0fa73a29470bd14944e4942d3Lennart Poettering /* Did the mtime change? If not, there's no point in re-reading the file. */
dd0bc0f1414cc1d0fa73a29470bd14944e4942d3Lennart Poettering if (timespec_load(&st.st_mtim) == m->etc_hosts_mtime)
dd0bc0f1414cc1d0fa73a29470bd14944e4942d3Lennart Poettering return 0;
dd0bc0f1414cc1d0fa73a29470bd14944e4942d3Lennart Poettering }
dd0bc0f1414cc1d0fa73a29470bd14944e4942d3Lennart Poettering
dd0bc0f1414cc1d0fa73a29470bd14944e4942d3Lennart Poettering f = fopen("/etc/hosts", "re");
dd0bc0f1414cc1d0fa73a29470bd14944e4942d3Lennart Poettering if (!f) {
dd0bc0f1414cc1d0fa73a29470bd14944e4942d3Lennart Poettering if (errno == ENOENT) {
dd0bc0f1414cc1d0fa73a29470bd14944e4942d3Lennart Poettering r = 0;
dd0bc0f1414cc1d0fa73a29470bd14944e4942d3Lennart Poettering goto clear;
dd0bc0f1414cc1d0fa73a29470bd14944e4942d3Lennart Poettering }
dd0bc0f1414cc1d0fa73a29470bd14944e4942d3Lennart Poettering
dd0bc0f1414cc1d0fa73a29470bd14944e4942d3Lennart Poettering return log_error_errno(errno, "Failed to open /etc/hosts: %m");
dd0bc0f1414cc1d0fa73a29470bd14944e4942d3Lennart Poettering }
dd0bc0f1414cc1d0fa73a29470bd14944e4942d3Lennart Poettering
dd0bc0f1414cc1d0fa73a29470bd14944e4942d3Lennart Poettering /* Take the timestamp at the beginning of processing, so that any changes made later are read on the next
dd0bc0f1414cc1d0fa73a29470bd14944e4942d3Lennart Poettering * invocation */
dd0bc0f1414cc1d0fa73a29470bd14944e4942d3Lennart Poettering r = fstat(fileno(f), &st);
dd0bc0f1414cc1d0fa73a29470bd14944e4942d3Lennart Poettering if (r < 0)
dd0bc0f1414cc1d0fa73a29470bd14944e4942d3Lennart Poettering return log_error_errno(errno, "Failed to fstat() /etc/hosts: %m");
dd0bc0f1414cc1d0fa73a29470bd14944e4942d3Lennart Poettering
dd0bc0f1414cc1d0fa73a29470bd14944e4942d3Lennart Poettering manager_etc_hosts_flush(m);
dd0bc0f1414cc1d0fa73a29470bd14944e4942d3Lennart Poettering
dd0bc0f1414cc1d0fa73a29470bd14944e4942d3Lennart Poettering FOREACH_LINE(line, f, return log_error_errno(errno, "Failed to read /etc/hosts: %m")) {
dd0bc0f1414cc1d0fa73a29470bd14944e4942d3Lennart Poettering char *l;
dd0bc0f1414cc1d0fa73a29470bd14944e4942d3Lennart Poettering
dd0bc0f1414cc1d0fa73a29470bd14944e4942d3Lennart Poettering nr ++;
dd0bc0f1414cc1d0fa73a29470bd14944e4942d3Lennart Poettering
dd0bc0f1414cc1d0fa73a29470bd14944e4942d3Lennart Poettering l = strstrip(line);
dd0bc0f1414cc1d0fa73a29470bd14944e4942d3Lennart Poettering if (isempty(l))
dd0bc0f1414cc1d0fa73a29470bd14944e4942d3Lennart Poettering continue;
dd0bc0f1414cc1d0fa73a29470bd14944e4942d3Lennart Poettering if (l[0] == '#')
dd0bc0f1414cc1d0fa73a29470bd14944e4942d3Lennart Poettering continue;
dd0bc0f1414cc1d0fa73a29470bd14944e4942d3Lennart Poettering
dd0bc0f1414cc1d0fa73a29470bd14944e4942d3Lennart Poettering r = parse_line(m, nr, l);
dd0bc0f1414cc1d0fa73a29470bd14944e4942d3Lennart Poettering if (r == -ENOMEM) /* On OOM we abandon the half-built-up structure. All other errors we ignore and proceed */
dd0bc0f1414cc1d0fa73a29470bd14944e4942d3Lennart Poettering goto clear;
dd0bc0f1414cc1d0fa73a29470bd14944e4942d3Lennart Poettering }
dd0bc0f1414cc1d0fa73a29470bd14944e4942d3Lennart Poettering
dd0bc0f1414cc1d0fa73a29470bd14944e4942d3Lennart Poettering m->etc_hosts_mtime = timespec_load(&st.st_mtim);
dd0bc0f1414cc1d0fa73a29470bd14944e4942d3Lennart Poettering m->etc_hosts_last = ts;
dd0bc0f1414cc1d0fa73a29470bd14944e4942d3Lennart Poettering
dd0bc0f1414cc1d0fa73a29470bd14944e4942d3Lennart Poettering return 1;
dd0bc0f1414cc1d0fa73a29470bd14944e4942d3Lennart Poettering
dd0bc0f1414cc1d0fa73a29470bd14944e4942d3Lennart Poetteringclear:
dd0bc0f1414cc1d0fa73a29470bd14944e4942d3Lennart Poettering manager_etc_hosts_flush(m);
dd0bc0f1414cc1d0fa73a29470bd14944e4942d3Lennart Poettering return r;
dd0bc0f1414cc1d0fa73a29470bd14944e4942d3Lennart Poettering}
dd0bc0f1414cc1d0fa73a29470bd14944e4942d3Lennart Poettering
dd0bc0f1414cc1d0fa73a29470bd14944e4942d3Lennart Poetteringint manager_etc_hosts_lookup(Manager *m, DnsQuestion* q, DnsAnswer **answer) {
dd0bc0f1414cc1d0fa73a29470bd14944e4942d3Lennart Poettering bool found_a = false, found_aaaa = false;
dd0bc0f1414cc1d0fa73a29470bd14944e4942d3Lennart Poettering EtcHostsItemByName *bn;
dd0bc0f1414cc1d0fa73a29470bd14944e4942d3Lennart Poettering EtcHostsItem k = {};
dd0bc0f1414cc1d0fa73a29470bd14944e4942d3Lennart Poettering DnsResourceKey *t;
dd0bc0f1414cc1d0fa73a29470bd14944e4942d3Lennart Poettering const char *name;
dd0bc0f1414cc1d0fa73a29470bd14944e4942d3Lennart Poettering unsigned i;
dd0bc0f1414cc1d0fa73a29470bd14944e4942d3Lennart Poettering int r;
dd0bc0f1414cc1d0fa73a29470bd14944e4942d3Lennart Poettering
dd0bc0f1414cc1d0fa73a29470bd14944e4942d3Lennart Poettering assert(m);
dd0bc0f1414cc1d0fa73a29470bd14944e4942d3Lennart Poettering assert(q);
dd0bc0f1414cc1d0fa73a29470bd14944e4942d3Lennart Poettering assert(answer);
dd0bc0f1414cc1d0fa73a29470bd14944e4942d3Lennart Poettering
dd0bc0f1414cc1d0fa73a29470bd14944e4942d3Lennart Poettering r = manager_etc_hosts_read(m);
dd0bc0f1414cc1d0fa73a29470bd14944e4942d3Lennart Poettering if (r < 0)
dd0bc0f1414cc1d0fa73a29470bd14944e4942d3Lennart Poettering return r;
dd0bc0f1414cc1d0fa73a29470bd14944e4942d3Lennart Poettering
dd0bc0f1414cc1d0fa73a29470bd14944e4942d3Lennart Poettering name = dns_question_first_name(q);
dd0bc0f1414cc1d0fa73a29470bd14944e4942d3Lennart Poettering if (!name)
dd0bc0f1414cc1d0fa73a29470bd14944e4942d3Lennart Poettering return 0;
dd0bc0f1414cc1d0fa73a29470bd14944e4942d3Lennart Poettering
dd0bc0f1414cc1d0fa73a29470bd14944e4942d3Lennart Poettering r = dns_name_address(name, &k.family, &k.address);
dd0bc0f1414cc1d0fa73a29470bd14944e4942d3Lennart Poettering if (r > 0) {
dd0bc0f1414cc1d0fa73a29470bd14944e4942d3Lennart Poettering EtcHostsItem *item;
dd0bc0f1414cc1d0fa73a29470bd14944e4942d3Lennart Poettering DnsResourceKey *found_ptr = NULL;
dd0bc0f1414cc1d0fa73a29470bd14944e4942d3Lennart Poettering
dd0bc0f1414cc1d0fa73a29470bd14944e4942d3Lennart Poettering item = set_get(m->etc_hosts_by_address, &k);
dd0bc0f1414cc1d0fa73a29470bd14944e4942d3Lennart Poettering if (!item)
dd0bc0f1414cc1d0fa73a29470bd14944e4942d3Lennart Poettering return 0;
dd0bc0f1414cc1d0fa73a29470bd14944e4942d3Lennart Poettering
dd0bc0f1414cc1d0fa73a29470bd14944e4942d3Lennart Poettering /* We have an address in /etc/hosts that matches the queried name. Let's return successful. Actual data
dd0bc0f1414cc1d0fa73a29470bd14944e4942d3Lennart Poettering * we'll only return if the request was for PTR. */
dd0bc0f1414cc1d0fa73a29470bd14944e4942d3Lennart Poettering
dd0bc0f1414cc1d0fa73a29470bd14944e4942d3Lennart Poettering DNS_QUESTION_FOREACH(t, q) {
dd0bc0f1414cc1d0fa73a29470bd14944e4942d3Lennart Poettering if (!IN_SET(t->type, DNS_TYPE_PTR, DNS_TYPE_ANY))
dd0bc0f1414cc1d0fa73a29470bd14944e4942d3Lennart Poettering continue;
dd0bc0f1414cc1d0fa73a29470bd14944e4942d3Lennart Poettering if (!IN_SET(t->class, DNS_CLASS_IN, DNS_CLASS_ANY))
dd0bc0f1414cc1d0fa73a29470bd14944e4942d3Lennart Poettering continue;
dd0bc0f1414cc1d0fa73a29470bd14944e4942d3Lennart Poettering
dd0bc0f1414cc1d0fa73a29470bd14944e4942d3Lennart Poettering r = dns_name_equal(DNS_RESOURCE_KEY_NAME(t), name);
dd0bc0f1414cc1d0fa73a29470bd14944e4942d3Lennart Poettering if (r < 0)
dd0bc0f1414cc1d0fa73a29470bd14944e4942d3Lennart Poettering return r;
dd0bc0f1414cc1d0fa73a29470bd14944e4942d3Lennart Poettering if (r > 0) {
dd0bc0f1414cc1d0fa73a29470bd14944e4942d3Lennart Poettering found_ptr = t;
dd0bc0f1414cc1d0fa73a29470bd14944e4942d3Lennart Poettering break;
dd0bc0f1414cc1d0fa73a29470bd14944e4942d3Lennart Poettering }
dd0bc0f1414cc1d0fa73a29470bd14944e4942d3Lennart Poettering }
dd0bc0f1414cc1d0fa73a29470bd14944e4942d3Lennart Poettering
dd0bc0f1414cc1d0fa73a29470bd14944e4942d3Lennart Poettering if (found_ptr) {
dd0bc0f1414cc1d0fa73a29470bd14944e4942d3Lennart Poettering char **n;
dd0bc0f1414cc1d0fa73a29470bd14944e4942d3Lennart Poettering
dd0bc0f1414cc1d0fa73a29470bd14944e4942d3Lennart Poettering r = dns_answer_reserve(answer, strv_length(item->names));
dd0bc0f1414cc1d0fa73a29470bd14944e4942d3Lennart Poettering if (r < 0)
dd0bc0f1414cc1d0fa73a29470bd14944e4942d3Lennart Poettering return r;
dd0bc0f1414cc1d0fa73a29470bd14944e4942d3Lennart Poettering
dd0bc0f1414cc1d0fa73a29470bd14944e4942d3Lennart Poettering STRV_FOREACH(n, item->names) {
dd0bc0f1414cc1d0fa73a29470bd14944e4942d3Lennart Poettering _cleanup_(dns_resource_record_unrefp) DnsResourceRecord *rr = NULL;
dd0bc0f1414cc1d0fa73a29470bd14944e4942d3Lennart Poettering
dd0bc0f1414cc1d0fa73a29470bd14944e4942d3Lennart Poettering rr = dns_resource_record_new(found_ptr);
dd0bc0f1414cc1d0fa73a29470bd14944e4942d3Lennart Poettering if (!rr)
dd0bc0f1414cc1d0fa73a29470bd14944e4942d3Lennart Poettering return -ENOMEM;
dd0bc0f1414cc1d0fa73a29470bd14944e4942d3Lennart Poettering
dd0bc0f1414cc1d0fa73a29470bd14944e4942d3Lennart Poettering rr->ptr.name = strdup(*n);
dd0bc0f1414cc1d0fa73a29470bd14944e4942d3Lennart Poettering if (!rr->ptr.name)
dd0bc0f1414cc1d0fa73a29470bd14944e4942d3Lennart Poettering return -ENOMEM;
dd0bc0f1414cc1d0fa73a29470bd14944e4942d3Lennart Poettering
dd0bc0f1414cc1d0fa73a29470bd14944e4942d3Lennart Poettering r = dns_answer_add(*answer, rr, 0, DNS_ANSWER_AUTHENTICATED);
dd0bc0f1414cc1d0fa73a29470bd14944e4942d3Lennart Poettering if (r < 0)
dd0bc0f1414cc1d0fa73a29470bd14944e4942d3Lennart Poettering return r;
dd0bc0f1414cc1d0fa73a29470bd14944e4942d3Lennart Poettering }
dd0bc0f1414cc1d0fa73a29470bd14944e4942d3Lennart Poettering }
dd0bc0f1414cc1d0fa73a29470bd14944e4942d3Lennart Poettering
dd0bc0f1414cc1d0fa73a29470bd14944e4942d3Lennart Poettering return 1;
dd0bc0f1414cc1d0fa73a29470bd14944e4942d3Lennart Poettering }
dd0bc0f1414cc1d0fa73a29470bd14944e4942d3Lennart Poettering
dd0bc0f1414cc1d0fa73a29470bd14944e4942d3Lennart Poettering bn = hashmap_get(m->etc_hosts_by_name, name);
dd0bc0f1414cc1d0fa73a29470bd14944e4942d3Lennart Poettering if (!bn)
dd0bc0f1414cc1d0fa73a29470bd14944e4942d3Lennart Poettering return 0;
dd0bc0f1414cc1d0fa73a29470bd14944e4942d3Lennart Poettering
dd0bc0f1414cc1d0fa73a29470bd14944e4942d3Lennart Poettering r = dns_answer_reserve(answer, bn->n_items);
dd0bc0f1414cc1d0fa73a29470bd14944e4942d3Lennart Poettering if (r < 0)
dd0bc0f1414cc1d0fa73a29470bd14944e4942d3Lennart Poettering return r;
dd0bc0f1414cc1d0fa73a29470bd14944e4942d3Lennart Poettering
dd0bc0f1414cc1d0fa73a29470bd14944e4942d3Lennart Poettering DNS_QUESTION_FOREACH(t, q) {
dd0bc0f1414cc1d0fa73a29470bd14944e4942d3Lennart Poettering if (!IN_SET(t->type, DNS_TYPE_A, DNS_TYPE_AAAA, DNS_TYPE_ANY))
dd0bc0f1414cc1d0fa73a29470bd14944e4942d3Lennart Poettering continue;
dd0bc0f1414cc1d0fa73a29470bd14944e4942d3Lennart Poettering if (!IN_SET(t->class, DNS_CLASS_IN, DNS_CLASS_ANY))
dd0bc0f1414cc1d0fa73a29470bd14944e4942d3Lennart Poettering continue;
dd0bc0f1414cc1d0fa73a29470bd14944e4942d3Lennart Poettering
dd0bc0f1414cc1d0fa73a29470bd14944e4942d3Lennart Poettering r = dns_name_equal(DNS_RESOURCE_KEY_NAME(t), name);
dd0bc0f1414cc1d0fa73a29470bd14944e4942d3Lennart Poettering if (r < 0)
dd0bc0f1414cc1d0fa73a29470bd14944e4942d3Lennart Poettering return r;
dd0bc0f1414cc1d0fa73a29470bd14944e4942d3Lennart Poettering if (r == 0)
dd0bc0f1414cc1d0fa73a29470bd14944e4942d3Lennart Poettering continue;
dd0bc0f1414cc1d0fa73a29470bd14944e4942d3Lennart Poettering
dd0bc0f1414cc1d0fa73a29470bd14944e4942d3Lennart Poettering if (IN_SET(t->type, DNS_TYPE_A, DNS_TYPE_ANY))
dd0bc0f1414cc1d0fa73a29470bd14944e4942d3Lennart Poettering found_a = true;
dd0bc0f1414cc1d0fa73a29470bd14944e4942d3Lennart Poettering if (IN_SET(t->type, DNS_TYPE_AAAA, DNS_TYPE_ANY))
dd0bc0f1414cc1d0fa73a29470bd14944e4942d3Lennart Poettering found_aaaa = true;
dd0bc0f1414cc1d0fa73a29470bd14944e4942d3Lennart Poettering
dd0bc0f1414cc1d0fa73a29470bd14944e4942d3Lennart Poettering if (found_a && found_aaaa)
dd0bc0f1414cc1d0fa73a29470bd14944e4942d3Lennart Poettering break;
dd0bc0f1414cc1d0fa73a29470bd14944e4942d3Lennart Poettering }
dd0bc0f1414cc1d0fa73a29470bd14944e4942d3Lennart Poettering
dd0bc0f1414cc1d0fa73a29470bd14944e4942d3Lennart Poettering for (i = 0; i < bn->n_items; i++) {
dd0bc0f1414cc1d0fa73a29470bd14944e4942d3Lennart Poettering _cleanup_(dns_resource_record_unrefp) DnsResourceRecord *rr = NULL;
dd0bc0f1414cc1d0fa73a29470bd14944e4942d3Lennart Poettering
dd0bc0f1414cc1d0fa73a29470bd14944e4942d3Lennart Poettering if ((found_a && bn->items[i]->family != AF_INET) &&
dd0bc0f1414cc1d0fa73a29470bd14944e4942d3Lennart Poettering (found_aaaa && bn->items[i]->family != AF_INET6))
dd0bc0f1414cc1d0fa73a29470bd14944e4942d3Lennart Poettering continue;
dd0bc0f1414cc1d0fa73a29470bd14944e4942d3Lennart Poettering
dd0bc0f1414cc1d0fa73a29470bd14944e4942d3Lennart Poettering r = dns_resource_record_new_address(&rr, bn->items[i]->family, &bn->items[i]->address, bn->name);
dd0bc0f1414cc1d0fa73a29470bd14944e4942d3Lennart Poettering if (r < 0)
dd0bc0f1414cc1d0fa73a29470bd14944e4942d3Lennart Poettering return r;
dd0bc0f1414cc1d0fa73a29470bd14944e4942d3Lennart Poettering
dd0bc0f1414cc1d0fa73a29470bd14944e4942d3Lennart Poettering r = dns_answer_add(*answer, rr, 0, DNS_ANSWER_AUTHENTICATED);
dd0bc0f1414cc1d0fa73a29470bd14944e4942d3Lennart Poettering if (r < 0)
dd0bc0f1414cc1d0fa73a29470bd14944e4942d3Lennart Poettering return r;
dd0bc0f1414cc1d0fa73a29470bd14944e4942d3Lennart Poettering }
dd0bc0f1414cc1d0fa73a29470bd14944e4942d3Lennart Poettering
dd0bc0f1414cc1d0fa73a29470bd14944e4942d3Lennart Poettering return 1;
dd0bc0f1414cc1d0fa73a29470bd14944e4942d3Lennart Poettering}