1
0
mirror of https://github.com/systemd/systemd synced 2025-09-30 17:24:46 +02:00

Compare commits

...

18 Commits

Author SHA1 Message Date
Lennart Poettering
71311efe23 journalctl: rotation is not a reason to warn, but certainly noteworthy
Downgrade the phrasing, since it is a bit misleading.

Fixes: #18465
2021-02-15 14:41:57 -08:00
Lennart Poettering
83ce3b1944
Merge pull request #18579 from keszybz/fix-fragment-id-crash
Fix fragment id crash
2021-02-15 23:35:25 +01:00
Lennart Poettering
0886999416
Merge pull request #18605 from poettering/suppress-repeated-stub
resolved: filter repeated stub queries
2021-02-15 23:06:37 +01:00
Lennart Poettering
5e8bc852d5 resolved: don't redundantly switch DNS servers because of transaction failures
When a transaction fails and we decide to switch DNS servers, don#t do
so unconditionally. Check if the current DNS server is still the same as
when the transaction was initiated. And if not, do not do anything.

That should reduce the number of redundant DNS server switches if many
parallel transactions fail simultaneously (which is pretty likely if
DNSSEC is on).

Fixes: #17040
2021-02-15 21:59:05 +01:00
Lennart Poettering
c78735eb79 resolved: reuse check for link-local IP address lookups
Let's reuse accept_link_local_reverse_lookups() at one more place, where
we check for the list of link local reverase address domains. Since we
don't actually accept the domains here (but rather the opposite, not
accept), let's rename the function a bit more generically with accept_ →
match_.

While we are at it invert the if branches, to make things more easily
understandable: filter out the unwatnted stuff and have the "all good"
state as main codepath.
2021-02-15 21:54:53 +01:00
Zbigniew Jędrzejewski-Szmek
bb3443d4f6
Merge pull request #18604 from poettering/resolved-minor-tweaks
two minor resolved tweaks
2021-02-15 21:18:34 +01:00
Luca Boccassi
79dbbb261d
Merge pull request #18593 from keszybz/fuzz-more-systemctl-paths
Fuzz more systemctl paths
2021-02-15 19:13:58 +00:00
Frantisek Sumsal
986eeaeb55 Revert "ci: build on Fedora ELN as well"
This reverts commit 58bc1735fed62bc7426187a80d166369569e799a.

