summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/basic/hostname-util.c2
-rw-r--r--src/core/dbus-timer.c17
-rw-r--r--src/core/load-fragment-gperf.gperf.m41
-rw-r--r--src/core/timer.c28
-rw-r--r--src/core/timer.h1
-rw-r--r--src/libsystemd-network/dhcp-protocol.h10
-rw-r--r--src/libsystemd-network/sd-dhcp-client.c53
-rw-r--r--src/libsystemd-network/sd-ndisc.c18
-rw-r--r--src/network/networkd-link.c20
-rw-r--r--src/network/networkd-ndisc.c13
-rw-r--r--src/resolve/resolved-dns-scope.c6
-rw-r--r--src/resolve/resolved-dns-transaction.c14
-rw-r--r--src/resolve/resolved-dns-zone.c245
-rw-r--r--src/resolve/resolved-dns-zone.h2
-rw-r--r--src/shared/bus-util.c32
-rw-r--r--src/shared/dns-domain.c34
-rw-r--r--src/shared/dns-domain.h2
-rw-r--r--src/systemctl/systemctl.c11
-rw-r--r--src/test/test-dns-domain.c31
-rw-r--r--src/test/test-siphash24.c6
20 files changed, 373 insertions, 173 deletions
diff --git a/src/basic/hostname-util.c b/src/basic/hostname-util.c
index ea0528c6fc..c57a3cbd60 100644
--- a/src/basic/hostname-util.c
+++ b/src/basic/hostname-util.c
@@ -72,7 +72,7 @@ static bool hostname_valid_char(char c) {
* allow_trailing_dot is true and at least two components are present
* in the name. Note that due to the restricted charset and length
* this call is substantially more conservative than
- * dns_domain_is_valid().
+ * dns_name_is_valid().
*/
bool hostname_is_valid(const char *s, bool allow_trailing_dot) {
unsigned n_dots = 0;
diff --git a/src/core/dbus-timer.c b/src/core/dbus-timer.c
index 2e6c479c3a..4bee82df07 100644
--- a/src/core/dbus-timer.c
+++ b/src/core/dbus-timer.c
@@ -180,6 +180,7 @@ const sd_bus_vtable bus_timer_vtable[] = {
BUS_PROPERTY_DUAL_TIMESTAMP("LastTriggerUSec", offsetof(Timer, last_trigger), SD_BUS_VTABLE_PROPERTY_EMITS_CHANGE),
SD_BUS_PROPERTY("Result", "s", property_get_result, offsetof(Timer, result), SD_BUS_VTABLE_PROPERTY_EMITS_CHANGE),
SD_BUS_PROPERTY("AccuracyUSec", "t", bus_property_get_usec, offsetof(Timer, accuracy_usec), SD_BUS_VTABLE_PROPERTY_CONST),
+ SD_BUS_PROPERTY("RandomUSec", "t", bus_property_get_usec, offsetof(Timer, random_usec), SD_BUS_VTABLE_PROPERTY_CONST),
SD_BUS_PROPERTY("Persistent", "b", bus_property_get_bool, offsetof(Timer, persistent), SD_BUS_VTABLE_PROPERTY_CONST),
SD_BUS_PROPERTY("WakeSystem", "b", bus_property_get_bool, offsetof(Timer, wake_system), SD_BUS_VTABLE_PROPERTY_CONST),
SD_BUS_PROPERTY("RemainAfterElapse", "b", bus_property_get_bool, offsetof(Timer, remain_after_elapse), SD_BUS_VTABLE_PROPERTY_CONST),
@@ -283,6 +284,22 @@ static int bus_timer_set_transient_property(
return 1;
+ } else if (streq(name, "RandomUSec")) {
+ usec_t u = 0;
+
+ r = sd_bus_message_read(message, "t", &u);
+ if (r < 0)
+ return r;
+
+ if (mode != UNIT_CHECK) {
+ char time[FORMAT_TIMESPAN_MAX];
+
+ t->random_usec = u;
+ unit_write_drop_in_private_format(UNIT(t), mode, name, "RandomSec=%s\n", format_timespan(time, sizeof(time), u, USEC_PER_MSEC));
+ }
+
+ return 1;
+
} else if (streq(name, "WakeSystem")) {
int b;
diff --git a/src/core/load-fragment-gperf.gperf.m4 b/src/core/load-fragment-gperf.gperf.m4
index 0dbe38d7e5..c64850802e 100644
--- a/src/core/load-fragment-gperf.gperf.m4
+++ b/src/core/load-fragment-gperf.gperf.m4
@@ -347,6 +347,7 @@ Timer.Persistent, config_parse_bool, 0,
Timer.WakeSystem, config_parse_bool, 0, offsetof(Timer, wake_system)
Timer.RemainAfterElapse, config_parse_bool, 0, offsetof(Timer, remain_after_elapse)
Timer.AccuracySec, config_parse_sec, 0, offsetof(Timer, accuracy_usec)
+Timer.RandomSec, config_parse_sec, 0, offsetof(Timer, random_usec)
Timer.Unit, config_parse_trigger_unit, 0, 0
m4_dnl
Path.PathExists, config_parse_path_spec, 0, 0
diff --git a/src/core/timer.c b/src/core/timer.c
index 0587452cfb..6b0f8e8616 100644
--- a/src/core/timer.c
+++ b/src/core/timer.c
@@ -27,6 +27,7 @@
#include "dbus-timer.h"
#include "fs-util.h"
#include "parse-util.h"
+#include "random-util.h"
#include "special.h"
#include "string-table.h"
#include "string-util.h"
@@ -330,6 +331,28 @@ static usec_t monotonic_to_boottime(usec_t t) {
return 0;
}
+static void add_random(Timer *t, usec_t *v) {
+ char s[FORMAT_TIMESPAN_MAX];
+ usec_t add;
+
+ assert(t);
+ assert(*v);
+
+ if (t->random_usec == 0)
+ return;
+ if (*v == USEC_INFINITY)
+ return;
+
+ add = random_u64() % t->random_usec;
+
+ if (*v + add < *v) /* overflow */
+ *v = (usec_t) -2; /* Highest possible value, that is not USEC_INFINITY */
+ else
+ *v += add;
+
+ log_unit_info(UNIT(t), "Adding %s random time.", format_timespan(s, sizeof(s), add, 0));
+}
+
static void timer_enter_waiting(Timer *t, bool initial) {
bool found_monotonic = false, found_realtime = false;
usec_t ts_realtime, ts_monotonic;
@@ -452,6 +475,8 @@ static void timer_enter_waiting(Timer *t, bool initial) {
char buf[FORMAT_TIMESPAN_MAX];
usec_t left;
+ add_random(t, &t->next_elapse_monotonic_or_boottime);
+
left = t->next_elapse_monotonic_or_boottime > ts_monotonic ? t->next_elapse_monotonic_or_boottime - ts_monotonic : 0;
log_unit_debug(UNIT(t), "Monotonic timer elapses in %s.", format_timespan(buf, sizeof(buf), left, 0));
@@ -486,6 +511,9 @@ static void timer_enter_waiting(Timer *t, bool initial) {
if (found_realtime) {
char buf[FORMAT_TIMESTAMP_MAX];
+
+ add_random(t, &t->next_elapse_realtime);
+
log_unit_debug(UNIT(t), "Realtime timer elapses at %s.", format_timestamp(buf, sizeof(buf), t->next_elapse_realtime));
if (t->realtime_event_source) {
diff --git a/src/core/timer.h b/src/core/timer.h
index 6bc9fbed3d..0599f07818 100644
--- a/src/core/timer.h
+++ b/src/core/timer.h
@@ -58,6 +58,7 @@ struct Timer {
Unit meta;
usec_t accuracy_usec;
+ usec_t random_usec;
LIST_HEAD(TimerValue, values);
usec_t next_elapse_realtime;
diff --git a/src/libsystemd-network/dhcp-protocol.h b/src/libsystemd-network/dhcp-protocol.h
index 69b37fc352..05bb5ae493 100644
--- a/src/libsystemd-network/dhcp-protocol.h
+++ b/src/libsystemd-network/dhcp-protocol.h
@@ -137,6 +137,7 @@ enum {
DHCP_OPTION_REBINDING_T2_TIME = 59,
DHCP_OPTION_VENDOR_CLASS_IDENTIFIER = 60,
DHCP_OPTION_CLIENT_IDENTIFIER = 61,
+ DHCP_OPTION_FQDN = 81,
DHCP_OPTION_NEW_POSIX_TIMEZONE = 100,
DHCP_OPTION_NEW_TZDB_TIMEZONE = 101,
DHCP_OPTION_CLASSLESS_STATIC_ROUTE = 121,
@@ -144,3 +145,12 @@ enum {
DHCP_OPTION_PRIVATE_LAST = 254,
DHCP_OPTION_END = 255,
};
+
+#define DHCP_MAX_FQDN_LENGTH 255
+
+enum {
+ DHCP_FQDN_FLAG_S = (1 << 0),
+ DHCP_FQDN_FLAG_O = (1 << 1),
+ DHCP_FQDN_FLAG_E = (1 << 2),
+ DHCP_FQDN_FLAG_N = (1 << 3),
+};
diff --git a/src/libsystemd-network/sd-dhcp-client.c b/src/libsystemd-network/sd-dhcp-client.c
index 137537253a..5ec0e661f7 100644
--- a/src/libsystemd-network/sd-dhcp-client.c
+++ b/src/libsystemd-network/sd-dhcp-client.c
@@ -34,6 +34,8 @@
#include "dhcp-internal.h"
#include "dhcp-lease-internal.h"
#include "dhcp-protocol.h"
+#include "dns-domain.h"
+#include "hostname-util.h"
#include "random-util.h"
#include "string-util.h"
#include "util.h"
@@ -298,6 +300,9 @@ int sd_dhcp_client_set_hostname(sd_dhcp_client *client,
assert_return(client, -EINVAL);
+ if (!hostname_is_valid(hostname, false) && !dns_name_is_valid(hostname))
+ return -EINVAL;
+
if (streq_ptr(client->hostname, hostname))
return 0;
@@ -539,6 +544,24 @@ static int client_message_init(sd_dhcp_client *client, DHCPPacket **ret,
return 0;
}
+static int client_append_fqdn_option(DHCPMessage *message, size_t optlen, size_t *optoffset,
+ const char *fqdn) {
+ uint8_t buffer[3 + DHCP_MAX_FQDN_LENGTH];
+ int r;
+
+ buffer[0] = DHCP_FQDN_FLAG_S | /* Request server to perform A RR DNS updates */
+ DHCP_FQDN_FLAG_E; /* Canonical wire format */
+ buffer[1] = 0; /* RCODE1 (deprecated) */
+ buffer[2] = 0; /* RCODE2 (deprecated) */
+
+ r = dns_name_to_wire_format(fqdn, buffer + 3, sizeof(buffer) - 3);
+ if (r > 0)
+ r = dhcp_option_append(message, optlen, optoffset, 0,
+ DHCP_OPTION_FQDN, 3 + r, buffer);
+
+ return r;
+}
+
static int dhcp_client_send_raw(sd_dhcp_client *client, DHCPPacket *packet,
size_t len) {
dhcp_packet_append_ip_headers(packet, INADDR_ANY, DHCP_PORT_CLIENT,
@@ -576,13 +599,21 @@ static int client_send_discover(sd_dhcp_client *client) {
return r;
}
- /* it is unclear from RFC 2131 if client should send hostname in
- DHCPDISCOVER but dhclient does and so we do as well
- */
if (client->hostname) {
- r = dhcp_option_append(&discover->dhcp, optlen, &optoffset, 0,
- DHCP_OPTION_HOST_NAME,
- strlen(client->hostname), client->hostname);
+ /* According to RFC 4702 "clients that send the Client FQDN option in
+ their messages MUST NOT also send the Host Name option". Just send
+ one of the two depending on the hostname type.
+ */
+ if (dns_name_single_label(client->hostname)) {
+ /* it is unclear from RFC 2131 if client should send hostname in
+ DHCPDISCOVER but dhclient does and so we do as well
+ */
+ r = dhcp_option_append(&discover->dhcp, optlen, &optoffset, 0,
+ DHCP_OPTION_HOST_NAME,
+ strlen(client->hostname), client->hostname);
+ } else
+ r = client_append_fqdn_option(&discover->dhcp, optlen, &optoffset,
+ client->hostname);
if (r < 0)
return r;
}
@@ -688,9 +719,13 @@ static int client_send_request(sd_dhcp_client *client) {
}
if (client->hostname) {
- r = dhcp_option_append(&request->dhcp, optlen, &optoffset, 0,
- DHCP_OPTION_HOST_NAME,
- strlen(client->hostname), client->hostname);
+ if (dns_name_single_label(client->hostname))
+ r = dhcp_option_append(&request->dhcp, optlen, &optoffset, 0,
+ DHCP_OPTION_HOST_NAME,
+ strlen(client->hostname), client->hostname);
+ else
+ r = client_append_fqdn_option(&request->dhcp, optlen, &optoffset,
+ client->hostname);
if (r < 0)
return r;
}
diff --git a/src/libsystemd-network/sd-ndisc.c b/src/libsystemd-network/sd-ndisc.c
index 6703d87bc4..713438f212 100644
--- a/src/libsystemd-network/sd-ndisc.c
+++ b/src/libsystemd-network/sd-ndisc.c
@@ -32,6 +32,7 @@
#include "in-addr-util.h"
#include "list.h"
#include "socket-util.h"
+#include "string-util.h"
#define NDISC_ROUTER_SOLICITATION_INTERVAL 4 * USEC_PER_SEC
#define NDISC_MAX_ROUTER_SOLICITATIONS 3
@@ -484,6 +485,7 @@ static int ndisc_router_advertisment_recv(sd_event_source *s, int fd, uint32_t r
int r, buflen = 0, pref, stateful;
union sockaddr_union router = {};
socklen_t router_len = sizeof(router);
+ struct in6_addr *gw;
unsigned lifetime;
ssize_t len;
@@ -503,9 +505,21 @@ static int ndisc_router_advertisment_recv(sd_event_source *s, int fd, uint32_t r
if (len < 0) {
log_ndisc(nd, "Could not receive message from ICMPv6 socket: %m");
return 0;
- } else if (router_len != sizeof(router.in6) && router_len != 0) {
+ } else if (router_len == 0)
+ gw = NULL; /* only happens when running the test-suite over a socketpair */
+ else if (router_len != sizeof(router.in6)) {
log_ndisc(nd, "Received invalid source address size from ICMPv6 socket: %zu bytes", (size_t)router_len);
return 0;
+ } else
+ gw = &router.in6.sin6_addr;
+
+ if (gw && !in_addr_is_link_local(AF_INET6, (const union in_addr_union*) gw)) {
+ _cleanup_free_ char *addr = NULL;
+
+ (void)in_addr_to_string(AF_INET6, (const union in_addr_union*) gw, &addr);
+
+ log_ndisc(nd, "Received RA from non-link-local address %s. Ignoring.", strna(addr));
+ return 0;
}
if (ra->nd_ra_type != ND_ROUTER_ADVERT)
@@ -544,7 +558,7 @@ static int ndisc_router_advertisment_recv(sd_event_source *s, int fd, uint32_t r
}
if (nd->router_callback)
- nd->router_callback(nd, stateful, router_len != 0 ? &router.in6.sin6_addr : NULL, lifetime, pref, nd->userdata);
+ nd->router_callback(nd, stateful, gw, lifetime, pref, nd->userdata);
return 0;
}
diff --git a/src/network/networkd-link.c b/src/network/networkd-link.c
index 295249a50d..4af895a6fb 100644
--- a/src/network/networkd-link.c
+++ b/src/network/networkd-link.c
@@ -626,6 +626,9 @@ void link_check_ready(Link *link) {
!link->dhcp4_configured && !link->dhcp6_configured))
return;
+ if (link_ipv6_accept_ra_enabled(link) && !link->ndisc_configured)
+ return;
+
SET_FOREACH(a, link->addresses, i)
if (!address_is_ready(a))
return;
@@ -1923,7 +1926,6 @@ static int link_set_ipv6_privacy_extensions(Link *link) {
static int link_set_ipv6_accept_ra(Link *link) {
const char *p = NULL;
- const char *v;
int r;
/* Make this a NOP if IPv6 is not available */
@@ -1936,16 +1938,12 @@ static int link_set_ipv6_accept_ra(Link *link) {
if (!link->network)
return 0;
- if (link_ipv6_accept_ra_enabled(link))
- v = "1";
- else
- v = "0";
-
p = strjoina("/proc/sys/net/ipv6/conf/", link->ifname, "/accept_ra");
- r = write_string_file(p, v, WRITE_STRING_FILE_VERIFY_ON_FAILURE);
+ /* We handle router advertisments ourselves, tell the kernel to GTFO */
+ r = write_string_file(p, "0", WRITE_STRING_FILE_VERIFY_ON_FAILURE);
if (r < 0)
- log_link_warning_errno(link, r, "Cannot configure kernel IPv6 accept_ra for interface: %m");
+ log_link_warning_errno(link, r, "Cannot disable kernel IPv6 accept_ra for interface: %m");
return 0;
}
@@ -2006,7 +2004,6 @@ static int link_set_ipv6_hop_limit(Link *link) {
return 0;
}
-/*
static int link_drop_foreign_config(Link *link) {
Address *address;
Route *route;
@@ -2014,6 +2011,7 @@ static int link_drop_foreign_config(Link *link) {
int r;
SET_FOREACH(address, link->addresses_foreign, i) {
+ /* we consider IPv6LL addresses to be managed by the kernel */
if (address->family == AF_INET6 && in_addr_is_link_local(AF_INET6, &address->in_addr) == 1)
continue;
@@ -2023,6 +2021,7 @@ static int link_drop_foreign_config(Link *link) {
}
SET_FOREACH(route, link->routes_foreign, i) {
+ /* do not touch routes managed by the kernel */
if (route->protocol == RTPROT_KERNEL)
continue;
@@ -2033,7 +2032,6 @@ static int link_drop_foreign_config(Link *link) {
return 0;
}
-*/
static int link_configure(Link *link) {
int r;
@@ -2042,11 +2040,9 @@ static int link_configure(Link *link) {
assert(link->network);
assert(link->state == LINK_STATE_PENDING);
-/*
r = link_drop_foreign_config(link);
if (r < 0)
return r;
-*/
r = link_set_bridge_fdb(link);
if (r < 0)
diff --git a/src/network/networkd-ndisc.c b/src/network/networkd-ndisc.c
index 966d729d85..ce9e513ceb 100644
--- a/src/network/networkd-ndisc.c
+++ b/src/network/networkd-ndisc.c
@@ -26,7 +26,7 @@
#include "sd-ndisc.h"
#include "networkd-link.h"
-/*
+
static int ndisc_netlink_handler(sd_netlink *rtnl, sd_netlink_message *m, void *userdata) {
_cleanup_link_unref_ Link *link = userdata;
int r;
@@ -77,6 +77,7 @@ static void ndisc_prefix_autonomous_handler(sd_ndisc *nd, const struct in6_addr
if (in_addr_is_null(AF_INET6, (const union in_addr_union *) &link->network->ipv6_token) == 0)
memcpy(((char *)&address->in_addr.in6) + 8, ((char *)&link->network->ipv6_token) + 8, 8);
else {
+ /* see RFC4291 section 2.5.1 */
address->in_addr.in6.__in6_u.__u6_addr8[8] = link->mac.ether_addr_octet[0];
address->in_addr.in6.__in6_u.__u6_addr8[8] ^= 1 << 1;
address->in_addr.in6.__in6_u.__u6_addr8[9] = link->mac.ether_addr_octet[1];
@@ -139,12 +140,11 @@ static void ndisc_prefix_onlink_handler(sd_ndisc *nd, const struct in6_addr *pre
link->ndisc_messages ++;
}
-*/
static void ndisc_router_handler(sd_ndisc *nd, uint8_t flags, const struct in6_addr *gateway, unsigned lifetime, int pref, void *userdata) {
_cleanup_route_free_ Route *route = NULL;
Link *link = userdata;
- /* usec_t time_now; */
+ usec_t time_now;
int r;
assert(link);
@@ -163,8 +163,6 @@ static void ndisc_router_handler(sd_ndisc *nd, uint8_t flags, const struct in6_a
log_link_warning_errno(link, r, "Starting DHCPv6 client on NDisc request failed: %m");
}
- return;
-/*
if (!gateway)
return;
@@ -191,7 +189,6 @@ static void ndisc_router_handler(sd_ndisc *nd, uint8_t flags, const struct in6_a
}
link->ndisc_messages ++;
-*/
}
static void ndisc_handler(sd_ndisc *nd, int event, void *userdata) {
@@ -245,8 +242,8 @@ int ndisc_configure(Link *link) {
r = sd_ndisc_set_callback(link->ndisc_router_discovery,
ndisc_router_handler,
- NULL,
- NULL,
+ ndisc_prefix_onlink_handler,
+ ndisc_prefix_autonomous_handler,
ndisc_handler,
link);
diff --git a/src/resolve/resolved-dns-scope.c b/src/resolve/resolved-dns-scope.c
index b15370b017..873d76e40c 100644
--- a/src/resolve/resolved-dns-scope.c
+++ b/src/resolve/resolved-dns-scope.c
@@ -543,6 +543,7 @@ static void dns_scope_verify_conflicts(DnsScope *s, DnsPacket *p) {
void dns_scope_process_query(DnsScope *s, DnsStream *stream, DnsPacket *p) {
_cleanup_(dns_packet_unrefp) DnsPacket *reply = NULL;
_cleanup_(dns_answer_unrefp) DnsAnswer *answer = NULL, *soa = NULL;
+ DnsResourceKey *key = NULL;
bool tentative = false;
int r, fd;
@@ -576,7 +577,10 @@ void dns_scope_process_query(DnsScope *s, DnsStream *stream, DnsPacket *p) {
return;
}
- r = dns_zone_lookup(&s->zone, p->question, &answer, &soa, &tentative);
+ assert(p->question->n_keys == 1);
+ key = p->question->keys[0];
+
+ r = dns_zone_lookup(&s->zone, key, &answer, &soa, &tentative);
if (r < 0) {
log_debug_errno(r, "Failed to lookup key: %m");
return;
diff --git a/src/resolve/resolved-dns-transaction.c b/src/resolve/resolved-dns-transaction.c
index 6545f6cd8a..37f47c47c0 100644
--- a/src/resolve/resolved-dns-transaction.c
+++ b/src/resolve/resolved-dns-transaction.c
@@ -626,6 +626,20 @@ int dns_transaction_go(DnsTransaction *t) {
t->cached = dns_answer_unref(t->cached);
t->cached_rcode = 0;
+ /* Check the zone, but obly if this transaction is not used
+ * for probing or verifying a zone item. */
+ if (set_isempty(t->zone_items)) {
+
+ r = dns_zone_lookup(&t->scope->zone, t->key, &t->cached, NULL, NULL);
+ if (r < 0)
+ return r;
+ if (r > 0) {
+ t->cached_rcode = DNS_RCODE_SUCCESS;
+ dns_transaction_complete(t, DNS_TRANSACTION_SUCCESS);
+ return 0;
+ }
+ }
+
/* Check the cache, but only if this transaction is not used
* for probing or verifying a zone item. */
if (set_isempty(t->zone_items)) {
diff --git a/src/resolve/resolved-dns-zone.c b/src/resolve/resolved-dns-zone.c
index 48dcf76daa..a021ecb93d 100644
--- a/src/resolve/resolved-dns-zone.c
+++ b/src/resolve/resolved-dns-zone.c
@@ -283,97 +283,76 @@ int dns_zone_put(DnsZone *z, DnsScope *s, DnsResourceRecord *rr, bool probe) {
return 0;
}
-int dns_zone_lookup(DnsZone *z, DnsQuestion *q, DnsAnswer **ret_answer, DnsAnswer **ret_soa, bool *ret_tentative) {
+int dns_zone_lookup(DnsZone *z, DnsResourceKey *key, DnsAnswer **ret_answer, DnsAnswer **ret_soa, bool *ret_tentative) {
_cleanup_(dns_answer_unrefp) DnsAnswer *answer = NULL, *soa = NULL;
- unsigned i, n_answer = 0, n_soa = 0;
- bool tentative = true;
+ unsigned n_answer = 0;
+ DnsZoneItem *j, *first;
+ bool tentative = true, need_soa = false;
int r;
assert(z);
- assert(q);
+ assert(key);
assert(ret_answer);
- assert(ret_soa);
- if (q->n_keys <= 0) {
- *ret_answer = NULL;
- *ret_soa = NULL;
-
- if (ret_tentative)
- *ret_tentative = false;
+ /* First iteration, count what we have */
- return 0;
- }
+ if (key->type == DNS_TYPE_ANY || key->class == DNS_CLASS_ANY) {
+ bool found = false, added = false;
+ int k;
- /* First iteration, count what we have */
- for (i = 0; i < q->n_keys; i++) {
- DnsZoneItem *j, *first;
+ /* If this is a generic match, then we have to
+ * go through the list by the name and look
+ * for everything manually */
- if (q->keys[i]->type == DNS_TYPE_ANY ||
- q->keys[i]->class == DNS_CLASS_ANY) {
- bool found = false, added = false;
- int k;
+ first = hashmap_get(z->by_name, DNS_RESOURCE_KEY_NAME(key));
+ LIST_FOREACH(by_name, j, first) {
+ if (!IN_SET(j->state, DNS_ZONE_ITEM_PROBING, DNS_ZONE_ITEM_ESTABLISHED, DNS_ZONE_ITEM_VERIFYING))
+ continue;
- /* If this is a generic match, then we have to
- * go through the list by the name and look
- * for everything manually */
+ found = true;
- first = hashmap_get(z->by_name, DNS_RESOURCE_KEY_NAME(q->keys[i]));
- LIST_FOREACH(by_name, j, first) {
- if (!IN_SET(j->state, DNS_ZONE_ITEM_PROBING, DNS_ZONE_ITEM_ESTABLISHED, DNS_ZONE_ITEM_VERIFYING))
- continue;
+ k = dns_resource_key_match_rr(key, j->rr);
+ if (k < 0)
+ return k;
+ if (k > 0) {
+ n_answer++;
+ added = true;
+ }
- found = true;
+ }
- k = dns_resource_key_match_rr(q->keys[i], j->rr);
- if (k < 0)
- return k;
- if (k > 0) {
- n_answer++;
- added = true;
- }
+ if (found && !added)
+ need_soa = true;
- }
+ } else {
+ bool found = false;
- if (found && !added)
- n_soa++;
+ /* If this is a specific match, then look for
+ * the right key immediately */
- } else {
- bool found = false;
+ first = hashmap_get(z->by_key, key);
+ LIST_FOREACH(by_key, j, first) {
+ if (!IN_SET(j->state, DNS_ZONE_ITEM_PROBING, DNS_ZONE_ITEM_ESTABLISHED, DNS_ZONE_ITEM_VERIFYING))
+ continue;
- /* If this is a specific match, then look for
- * the right key immediately */
+ found = true;
+ n_answer++;
+ }
- first = hashmap_get(z->by_key, q->keys[i]);
- LIST_FOREACH(by_key, j, first) {
+ if (!found) {
+ first = hashmap_get(z->by_name, DNS_RESOURCE_KEY_NAME(key));
+ LIST_FOREACH(by_name, j, first) {
if (!IN_SET(j->state, DNS_ZONE_ITEM_PROBING, DNS_ZONE_ITEM_ESTABLISHED, DNS_ZONE_ITEM_VERIFYING))
continue;
- found = true;
- n_answer++;
- }
-
- if (!found) {
- first = hashmap_get(z->by_name, DNS_RESOURCE_KEY_NAME(q->keys[i]));
- LIST_FOREACH(by_name, j, first) {
- if (!IN_SET(j->state, DNS_ZONE_ITEM_PROBING, DNS_ZONE_ITEM_ESTABLISHED, DNS_ZONE_ITEM_VERIFYING))
- continue;
-
- n_soa++;
- break;
- }
+ need_soa = true;
+ break;
}
}
}
- if (n_answer <= 0 && n_soa <= 0) {
- *ret_answer = NULL;
- *ret_soa = NULL;
-
- if (ret_tentative)
- *ret_tentative = false;
-
- return 0;
- }
+ if (n_answer <= 0 && !need_soa)
+ goto return_empty;
if (n_answer > 0) {
answer = dns_answer_new(n_answer);
@@ -381,99 +360,113 @@ int dns_zone_lookup(DnsZone *z, DnsQuestion *q, DnsAnswer **ret_answer, DnsAnswe
return -ENOMEM;
}
- if (n_soa > 0) {
- soa = dns_answer_new(n_soa);
+ if (need_soa) {
+ soa = dns_answer_new(1);
if (!soa)
return -ENOMEM;
}
/* Second iteration, actually add the RRs to the answers */
- for (i = 0; i < q->n_keys; i++) {
- DnsZoneItem *j, *first;
-
- if (q->keys[i]->type == DNS_TYPE_ANY ||
- q->keys[i]->class == DNS_CLASS_ANY) {
- bool found = false, added = false;
- int k;
+ if (key->type == DNS_TYPE_ANY || key->class == DNS_CLASS_ANY) {
+ bool found = false, added = false;
+ int k;
- first = hashmap_get(z->by_name, DNS_RESOURCE_KEY_NAME(q->keys[i]));
- LIST_FOREACH(by_name, j, first) {
- if (!IN_SET(j->state, DNS_ZONE_ITEM_PROBING, DNS_ZONE_ITEM_ESTABLISHED, DNS_ZONE_ITEM_VERIFYING))
- continue;
-
- found = true;
+ first = hashmap_get(z->by_name, DNS_RESOURCE_KEY_NAME(key));
+ LIST_FOREACH(by_name, j, first) {
+ if (!IN_SET(j->state, DNS_ZONE_ITEM_PROBING, DNS_ZONE_ITEM_ESTABLISHED, DNS_ZONE_ITEM_VERIFYING))
+ continue;
- if (j->state != DNS_ZONE_ITEM_PROBING)
- tentative = false;
+ found = true;
- k = dns_resource_key_match_rr(q->keys[i], j->rr);
- if (k < 0)
- return k;
- if (k > 0) {
- r = dns_answer_add(answer, j->rr, 0);
- if (r < 0)
- return r;
+ if (j->state != DNS_ZONE_ITEM_PROBING)
+ tentative = false;
- added = true;
- }
- }
-
- if (found && !added) {
- r = dns_answer_add_soa(soa, DNS_RESOURCE_KEY_NAME(q->keys[i]), LLMNR_DEFAULT_TTL);
+ k = dns_resource_key_match_rr(key, j->rr);
+ if (k < 0)
+ return k;
+ if (k > 0) {
+ r = dns_answer_add(answer, j->rr, 0);
if (r < 0)
return r;
+
+ added = true;
}
- } else {
- bool found = false;
+ }
- first = hashmap_get(z->by_key, q->keys[i]);
- LIST_FOREACH(by_key, j, first) {
- if (!IN_SET(j->state, DNS_ZONE_ITEM_PROBING, DNS_ZONE_ITEM_ESTABLISHED, DNS_ZONE_ITEM_VERIFYING))
- continue;
+ if (found && !added) {
+ r = dns_answer_add_soa(soa, DNS_RESOURCE_KEY_NAME(key), LLMNR_DEFAULT_TTL);
+ if (r < 0)
+ return r;
+ }
+ } else {
+ bool found = false;
- found = true;
+ first = hashmap_get(z->by_key, key);
+ LIST_FOREACH(by_key, j, first) {
+ if (!IN_SET(j->state, DNS_ZONE_ITEM_PROBING, DNS_ZONE_ITEM_ESTABLISHED, DNS_ZONE_ITEM_VERIFYING))
+ continue;
- if (j->state != DNS_ZONE_ITEM_PROBING)
- tentative = false;
+ found = true;
- r = dns_answer_add(answer, j->rr, 0);
- if (r < 0)
- return r;
- }
+ if (j->state != DNS_ZONE_ITEM_PROBING)
+ tentative = false;
+
+ r = dns_answer_add(answer, j->rr, 0);
+ if (r < 0)
+ return r;
+ }
- if (!found) {
- bool add_soa = false;
+ if (!found) {
+ bool add_soa = false;
- first = hashmap_get(z->by_name, DNS_RESOURCE_KEY_NAME(q->keys[i]));
- LIST_FOREACH(by_name, j, first) {
- if (!IN_SET(j->state, DNS_ZONE_ITEM_PROBING, DNS_ZONE_ITEM_ESTABLISHED, DNS_ZONE_ITEM_VERIFYING))
- continue;
+ first = hashmap_get(z->by_name, DNS_RESOURCE_KEY_NAME(key));
+ LIST_FOREACH(by_name, j, first) {
+ if (!IN_SET(j->state, DNS_ZONE_ITEM_PROBING, DNS_ZONE_ITEM_ESTABLISHED, DNS_ZONE_ITEM_VERIFYING))
+ continue;
- if (j->state != DNS_ZONE_ITEM_PROBING)
- tentative = false;
+ if (j->state != DNS_ZONE_ITEM_PROBING)
+ tentative = false;
- add_soa = true;
- }
+ add_soa = true;
+ }
- if (add_soa) {
- r = dns_answer_add_soa(soa, DNS_RESOURCE_KEY_NAME(q->keys[i]), LLMNR_DEFAULT_TTL);
- if (r < 0)
- return r;
- }
+ if (add_soa) {
+ r = dns_answer_add_soa(soa, DNS_RESOURCE_KEY_NAME(key), LLMNR_DEFAULT_TTL);
+ if (r < 0)
+ return r;
}
}
}
+ /* If the caller sets ret_tentative to NULL, then use this as
+ * indication to not return tentative entries */
+
+ if (!ret_tentative && tentative)
+ goto return_empty;
+
*ret_answer = answer;
answer = NULL;
- *ret_soa = soa;
- soa = NULL;
+ if (ret_soa) {
+ *ret_soa = soa;
+ soa = NULL;
+ }
if (ret_tentative)
*ret_tentative = tentative;
return 1;
+
+return_empty:
+ *ret_answer = NULL;
+
+ if (ret_soa)
+ *ret_soa = NULL;
+
+ if (ret_tentative)
+ *ret_tentative = false;
+
+ return 0;
}
void dns_zone_item_conflict(DnsZoneItem *i) {
diff --git a/src/resolve/resolved-dns-zone.h b/src/resolve/resolved-dns-zone.h
index de110f9de7..44a8624c30 100644
--- a/src/resolve/resolved-dns-zone.h
+++ b/src/resolve/resolved-dns-zone.h
@@ -67,7 +67,7 @@ void dns_zone_flush(DnsZone *z);
int dns_zone_put(DnsZone *z, DnsScope *s, DnsResourceRecord *rr, bool probe);
void dns_zone_remove_rr(DnsZone *z, DnsResourceRecord *rr);
-int dns_zone_lookup(DnsZone *z, DnsQuestion *q, DnsAnswer **answer, DnsAnswer **soa, bool *tentative);
+int dns_zone_lookup(DnsZone *z, DnsResourceKey *key, DnsAnswer **answer, DnsAnswer **soa, bool *tentative);
void dns_zone_item_conflict(DnsZoneItem *i);
void dns_zone_item_ready(DnsZoneItem *i);
diff --git a/src/shared/bus-util.c b/src/shared/bus-util.c
index 73ceeba18f..38281045b8 100644
--- a/src/shared/bus-util.c
+++ b/src/shared/bus-util.c
@@ -1428,16 +1428,36 @@ int bus_append_unit_property_assignment(sd_bus_message *m, const char *assignmen
return bus_log_create_error(r);
return 0;
+
} else if (streq(field, "EnvironmentFile")) {
+
r = sd_bus_message_append_basic(m, SD_BUS_TYPE_STRING, "EnvironmentFiles");
if (r < 0)
- return r;
+ return bus_log_create_error(r);
r = sd_bus_message_append(m, "v", "a(sb)", 1,
eq[0] == '-' ? eq + 1 : eq,
eq[0] == '-');
if (r < 0)
- return r;
+ return bus_log_create_error(r);
+
+ return 0;
+
+ } else if (streq(field, "RandomSec")) {
+ usec_t t;
+
+ r = parse_sec(eq, &t);
+ if (r < 0)
+ return log_error_errno(r, "Failed to parse RandomSec= parameter: %s", eq);
+
+ r = sd_bus_message_append_basic(m, SD_BUS_TYPE_STRING, "RandomUSec");
+ if (r < 0)
+ return bus_log_create_error(r);
+
+ r = sd_bus_message_append(m, "v", "t", t);
+ if (r < 0)
+ return bus_log_create_error(r);
+
return 0;
}
@@ -1450,13 +1470,11 @@ int bus_append_unit_property_assignment(sd_bus_message *m, const char *assignmen
"SendSIGHUP", "SendSIGKILL", "WakeSystem", "DefaultDependencies",
"IgnoreSIGPIPE", "TTYVHangup", "TTYReset", "RemainAfterExit",
"PrivateTmp", "PrivateDevices", "PrivateNetwork", "NoNewPrivileges",
- "SyslogLevelPrefix", "Delegate")) {
+ "SyslogLevelPrefix", "Delegate", "RemainAfterElapse")) {
r = parse_boolean(eq);
- if (r < 0) {
- log_error("Failed to parse boolean assignment %s.", assignment);
- return -EINVAL;
- }
+ if (r < 0)
+ return log_error_errno(r, "Failed to parse boolean assignment %s.", assignment);
r = sd_bus_message_append(m, "v", "b", r);
diff --git a/src/shared/dns-domain.c b/src/shared/dns-domain.c
index 7af15e0098..423ccca9cc 100644
--- a/src/shared/dns-domain.c
+++ b/src/shared/dns-domain.c
@@ -715,3 +715,37 @@ int dns_name_single_label(const char *name) {
return r == 0 && *name == 0;
}
+
+/* Encode a domain name according to RFC 1035 Section 3.1 */
+int dns_name_to_wire_format(const char *domain, uint8_t *buffer, size_t len) {
+ uint8_t *label_length;
+ uint8_t *out;
+ int r;
+
+ assert_return(buffer, -EINVAL);
+ assert_return(domain, -EINVAL);
+ assert_return(domain[0], -EINVAL);
+
+ out = buffer;
+
+ do {
+ /* reserve a byte for label length */
+ if (len == 0)
+ return -ENOBUFS;
+ len--;
+ label_length = out;
+ out++;
+
+ /* convert and copy a single label */
+ r = dns_label_unescape(&domain, (char *) out, len);
+ if (r < 0)
+ return r;
+
+ /* fill label length, move forward */
+ *label_length = r;
+ out += r;
+ len -= r;
+ } while (r != 0);
+
+ return out - buffer;
+}
diff --git a/src/shared/dns-domain.h b/src/shared/dns-domain.h
index 1f0d242c18..b214897440 100644
--- a/src/shared/dns-domain.h
+++ b/src/shared/dns-domain.h
@@ -67,3 +67,5 @@ int dns_name_address(const char *p, int *family, union in_addr_union *a);
int dns_name_root(const char *name);
int dns_name_single_label(const char *name);
+
+int dns_name_to_wire_format(const char *domain, uint8_t *buffer, size_t len);
diff --git a/src/systemctl/systemctl.c b/src/systemctl/systemctl.c
index 51b82d57db..240fa2c551 100644
--- a/src/systemctl/systemctl.c
+++ b/src/systemctl/systemctl.c
@@ -3360,6 +3360,7 @@ typedef struct UnitStatusInfo {
usec_t inactive_enter_timestamp;
bool need_daemon_reload;
+ bool transient;
/* Service */
pid_t main_pid;
@@ -3459,7 +3460,7 @@ static void print_status_info(
path = i->source_path ? i->source_path : i->fragment_path;
- if (i->load_error)
+ if (i->load_error != 0)
printf(" Loaded: %s%s%s (Reason: %s)\n",
on, strna(i->load_state), off, i->load_error);
else if (path && !isempty(i->unit_file_state) && !isempty(i->unit_file_preset))
@@ -3475,6 +3476,9 @@ static void print_status_info(
printf(" Loaded: %s%s%s\n",
on, strna(i->load_state), off);
+ if (i->transient)
+ printf("Transient: yes\n");
+
if (!strv_isempty(i->dropin_paths)) {
_cleanup_free_ char *dir = NULL;
bool last = false;
@@ -3839,6 +3843,8 @@ static int status_property(const char *name, sd_bus_message *m, UnitStatusInfo *
i->condition_result = b;
else if (streq(name, "AssertResult"))
i->assert_result = b;
+ else if (streq(name, "Transient"))
+ i->transient = b;
break;
}
@@ -4646,8 +4652,7 @@ static int show(int argc, char *argv[], void *userdata) {
return -EINVAL;
}
- if (show_properties)
- pager_open_if_enabled();
+ pager_open_if_enabled();
if (show_status)
/* Increase max number of open files to 16K if we can, we
diff --git a/src/test/test-dns-domain.c b/src/test/test-dns-domain.c
index d5778748a0..407c7d8ef7 100644
--- a/src/test/test-dns-domain.c
+++ b/src/test/test-dns-domain.c
@@ -52,6 +52,36 @@ static void test_dns_label_unescape(void) {
test_dns_label_unescape_one("foobar.", "foobar", 20, 6);
}
+static void test_dns_name_to_wire_format_one(const char *what, const char *expect, size_t buffer_sz, int ret) {
+ uint8_t buffer[buffer_sz];
+ int r;
+
+ r = dns_name_to_wire_format(what, buffer, buffer_sz);
+ assert_se(r == ret);
+
+ if (r < 0)
+ return;
+
+ assert_se(!memcmp(buffer, expect, r));
+}
+
+static void test_dns_name_to_wire_format(void) {
+ const char out1[] = { 3, 'f', 'o', 'o', 0 };
+ const char out2[] = { 5, 'h', 'a', 'l', 'l', 'o', 3, 'f', 'o', 'o', 3, 'b', 'a', 'r', 0 };
+ const char out3[] = { 4, ' ', 'f', 'o', 'o', 3, 'b', 'a', 'r', 0 };
+
+ test_dns_name_to_wire_format_one("", NULL, 0, -EINVAL);
+
+ test_dns_name_to_wire_format_one("foo", out1, sizeof(out1), sizeof(out1));
+ test_dns_name_to_wire_format_one("foo", out1, sizeof(out1) + 1, sizeof(out1));
+ test_dns_name_to_wire_format_one("foo", out1, sizeof(out1) - 1, -ENOBUFS);
+
+ test_dns_name_to_wire_format_one("hallo.foo.bar", out2, sizeof(out2), sizeof(out2));
+ test_dns_name_to_wire_format_one("hallo.foo..bar", NULL, 32, -EINVAL);
+
+ test_dns_name_to_wire_format_one("\\032foo.bar", out3, sizeof(out3), sizeof(out3));
+}
+
static void test_dns_label_unescape_suffix_one(const char *what, const char *expect1, const char *expect2, size_t buffer_sz, int ret1, int ret2) {
char buffer[buffer_sz];
const char *label;
@@ -300,6 +330,7 @@ int main(int argc, char *argv[]) {
test_dns_name_reverse();
test_dns_name_concat();
test_dns_name_is_valid();
+ test_dns_name_to_wire_format();
return 0;
}
diff --git a/src/test/test-siphash24.c b/src/test/test-siphash24.c
index a571a95a70..c20be99350 100644
--- a/src/test/test-siphash24.c
+++ b/src/test/test-siphash24.c
@@ -30,7 +30,7 @@ static int do_test(const uint8_t *in, size_t len, const uint8_t *key) {
unsigned i, j;
out = siphash24(in, len, key);
- assert_se(out == htole64(0xa129ca6149be45e5));
+ assert_se(out == 0xa129ca6149be45e5);
/* verify the internal state as given in the above paper */
siphash24_init(&state, key);
@@ -44,7 +44,7 @@ static int do_test(const uint8_t *in, size_t len, const uint8_t *key) {
assert_se(state.v2 == 0x634cb3577b01fd3d);
assert_se(state.v3 == 0xa5224d6f55c7d9c8);
out = siphash24_finalize(&state);
- assert_se(out == htole64(0xa129ca6149be45e5));
+ assert_se(out == 0xa129ca6149be45e5);
assert_se(state.v0 == 0xf6bcd53893fecff1);
assert_se(state.v1 == 0x54b9964c7ea0d937);
assert_se(state.v2 == 0x1b38329c099bb55a);
@@ -59,7 +59,7 @@ static int do_test(const uint8_t *in, size_t len, const uint8_t *key) {
siphash24_compress(&in[i], j - i, &state);
siphash24_compress(&in[j], len - j, &state);
out = siphash24_finalize(&state);
- assert_se(out == htole64(0xa129ca6149be45e5));
+ assert_se(out == 0xa129ca6149be45e5);
}
}
return 0;