+/* SPDX-License-Identifier: LGPL-2.1+ */
/***
This file is part of systemd.
unsigned n_addresses,
int af, const union in_addr_union *match) {
+ bool added = false;
unsigned j;
int r;
r = dns_answer_add(*answer, rr, addresses[j].ifindex, DNS_ANSWER_AUTHENTICATED);
if (r < 0)
return r;
+
+ added = true;
}
- return 0;
+ return added;
}
static int synthesize_system_hostname_rr(Manager *m, const DnsResourceKey *key, int ifindex, DnsAnswer **answer) {
/* If we have no local addresses then use ::1
* and 127.0.0.2 as local ones. */
- if (af == AF_INET || af == AF_UNSPEC)
+ if (IN_SET(af, AF_INET, AF_UNSPEC))
buffer[n++] = (struct local_address) {
.family = AF_INET,
.ifindex = dns_synthesize_ifindex(ifindex),
.address.in.s_addr = htobe32(0x7F000002),
};
- if (af == AF_INET6 || af == AF_UNSPEC)
+ if (IN_SET(af, AF_INET6, AF_UNSPEC))
buffer[n++] = (struct local_address) {
.family = AF_INET6,
.ifindex = dns_synthesize_ifindex(ifindex),
.address.in6 = in6addr_loopback,
};
- return answer_add_addresses_rr(answer, dns_resource_key_name(key), buffer, n);
+ return answer_add_addresses_rr(answer,
+ dns_resource_key_name(key),
+ buffer, n);
}
}
static int synthesize_system_hostname_ptr(Manager *m, int af, const union in_addr_union *address, int ifindex, DnsAnswer **answer) {
_cleanup_free_ struct local_address *addresses = NULL;
+ bool added = false;
int n, r;
assert(m);
if (af == AF_INET && address->in.s_addr == htobe32(0x7F000002)) {
- /* Always map the IPv4 address 127.0.0.2 to the local
- * hostname, in addition to "localhost": */
+ /* Always map the IPv4 address 127.0.0.2 to the local hostname, in addition to "localhost": */
- r = dns_answer_reserve(answer, 3);
+ r = dns_answer_reserve(answer, 4);
+ if (r < 0)
+ return r;
+
+ r = answer_add_ptr(answer, "2.0.0.127.in-addr.arpa", m->full_hostname, dns_synthesize_ifindex(ifindex), DNS_ANSWER_AUTHENTICATED);
if (r < 0)
return r;
if (r < 0)
return r;
- return 0;
+ return 1;
}
n = local_addresses(m->rtnl, ifindex, af, &addresses);
- if (n < 0)
+ if (n <= 0)
return n;
+ r = answer_add_addresses_ptr(answer, m->full_hostname, addresses, n, af, address);
+ if (r < 0)
+ return r;
+ if (r > 0)
+ added = true;
+
r = answer_add_addresses_ptr(answer, m->llmnr_hostname, addresses, n, af, address);
if (r < 0)
return r;
+ if (r > 0)
+ added = true;
+
+ r = answer_add_addresses_ptr(answer, m->mdns_hostname, addresses, n, af, address);
+ if (r < 0)
+ return r;
+ if (r > 0)
+ added = true;
- return answer_add_addresses_ptr(answer, m->mdns_hostname, addresses, n, af, address);
+ return added;
}
static int synthesize_gateway_rr(Manager *m, const DnsResourceKey *key, int ifindex, DnsAnswer **answer) {
_cleanup_free_ struct local_address *addresses = NULL;
- int n = 0, af;
+ int n = 0, af, r;
assert(m);
assert(key);
af = dns_type_to_af(key->type);
if (af >= 0) {
n = local_gateways(m->rtnl, ifindex, af, &addresses);
- if (n < 0)
- return n;
+ if (n <= 0)
+ return n; /* < 0 means: error; == 0 means we have no gateway */
}
- return answer_add_addresses_rr(answer, dns_resource_key_name(key), addresses, n);
+ r = answer_add_addresses_rr(answer, dns_resource_key_name(key), addresses, n);
+ if (r < 0)
+ return r;
+
+ return 1; /* > 0 means: we have some gateway */
}
static int synthesize_gateway_ptr(Manager *m, int af, const union in_addr_union *address, int ifindex, DnsAnswer **answer) {
assert(answer);
n = local_gateways(m->rtnl, ifindex, af, &addresses);
- if (n < 0)
+ if (n <= 0)
return n;
- return answer_add_addresses_ptr(answer, "gateway", addresses, n, af, address);
+ return answer_add_addresses_ptr(answer, "_gateway", addresses, n, af, address);
}
int dns_synthesize_answer(
_cleanup_(dns_answer_unrefp) DnsAnswer *answer = NULL;
DnsResourceKey *key;
- bool found = false;
+ bool found = false, nxdomain = false;
int r;
assert(m);
const char *name;
int af;
- if (key->class != DNS_CLASS_IN &&
- key->class != DNS_CLASS_ANY)
+ if (!IN_SET(key->class, DNS_CLASS_IN, DNS_CLASS_ANY))
continue;
name = dns_resource_key_name(key);
r = synthesize_gateway_rr(m, key, ifindex, &answer);
if (r < 0)
return log_error_errno(r, "Failed to synthesize gateway RRs: %m");
+ if (r == 0) { /* if we have no gateway return NXDOMAIN */
+ nxdomain = true;
+ continue;
+ }
} else if ((dns_name_endswith(name, "127.in-addr.arpa") > 0 && dns_name_equal(name, "2.0.0.127.in-addr.arpa") == 0) ||
dns_name_equal(name, "1.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.ip6.arpa") > 0) {
return log_error_errno(r, "Failed to synthesize localhost PTR RRs: %m");
} else if (dns_name_address(name, &af, &address) > 0) {
+ int v, w;
- r = synthesize_system_hostname_ptr(m, af, &address, ifindex, &answer);
- if (r < 0)
- return log_error_errno(r, "Failed to synthesize system hostname PTR RR: %m");
+ v = synthesize_system_hostname_ptr(m, af, &address, ifindex, &answer);
+ if (v < 0)
+ return log_error_errno(v, "Failed to synthesize system hostname PTR RR: %m");
+
+ w = synthesize_gateway_ptr(m, af, &address, ifindex, &answer);
+ if (w < 0)
+ return log_error_errno(w, "Failed to synthesize gateway hostname PTR RR: %m");
+
+ if (v == 0 && w == 0) /* This IP address is neither a local one nor a gateway */
+ continue;
- r = synthesize_gateway_ptr(m, af, &address, ifindex, &answer);
- if (r < 0)
- return log_error_errno(r, "Failed to synthesize gateway hostname PTR RR: %m");
} else
continue;
found = true;
}
- r = found;
+ if (found) {
- if (ret) {
- *ret = answer;
- answer = NULL;
- }
+ if (ret)
+ *ret = TAKE_PTR(answer);
+
+ return 1;
+ } else if (nxdomain)
+ return -ENXIO;
- return r;
+ return 0;
}