The ELN composes are quite unstable and take a while to refresh. Let's
drop them again and revisit this once they get more mature to reduce
the CI noise.
2021-02-15 19:02:59 +00:00
RussianNeuroMancer
5185d4ddff Fix micmute hotkey on HP EliteBook Folio G1
Desktop environments expect f20 hotkey instead of micmute
2021-02-15 18:32:04 +00:00
Lennart Poettering
bf843b0bd4 update TODO 2021-02-15 19:23:05 +01:00
Lennart Poettering
bde69bbd89 resolved: filter repeated stub queries
Let's suppress repeated stub queries coming in, to minimize resource
usage. Many DNS clients are pretty aggressive regarding repeating DNS
requests, hence let's find them and suppress the follow-ups should we
need more time to fulfill the queries.
2021-02-15 16:27:40 +01:00
Lennart Poettering
ed8a48c9b6 resolved: allow DNS_PACKET_DATA() argument to be const 2021-02-15 16:27:40 +01:00
Lennart Poettering
7130db9155 resolved: allow DNS_PACKET_DATA() argument to be const 2021-02-15 16:23:30 +01:00
Lennart Poettering
6d76b5d7f0 resolved: move mdns event sources close to the fds 2021-02-15 16:22:14 +01:00
Zbigniew Jędrzejewski-Szmek
860f154fa3 fuzz-systemctl-parse-argv: add argv[0] values to corpus 2021-02-15 10:01:38 +01:00
Zbigniew Jędrzejewski-Szmek
d41a9e4fc1 systemctl: use argv[0] not program_invocation_short_name for arg dispatch
The immediate motivation is to allow fuzz-systemctl-parse-argv to cover also
the other code paths. p_i_s_n is not getting set (and it probably shouldn't),
so the fuzzer would only cover the paths for ./systemctl, and not ./reboot,
etc. Looking at argv[0] instead, which is passed as part of the fuzzer data,
fixes that.

But I think in general it's more correct to look at argv[0] here: after all we
have all the information available through local variables and shouldn't go out
of our way to look at a global.
2021-02-15 10:00:08 +01:00
Zbigniew Jędrzejewski-Szmek
3b5ab02119 TEST-15-DROPINS: add test for linked units 2021-02-14 15:08:49 +01:00
Zbigniew Jędrzejewski-Szmek
3aa5765843 basic/unit-file: when loading linked unit files, use link source as "fragment path"
The general idea is that when a unit file is "linked" (i.e. installed by
symlinking from outside of the search paths), the *destination* name is
irrelevant. It doesn't even have to be a valid unit name, or to match the type
or instance value. The obvious collorary is that we shouldn't look at the
symlink destination name to derive the unit name, instance value, or anything
else at all.

When building the name map, when we find a linked unit (possibly at the end
of a series of alias redirects), store the *source* of the final symlink as the
fragment path. This has two effects:
- we stop looking at the *target* file name to derive unit info, i.e. actually
  implement the stuff described in the first paragraph.
- we load the unit fragment through the symlink. If someone were to remove the
  symlink, we'll not load the unit. This seems like the right thing.

Fixes #18058.
Before this change, we were generally quite confused about unit alises for
linked units. Fortunately most poeple use the same symlink source and target,
so in practice we wouldn't hit this too often.

In unit_load_fragment() a comment is added to explain what we're doing there.
2021-02-14 14:49:00 +01:00
22 changed files with 211 additions and 97 deletions

View File

@ -43,5 +43,3 @@ jobs:
- fedora-rawhide-aarch64 - fedora-rawhide-aarch64
- fedora-rawhide-i386 - fedora-rawhide-i386
- fedora-rawhide-x86_64 - fedora-rawhide-x86_64
- fedora-eln-aarch64
- fedora-eln-x86_64

7
TODO
View File

@ -20,6 +20,13 @@ Janitorial Clean-ups:
Features: Features:
* Hook up journald's FSS logic with TPM2: seal the verification disk by
time-based policy, so that the verification key can remain on host and ve
validated via TPM.
* sd-event: port to new kernel API epoll_wait2() (new in 5.11), to get more
accurate wait timeouts
* sd-boot: define a drop-in dir in the ESP that may contain X.509 * sd-boot: define a drop-in dir in the ESP that may contain X.509
certificates. If the firmware is detected to be in setup mode, automatically certificates. If the firmware is detected to be in setup mode, automatically
enroll them as PK/KEK/db, turn off setup mode and proceed. Optionally, enroll them as PK/KEK/db, turn off setup mode and proceed. Optionally,

View File

@ -662,7 +662,7 @@ evdev:atkbd:dmi:bvn*:bvr*:bd*:svnHewlett-Packard*:pnHPEliteBookFolio1040G2:*
# HP EliteBook Folio G1 # HP EliteBook Folio G1
evdev:atkbd:dmi:bvn*:bvr*:bd*:svnHP:pnHPEliteBookFolioG1:* evdev:atkbd:dmi:bvn*:bvr*:bd*:svnHP:pnHPEliteBookFolioG1:*
KEYBOARD_KEY_64=calendar KEYBOARD_KEY_64=calendar
KEYBOARD_KEY_81=micmute KEYBOARD_KEY_81=f20
# HP ProBook 650 # HP ProBook 650
evdev:atkbd:dmi:bvn*:bvr*:bd*:svnHewlett-Packard*:pnHP*ProBook*650*:* evdev:atkbd:dmi:bvn*:bvr*:bd*:svnHewlett-Packard*:pnHP*ProBook*650*:*

View File

@ -354,10 +354,16 @@ int unit_file_build_name_map(
/* Check if the symlink goes outside of our search path. /* Check if the symlink goes outside of our search path.
* If yes, it's a linked unit file or mask, and we don't care about the target name. * If yes, it's a linked unit file or mask, and we don't care about the target name.
* Let's just store the link destination directly. * Let's just store the link source directly.
* If not, let's verify that it's a good symlink. */ * If not, let's verify that it's a good symlink. */
char *tail = path_startswith_strv(simplified, lp->search_path); char *tail = path_startswith_strv(simplified, lp->search_path);
if (tail) { if (!tail) {
log_debug("%s: linked unit file: %s → %s",
__func__, filename, simplified);
dst = filename;
} else {
bool self_alias; bool self_alias;
dst = basename(simplified); dst = basename(simplified);
@ -380,10 +386,6 @@ int unit_file_build_name_map(
} }
log_debug("%s: alias: %s/%s → %s", __func__, *dir, de->d_name, dst); log_debug("%s: alias: %s/%s → %s", __func__, *dir, de->d_name, dst);
} else {
dst = simplified;
log_debug("%s: linked unit file: %s/%s → %s", __func__, *dir, de->d_name, dst);
} }
} else { } else {

View File

@ -5536,10 +5536,11 @@ int unit_load_fragment(Unit *u) {
} }
} }
/* We do the merge dance here because for some unit types, the unit might have aliases which are not /* Call merge_by_names with the name derived from the fragment path as the preferred name.
*
* We do the merge dance here because for some unit types, the unit might have aliases which are not
* declared in the file system. In particular, this is true (and frequent) for device and swap units. * declared in the file system. In particular, this is true (and frequent) for device and swap units.
*/ */
Unit *merged;
const char *id = u->id; const char *id = u->id;
_cleanup_free_ char *free_id = NULL; _cleanup_free_ char *free_id = NULL;
@ -5556,7 +5557,7 @@ int unit_load_fragment(Unit *u) {
} }
} }
merged = u; Unit *merged = u;
r = merge_by_names(&merged, names, id); r = merge_by_names(&merged, names, id);
if (r < 0) if (r < 0)
return r; return r;

