diff options
Diffstat (limited to 'src')
-rw-r--r-- | src/core/dbus-timer.c | 17 | ||||
-rw-r--r-- | src/core/load-fragment-gperf.gperf.m4 | 1 | ||||
-rw-r--r-- | src/core/timer.c | 28 | ||||
-rw-r--r-- | src/core/timer.h | 1 | ||||
-rw-r--r-- | src/resolve/resolved-dns-scope.c | 6 | ||||
-rw-r--r-- | src/resolve/resolved-dns-transaction.c | 14 | ||||
-rw-r--r-- | src/resolve/resolved-dns-zone.c | 245 | ||||
-rw-r--r-- | src/resolve/resolved-dns-zone.h | 2 | ||||
-rw-r--r-- | src/shared/bus-util.c | 32 | ||||
-rw-r--r-- | src/systemctl/systemctl.c | 11 |
10 files changed, 219 insertions, 138 deletions
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/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 495d17cdb1..db92113a36 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/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 |