View File

@ -82,7 +82,7 @@ struct DnsPacket {
bool canonical_form:1; bool canonical_form:1;
}; };
static inline uint8_t* DNS_PACKET_DATA(DnsPacket *p) { static inline uint8_t* DNS_PACKET_DATA(const DnsPacket *p) {
if (_unlikely_(!p)) if (_unlikely_(!p))
return NULL; return NULL;

View File

@ -382,6 +382,13 @@ DnsQuery *dns_query_free(DnsQuery *q) {
varlink_unref(q->varlink_request); varlink_unref(q->varlink_request);
} }
if (q->request_packet)
hashmap_remove_value(q->stub_listener_extra ?
q->stub_listener_extra->queries_by_packet :
q->manager->stub_queries_by_packet,
q->request_packet,
q);
dns_packet_unref(q->request_packet); dns_packet_unref(q->request_packet);
dns_answer_unref(q->reply_answer); dns_answer_unref(q->reply_answer);
dns_answer_unref(q->reply_authoritative); dns_answer_unref(q->reply_authoritative);

View File

@ -153,16 +153,19 @@ unsigned dns_scope_get_n_dns_servers(DnsScope *s) {
return n; return n;
} }
void dns_scope_next_dns_server(DnsScope *s) { void dns_scope_next_dns_server(DnsScope *s, DnsServer *if_current) {
assert(s); assert(s);
if (s->protocol != DNS_PROTOCOL_DNS) if (s->protocol != DNS_PROTOCOL_DNS)
return; return;
/* Changes to the next DNS server in the list. If 'if_current' is passed will do so only if the
* current DNS server still matches it. */
if (s->link) if (s->link)
link_next_dns_server(s->link); link_next_dns_server(s->link, if_current);
else else
manager_next_dns_server(s->manager); manager_next_dns_server(s->manager, if_current);
} }
void dns_scope_packet_received(DnsScope *s, usec_t rtt) { void dns_scope_packet_received(DnsScope *s, usec_t rtt) {
@ -459,7 +462,7 @@ int dns_scope_socket_tcp(DnsScope *s, int family, const union in_addr_union *add
return dns_scope_socket(s, SOCK_STREAM, family, address, server, port, ret_socket_address); return dns_scope_socket(s, SOCK_STREAM, family, address, server, port, ret_socket_address);
} }
static DnsScopeMatch accept_link_local_reverse_lookups(const char *domain) { static DnsScopeMatch match_link_local_reverse_lookups(const char *domain) {
assert(domain); assert(domain);
if (dns_name_endswith(domain, "254.169.in-addr.arpa") > 0) if (dns_name_endswith(domain, "254.169.in-addr.arpa") > 0)
@ -568,29 +571,25 @@ DnsScopeMatch dns_scope_good_domain(
return DNS_SCOPE_YES_BASE + n_best; return DNS_SCOPE_YES_BASE + n_best;
} }
/* See if this scope is suitable as default route. */ /* Exclude link-local IP ranges */
if (match_link_local_reverse_lookups(domain) >= DNS_SCOPE_YES_BASE ||
/* If networks use .local in their private setups, they are supposed to also add .local
* to their search domains, which we already checked above. Otherwise, we consider .local
* specific to mDNS and won't send such queries ordinary DNS servers. */
dns_name_endswith(domain, "local") > 0)
return DNS_SCOPE_NO;
/* If there was no match at all, then see if this scope is suitable as default route. */
if (!dns_scope_is_default_route(s)) if (!dns_scope_is_default_route(s))
return DNS_SCOPE_NO; return DNS_SCOPE_NO;
/* Exclude link-local IP ranges */
if (dns_name_endswith(domain, "254.169.in-addr.arpa") == 0 &&
dns_name_endswith(domain, "8.e.f.ip6.arpa") == 0 &&
dns_name_endswith(domain, "9.e.f.ip6.arpa") == 0 &&
dns_name_endswith(domain, "a.e.f.ip6.arpa") == 0 &&
dns_name_endswith(domain, "b.e.f.ip6.arpa") == 0 &&
/* If networks use .local in their private setups, they are supposed to also add .local to their search
* domains, which we already checked above. Otherwise, we consider .local specific to mDNS and won't
* send such queries ordinary DNS servers. */
dns_name_endswith(domain, "local") == 0)
return DNS_SCOPE_MAYBE; return DNS_SCOPE_MAYBE;
return DNS_SCOPE_NO;
} }
case DNS_PROTOCOL_MDNS: { case DNS_PROTOCOL_MDNS: {
DnsScopeMatch m; DnsScopeMatch m;
m = accept_link_local_reverse_lookups(domain); m = match_link_local_reverse_lookups(domain);
if (m >= 0) if (m >= 0)
return m; return m;
@ -609,7 +608,7 @@ DnsScopeMatch dns_scope_good_domain(
case DNS_PROTOCOL_LLMNR: { case DNS_PROTOCOL_LLMNR: {
DnsScopeMatch m; DnsScopeMatch m;
m = accept_link_local_reverse_lookups(domain); m = match_link_local_reverse_lookups(domain);
if (m >= 0) if (m >= 0)
return m; return m;

View File

@ -80,7 +80,7 @@ bool dns_scope_good_key(DnsScope *s, const DnsResourceKey *key);
DnsServer *dns_scope_get_dns_server(DnsScope *s); DnsServer *dns_scope_get_dns_server(DnsScope *s);
unsigned dns_scope_get_n_dns_servers(DnsScope *s); unsigned dns_scope_get_n_dns_servers(DnsScope *s);
void dns_scope_next_dns_server(DnsScope *s); void dns_scope_next_dns_server(DnsScope *s, DnsServer *if_current);
int dns_scope_llmnr_membership(DnsScope *s, bool b); int dns_scope_llmnr_membership(DnsScope *s, bool b);
int dns_scope_mdns_membership(DnsScope *s, bool b); int dns_scope_mdns_membership(DnsScope *s, bool b);

View File

@ -771,23 +771,25 @@ DnsServer *manager_get_dns_server(Manager *m) {
return m->current_dns_server; return m->current_dns_server;
} }
void manager_next_dns_server(Manager *m) { void manager_next_dns_server(Manager *m, DnsServer *if_current) {
assert(m); assert(m);
/* If there's currently no DNS server set, then the next /* If the DNS server is already a different one than the one specified in 'if_current' don't do anything */
* manager_get_dns_server() will find one */ if (if_current && m->current_dns_server != if_current)
return;
/* If there's currently no DNS server set, then the next manager_get_dns_server() will find one */
if (!m->current_dns_server) if (!m->current_dns_server)
return; return;
/* Change to the next one, but make sure to follow the linked /* Change to the next one, but make sure to follow the linked list only if the server is still
* list only if the server is still linked. */ * linked. */
if (m->current_dns_server->linked && m->current_dns_server->servers_next) { if (m->current_dns_server->linked && m->current_dns_server->servers_next) {
manager_set_dns_server(m, m->current_dns_server->servers_next); manager_set_dns_server(m, m->current_dns_server->servers_next);
return; return;
} }
/* If there was no next one, then start from the beginning of /* If there was no next one, then start from the beginning of the list */
* the list */
if (m->current_dns_server->type == DNS_SERVER_FALLBACK) if (m->current_dns_server->type == DNS_SERVER_FALLBACK)
manager_set_dns_server(m, m->fallback_dns_servers); manager_set_dns_server(m, m->fallback_dns_servers);
else else

View File

@ -143,7 +143,7 @@ DnsServer *manager_get_first_dns_server(Manager *m, DnsServerType t);
DnsServer *manager_set_dns_server(Manager *m, DnsServer *s); DnsServer *manager_set_dns_server(Manager *m, DnsServer *s);
DnsServer *manager_get_dns_server(Manager *m); DnsServer *manager_get_dns_server(Manager *m);
void manager_next_dns_server(Manager *m); void manager_next_dns_server(Manager *m, DnsServer *if_current);
DnssecMode dns_server_get_dnssec_mode(DnsServer *s); DnssecMode dns_server_get_dnssec_mode(DnsServer *s);
DnsOverTlsMode dns_server_get_dns_over_tls_mode(DnsServer *s); DnsOverTlsMode dns_server_get_dns_over_tls_mode(DnsServer *s);

View File

@ -82,6 +82,8 @@ DnsStubListenerExtra *dns_stub_listener_extra_free(DnsStubListenerExtra *p) {
p->udp_event_source = sd_event_source_unref(p->udp_event_source); p->udp_event_source = sd_event_source_unref(p->udp_event_source);
p->tcp_event_source = sd_event_source_unref(p->tcp_event_source); p->tcp_event_source = sd_event_source_unref(p->tcp_event_source);
hashmap_free(p->queries_by_packet);
return mfree(p); return mfree(p);
} }
@ -94,6 +96,47 @@ uint16_t dns_stub_listener_extra_port(DnsStubListenerExtra *p) {
return 53; return 53;
} }
static void stub_packet_hash_func(const DnsPacket *p, struct siphash *state) {
assert(p);
siphash24_compress(&p->protocol, sizeof(p->protocol), state);
siphash24_compress(&p->family, sizeof(p->family), state);
siphash24_compress(&p->sender, sizeof(p->sender), state);
siphash24_compress(&p->ipproto, sizeof(p->ipproto), state);
siphash24_compress(&p->sender_port, sizeof(p->sender_port), state);
siphash24_compress(DNS_PACKET_HEADER(p), sizeof(DnsPacketHeader), state);
/* We don't bother hashing the full packet here, just the header */
}
static int stub_packet_compare_func(const DnsPacket *x, const DnsPacket *y) {
int r;
r = CMP(x->protocol, y->protocol);
if (r != 0)
return r;
r = CMP(x->family, y->family);
if (r != 0)
return r;
r = memcmp(&x->sender, &y->sender, sizeof(x->sender));
if (r != 0)
return r;
r = CMP(x->ipproto, y->ipproto);
if (r != 0)
return r;
r = CMP(x->sender_port, y->sender_port);
if (r != 0)
return r;
return memcmp(DNS_PACKET_HEADER(x), DNS_PACKET_HEADER(y), sizeof(DnsPacketHeader));
}
DEFINE_HASH_OPS(stub_packet_hash_ops, DnsPacket, stub_packet_hash_func, stub_packet_compare_func);
static int dns_stub_collect_answer_by_question( static int dns_stub_collect_answer_by_question(
DnsAnswer **reply, DnsAnswer **reply,
DnsAnswer *answer, DnsAnswer *answer,
@ -685,6 +728,8 @@ static int dns_stub_stream_complete(DnsStream *s, int error) {
static void dns_stub_process_query(Manager *m, DnsStubListenerExtra *l, DnsStream *s, DnsPacket *p) { static void dns_stub_process_query(Manager *m, DnsStubListenerExtra *l, DnsStream *s, DnsPacket *p) {
_cleanup_(dns_query_freep) DnsQuery *q = NULL; _cleanup_(dns_query_freep) DnsQuery *q = NULL;
Hashmap **queries_by_packet;
DnsQuery *existing;
int r; int r;
assert(m); assert(m);
@ -703,6 +748,13 @@ static void dns_stub_process_query(Manager *m, DnsStubListenerExtra *l, DnsStrea
return; return;
} }
queries_by_packet = l ? &l->queries_by_packet : &m->stub_queries_by_packet;
existing = hashmap_get(*queries_by_packet, p);
if (existing && dns_packet_equal(existing->request_packet, p)) {
log_debug("Got repeat packet from client, ignoring.");
return;
}
r = dns_packet_extract(p); r = dns_packet_extract(p);
if (r < 0) { if (r < 0) {
log_debug_errno(r, "Failed to extract resources from incoming packet, ignoring packet: %m"); log_debug_errno(r, "Failed to extract resources from incoming packet, ignoring packet: %m");
@ -735,6 +787,12 @@ static void dns_stub_process_query(Manager *m, DnsStubListenerExtra *l, DnsStrea
return; return;
} }
r = hashmap_ensure_allocated(queries_by_packet, &stub_packet_hash_ops);
if (r < 0) {
log_oom();
return;
}
if (DNS_PACKET_DO(p) && DNS_PACKET_CD(p)) { if (DNS_PACKET_DO(p) && DNS_PACKET_CD(p)) {
log_debug("Got request with DNSSEC checking disabled, enabling bypass logic."); log_debug("Got request with DNSSEC checking disabled, enabling bypass logic.");
@ -774,6 +832,11 @@ static void dns_stub_process_query(Manager *m, DnsStubListenerExtra *l, DnsStrea
assert(r > 0); assert(r > 0);
} }
/* Add the query to the hash table we use to determine repeat packets now. We don't care about
* failures here, since in the worst case we'll not recognize duplicate incoming requests, which
* isn't particularly bad. */
(void) hashmap_put(*queries_by_packet, q->request_packet, q);
r = dns_query_go(q); r = dns_query_go(q);
if (r < 0) { if (r < 0) {
log_error_errno(r, "Failed to start query: %m"); log_error_errno(r, "Failed to start query: %m");

View File

@ -27,6 +27,8 @@ struct DnsStubListenerExtra {
sd_event_source *udp_event_source; sd_event_source *udp_event_source;
sd_event_source *tcp_event_source; sd_event_source *tcp_event_source;
Hashmap *queries_by_packet;
}; };
extern const struct hash_ops dns_stub_listener_extra_hash_ops; extern const struct hash_ops dns_stub_listener_extra_hash_ops;

View File

@ -484,7 +484,7 @@ static void dns_transaction_retry(DnsTransaction *t, bool next_server) {
/* Before we try again, switch to a new server. */ /* Before we try again, switch to a new server. */
if (next_server) if (next_server)
dns_scope_next_dns_server(t->scope); dns_scope_next_dns_server(t->scope, t->server);
r = dns_transaction_go(t); r = dns_transaction_go(t);
if (r < 0) if (r < 0)
@ -1859,7 +1859,7 @@ int dns_transaction_go(DnsTransaction *t) {
/* One of our own stub listeners */ /* One of our own stub listeners */
log_debug_errno(r, "Detected that specified DNS server is our own extra listener, switching DNS servers."); log_debug_errno(r, "Detected that specified DNS server is our own extra listener, switching DNS servers.");
dns_scope_next_dns_server(t->scope); dns_scope_next_dns_server(t->scope, t->server);
if (dns_scope_get_dns_server(t->scope) == t->server) { if (dns_scope_get_dns_server(t->scope) == t->server) {
log_debug_errno(r, "Still pointing to extra listener after switching DNS servers, refusing operation."); log_debug_errno(r, "Still pointing to extra listener after switching DNS servers, refusing operation.");
@ -1890,7 +1890,7 @@ int dns_transaction_go(DnsTransaction *t) {
return r; return r;
/* Couldn't send? Try immediately again, with a new server */ /* Couldn't send? Try immediately again, with a new server */
dns_scope_next_dns_server(t->scope); dns_scope_next_dns_server(t->scope, t->server);
return dns_transaction_go(t); return dns_transaction_go(t);
} }

View File

@ -731,19 +731,27 @@ DnsServer *link_get_dns_server(Link *l) {
return l->current_dns_server; return l->current_dns_server;
} }
void link_next_dns_server(Link *l) { void link_next_dns_server(Link *l, DnsServer *if_current) {
assert(l); assert(l);
/* If the current server of the transaction is specified, and we already are at a different one,
* don't do anything */
if (if_current && l->current_dns_server != if_current)
return;
/* If currently have no DNS server, then don't do anything, we'll pick it lazily the next time a DNS
* server is needed. */
if (!l->current_dns_server) if (!l->current_dns_server)
return; return;
/* Change to the next one, but make sure to follow the linked /* Change to the next one, but make sure to follow the linked list only if this server is actually
* list only if this server is actually still linked. */ * still linked. */
if (l->current_dns_server->linked && l->current_dns_server->servers_next) { if (l->current_dns_server->linked && l->current_dns_server->servers_next) {
link_set_dns_server(l, l->current_dns_server->servers_next); link_set_dns_server(l, l->current_dns_server->servers_next);
return; return;
} }
/* Pick the first one again, after we reached the end */
link_set_dns_server(l, l->dns_servers); link_set_dns_server(l, l->dns_servers);
} }

View File

@ -91,7 +91,7 @@ void link_allocate_scopes(Link *l);
DnsServer* link_set_dns_server(Link *l, DnsServer *s); DnsServer* link_set_dns_server(Link *l, DnsServer *s);
DnsServer* link_get_dns_server(Link *l); DnsServer* link_get_dns_server(Link *l);
void link_next_dns_server(Link *l); void link_next_dns_server(Link *l, DnsServer *if_current);
DnssecMode link_get_dnssec_mode(Link *l); DnssecMode link_get_dnssec_mode(Link *l);
bool link_dnssec_supported(Link *l); bool link_dnssec_supported(Link *l);

View File

@ -739,6 +739,8 @@ Manager *manager_free(Manager *m) {
while (m->dns_queries) while (m->dns_queries)
dns_query_free(m->dns_queries); dns_query_free(m->dns_queries);
m->stub_queries_by_packet = hashmap_free(m->stub_queries_by_packet);
dns_scope_free(m->unicast_scope); dns_scope_free(m->unicast_scope);
/* At this point only orphaned streams should remain. All others should have been freed already by their /* At this point only orphaned streams should remain. All others should have been freed already by their

View File

@ -59,6 +59,7 @@ struct Manager {
Hashmap *dns_transactions; Hashmap *dns_transactions;
LIST_HEAD(DnsQuery, dns_queries); LIST_HEAD(DnsQuery, dns_queries);
unsigned n_dns_queries; unsigned n_dns_queries;
Hashmap *stub_queries_by_packet;
LIST_HEAD(DnsStream, dns_streams); LIST_HEAD(DnsStream, dns_streams);
unsigned n_dns_streams[_DNS_STREAM_TYPE_MAX]; unsigned n_dns_streams[_DNS_STREAM_TYPE_MAX];
@ -97,13 +98,12 @@ struct Manager {
/* mDNS */ /* mDNS */
int mdns_ipv4_fd; int mdns_ipv4_fd;
int mdns_ipv6_fd; int mdns_ipv6_fd;
sd_event_source *mdns_ipv4_event_source;
sd_event_source *mdns_ipv6_event_source;
/* DNS-SD */ /* DNS-SD */
Hashmap *dnssd_services; Hashmap *dnssd_services;
sd_event_source *mdns_ipv4_event_source;
sd_event_source *mdns_ipv6_event_source;
/* dbus */ /* dbus */
sd_bus *bus; sd_bus *bus;

View File

@ -1398,7 +1398,7 @@ int show_journal(
if (line == 0 && noaccess) if (line == 0 && noaccess)
fprintf(f, "Warning: some journal files were not opened due to insufficient permissions."); fprintf(f, "Warning: some journal files were not opened due to insufficient permissions.");
else if (!noaccess) else if (!noaccess)
fprintf(f, "Warning: journal has been rotated since unit was started, output may be incomplete.\n"); fprintf(f, "Notice: journal has been rotated since unit was started, output may be incomplete.\n");
else else
fprintf(f, "Warning: journal has been rotated since unit was started and some journal " fprintf(f, "Warning: journal has been rotated since unit was started and some journal "
"files were not opened due to insufficient permissions, output may be incomplete.\n"); "files were not opened due to insufficient permissions, output may be incomplete.\n");

View File

@ -912,39 +912,37 @@ int systemctl_dispatch_parse_argv(int argc, char *argv[]) {
assert(argc >= 0); assert(argc >= 0);
assert(argv); assert(argv);
if (program_invocation_short_name) { if (strstr_ptr(argv[0], "halt")) {
if (strstr(program_invocation_short_name, "halt")) {
arg_action = ACTION_HALT; arg_action = ACTION_HALT;
return halt_parse_argv(argc, argv); return halt_parse_argv(argc, argv);
} else if (strstr(program_invocation_short_name, "poweroff")) { } else if (strstr_ptr(argv[0], "poweroff")) {
arg_action = ACTION_POWEROFF; arg_action = ACTION_POWEROFF;
return halt_parse_argv(argc, argv); return halt_parse_argv(argc, argv);
} else if (strstr(program_invocation_short_name, "reboot")) { } else if (strstr_ptr(argv[0], "reboot")) {
if (kexec_loaded()) if (kexec_loaded())
arg_action = ACTION_KEXEC; arg_action = ACTION_KEXEC;
else else
arg_action = ACTION_REBOOT; arg_action = ACTION_REBOOT;
return halt_parse_argv(argc, argv); return halt_parse_argv(argc, argv);
} else if (strstr(program_invocation_short_name, "shutdown")) { } else if (strstr_ptr(argv[0], "shutdown")) {
arg_action = ACTION_POWEROFF; arg_action = ACTION_POWEROFF;
return shutdown_parse_argv(argc, argv); return shutdown_parse_argv(argc, argv);
} else if (strstr(program_invocation_short_name, "init")) { } else if (strstr_ptr(argv[0], "init")) {
/* Matches invocations as "init" as well as "telinit", which are synonymous when run /* Matches invocations as "init" as well as "telinit", which are synonymous when run
* as PID != 1 on SysV. * as PID != 1 on SysV.
* *
* On SysV "telinit" was the official command to communicate with PID 1, but "init" would * On SysV "telinit" was the official command to communicate with PID 1, but "init" would
* redirect itself to "telinit" if called with PID != 1. We follow the same logic here still, * redirect itself to "telinit" if called with PID != 1. We follow the same logic here still,
* though we add one level of indirection, as we implement "telinit" in "systemctl". Hence, for * though we add one level of indirection, as we implement "telinit" in "systemctl". Hence,
* us if you invoke "init" you get "systemd", but it will execve() "systemctl" immediately with * for us if you invoke "init" you get "systemd", but it will execve() "systemctl"
* argv[] unmodified if PID is != 1. If you invoke "telinit" you directly get "systemctl". In * immediately with argv[] unmodified if PID is != 1. If you invoke "telinit" you directly
* both cases we shall do the same thing, which is why we do strstr(p_i_s_n, "init") here, as a * get "systemctl". In both cases we shall do the same thing, which is why we do
* quick way to match both. * strstr_ptr(argv[0], "init") here, as a quick way to match both.
* *
* Also see redirect_telinit() in src/core/main.c. */ * Also see redirect_telinit() in src/core/main.c. */
@ -952,18 +950,16 @@ int systemctl_dispatch_parse_argv(int argc, char *argv[]) {
arg_action = _ACTION_INVALID; arg_action = _ACTION_INVALID;
return telinit_parse_argv(argc, argv); return telinit_parse_argv(argc, argv);
} else { } else {
/* Hmm, so some other init system is running, we need to forward this request /* Hmm, so some other init system is running, we need to forward this request to it.
* to it. */ */
arg_action = ACTION_TELINIT; arg_action = ACTION_TELINIT;
return 1; return 1;
} }
} else if (strstr(program_invocation_short_name, "runlevel")) { } else if (strstr_ptr(argv[0], "runlevel")) {
arg_action = ACTION_RUNLEVEL; arg_action = ACTION_RUNLEVEL;
return runlevel_parse_argv(argc, argv); return runlevel_parse_argv(argc, argv);
} }
}
arg_action = ACTION_SYSTEMCTL; arg_action = ACTION_SYSTEMCTL;
return systemctl_parse_argv(argc, argv); return systemctl_parse_argv(argc, argv);

View File

@ -124,6 +124,32 @@ EOF
clear_services test15-a test15-b test15-c clear_services test15-a test15-b test15-c
} }
test_linked_units () {
echo "Testing linked units..."
echo "*** test linked unit (same basename)"
create_service test15-a
mv /etc/systemd/system/test15-a.service /
ln -s /test15-a.service /etc/systemd/system/
ln -s test15-a.service /etc/systemd/system/test15-b.service
check_ok test15-a Names test15-a.service
check_ok test15-a Names test15-b.service
echo "*** test linked unit (cross basename)"
mv /test15-a.service /test15-a@.scope
ln -fs /test15-a@.scope /etc/systemd/system/test15-a.service
systemctl daemon-reload
check_ok test15-a Names test15-a.service
check_ok test15-a Names test15-b.service
check_ko test15-a Names test15-b@
rm /test15-a@.scope
clear_services test15-a test15-b
}
test_hierarchical_dropins () { test_hierarchical_dropins () {
echo "Testing hierarchical dropins..." echo "Testing hierarchical dropins..."
echo "*** test service.d/ top level drop-in" echo "*** test service.d/ top level drop-in"
@ -465,6 +491,7 @@ test_invalid_dropins () {
} }
test_basic_dropins test_basic_dropins
test_linked_units
test_hierarchical_dropins test_hierarchical_dropins
test_template_dropins test_template_dropins
test_alias_dropins test_alias_dropins