summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--NEWS21
-rw-r--r--man/systemctl.xml12
-rw-r--r--src/login/logind-dbus.c45
-rw-r--r--src/login/org.freedesktop.login1.conf4
-rw-r--r--src/login/org.freedesktop.login1.policy.in12
-rw-r--r--src/network/networkd-link.c2
-rw-r--r--src/network/networkd-network-gperf.gperf2
-rw-r--r--src/network/networkd-network.c30
-rw-r--r--src/network/networkd.h28
-rw-r--r--src/resolve-host/resolve-host.c20
-rw-r--r--src/resolve/resolved-bus.c16
-rw-r--r--src/resolve/resolved-dns-cache.c30
-rw-r--r--src/resolve/resolved-dns-packet.c43
-rw-r--r--src/resolve/resolved-dns-packet.h9
-rw-r--r--src/resolve/resolved-dns-query.c8
-rw-r--r--src/resolve/resolved-dns-scope.c60
-rw-r--r--src/resolve/resolved-dns-scope.h2
-rw-r--r--src/resolve/resolved-dns-transaction.c48
-rw-r--r--src/systemctl/systemctl.c102
19 files changed, 316 insertions, 178 deletions
diff --git a/NEWS b/NEWS
index fe5eb31672..7f35f66a8d 100644
--- a/NEWS
+++ b/NEWS
@@ -1,5 +1,26 @@
systemd System and Service Manager
+CHANGES WITH 225:
+
+ * Mostly a bugfix release, with tree-wide cleanups
+
+ * systemd-networkd learned to cope with private-zone DHCP options and
+ allows other programs to query the values.
+
+ Contributions from: Alastair Hughes, Alex Crawford, Daniel Mack,
+ David Herrmann, Dimitri John Ledkov, Eric Kostrowski, Evgeny
+ Vereshchagin, Felipe Sateler, Jan Pokorný, Jan Synacek, Johnny
+ Robeson, Karel Zak, Kay Sievers, Kefeng Wang, Lennart
+ Poettering, Major Hayden, Marcel Holtmann, Markus Elfring,
+ Martin Mikkelsen, Matt Turner, Maxim Mikityanskiy, Michael
+ Biebl, Namhyung Kim, Nicolas Cornu, Owen W. Taylor, Patrik
+ Flykt, Peter Hutterer, reverendhomer, Richard Maw, Ronny
+ Chevalier, Seth Jennings, Stef Walter, Susant Sahani, Thomas
+ Blume, Thomas Hindoe Paaboel Andersen, Thomas Meyer, Tom
+ Gundersen, WaLyong Cho, Zbigniew Jędrzejewski-Szmek
+
+ -- Berlin, 2015-xx-xx
+
CHANGES WITH 224:
* The systemd-efi-boot-generator functionality was merged into
diff --git a/man/systemctl.xml b/man/systemctl.xml
index 0b5282ba21..20d143741b 100644
--- a/man/systemctl.xml
+++ b/man/systemctl.xml
@@ -474,6 +474,18 @@
</varlistentry>
<varlistentry>
+ <term><option>--message=</option></term>
+
+ <listitem>
+ <para>When used with <command>halt</command>,
+ <command>poweroff</command>, <command>reboot</command> or
+ <command>kexec</command>, set a short message explaining the reason
+ for the operation. The message will be logged together with the
+ default shutdown message.</para>
+ </listitem>
+ </varlistentry>
+
+ <varlistentry>
<term><option>--now</option></term>
<listitem>
diff --git a/src/login/logind-dbus.c b/src/login/logind-dbus.c
index 992a9f5b4a..5b2b36b9c0 100644
--- a/src/login/logind-dbus.c
+++ b/src/login/logind-dbus.c
@@ -1339,7 +1339,8 @@ static int bus_manager_log_shutdown(
InhibitWhat w,
const char *unit_name) {
- const char *p, *q;
+ const char *p;
+ const char *q;
assert(m);
assert(unit_name);
@@ -1364,6 +1365,9 @@ static int bus_manager_log_shutdown(
q = NULL;
}
+ if (m->wall_message)
+ p = strjoina(p, " (", m->wall_message, ")", NULL);
+
return log_struct(LOG_NOTICE,
LOG_MESSAGE_ID(SD_MESSAGE_SHUTDOWN),
p,
@@ -2282,6 +2286,44 @@ static int method_can_reboot_to_firmware_setup(
return sd_bus_reply_method_return(message, "s", result);
}
+static int method_set_wall_message(
+ sd_bus_message *message,
+ void *userdata,
+ sd_bus_error *error) {
+
+ int r;
+ Manager *m = userdata;
+ char *wall_message;
+ bool enable_wall_messages;
+
+ assert(message);
+ assert(m);
+
+ r = sd_bus_message_read(message, "sb", &wall_message, &enable_wall_messages);
+ if (r < 0)
+ return r;
+
+ r = bus_verify_polkit_async(message,
+ CAP_SYS_ADMIN,
+ "org.freedesktop.login1.set-wall-message",
+ false,
+ UID_INVALID,
+ &m->polkit_registry,
+ error);
+
+ if (r < 0)
+ return r;
+ if (r == 0)
+ return 1; /* Will call us back */
+
+ r = free_and_strdup(&m->wall_message, wall_message);
+ if (r < 0)
+ return log_oom();
+ m->enable_wall_messages = enable_wall_messages;
+
+ return sd_bus_reply_method_return(message, NULL);
+}
+
static int method_inhibit(sd_bus_message *message, void *userdata, sd_bus_error *error) {
_cleanup_bus_creds_unref_ sd_bus_creds *creds = NULL;
const char *who, *why, *what, *mode;
@@ -2463,6 +2505,7 @@ const sd_bus_vtable manager_vtable[] = {
SD_BUS_METHOD("Inhibit", "ssss", "h", method_inhibit, SD_BUS_VTABLE_UNPRIVILEGED),
SD_BUS_METHOD("CanRebootToFirmwareSetup", NULL, "s", method_can_reboot_to_firmware_setup, SD_BUS_VTABLE_UNPRIVILEGED),
SD_BUS_METHOD("SetRebootToFirmwareSetup", "b", NULL, method_set_reboot_to_firmware_setup, SD_BUS_VTABLE_UNPRIVILEGED),
+ SD_BUS_METHOD("SetWallMessage", "sb", NULL, method_set_wall_message, SD_BUS_VTABLE_UNPRIVILEGED),
SD_BUS_SIGNAL("SessionNew", "so", 0),
SD_BUS_SIGNAL("SessionRemoved", "so", 0),
diff --git a/src/login/org.freedesktop.login1.conf b/src/login/org.freedesktop.login1.conf
index d8deb7bc8b..1662d4c428 100644
--- a/src/login/org.freedesktop.login1.conf
+++ b/src/login/org.freedesktop.login1.conf
@@ -182,6 +182,10 @@
<allow send_destination="org.freedesktop.login1"
send_interface="org.freedesktop.login1.Manager"
+ send_member="SetWallMessage"/>
+
+ <allow send_destination="org.freedesktop.login1"
+ send_interface="org.freedesktop.login1.Manager"
send_member="AttachDevice"/>
<allow send_destination="org.freedesktop.login1"
diff --git a/src/login/org.freedesktop.login1.policy.in b/src/login/org.freedesktop.login1.policy.in
index 83e7183323..23326bb79f 100644
--- a/src/login/org.freedesktop.login1.policy.in
+++ b/src/login/org.freedesktop.login1.policy.in
@@ -150,6 +150,7 @@
<allow_inactive>auth_admin_keep</allow_inactive>
<allow_active>yes</allow_active>
</defaults>
+ <annotate key="org.freedesktop.policykit.imply">org.freedesktop.login1.set-wall-message</annotate>
</action>
<action id="org.freedesktop.login1.power-off-multiple-sessions">
@@ -182,6 +183,7 @@
<allow_inactive>auth_admin_keep</allow_inactive>
<allow_active>yes</allow_active>
</defaults>
+ <annotate key="org.freedesktop.policykit.imply">org.freedesktop.login1.set-wall-message</annotate>
</action>
<action id="org.freedesktop.login1.reboot-multiple-sessions">
@@ -300,4 +302,14 @@
</defaults>
</action>
+ <action id="org.freedesktop.login1.set-wall-message">
+ <_description>Set a wall message</_description>
+ <_message>Authentication is required to set a wall message</_message>
+ <defaults>
+ <allow_any>auth_admin_keep</allow_any>
+ <allow_inactive>auth_admin_keep</allow_inactive>
+ <allow_active>auth_admin_keep</allow_active>
+ </defaults>
+ </action>
+
</policyconfig>
diff --git a/src/network/networkd-link.c b/src/network/networkd-link.c
index 91b9cdf30d..cc9dc393c6 100644
--- a/src/network/networkd-link.c
+++ b/src/network/networkd-link.c
@@ -2378,7 +2378,7 @@ int link_save(Link *link) {
yes_no(link->network->wildcard_domain));
fprintf(f, "LLMNR=%s\n",
- llmnr_support_to_string(link->network->llmnr));
+ resolve_support_to_string(link->network->llmnr));
}
if (!hashmap_isempty(link->bound_to_links)) {
diff --git a/src/network/networkd-network-gperf.gperf b/src/network/networkd-network-gperf.gperf
index 8735b39581..7ac7ef1ea3 100644
--- a/src/network/networkd-network-gperf.gperf
+++ b/src/network/networkd-network-gperf.gperf
@@ -45,7 +45,7 @@ Network.Address, config_parse_address, 0
Network.Gateway, config_parse_gateway, 0, 0
Network.Domains, config_parse_domains, 0, offsetof(Network, domains)
Network.DNS, config_parse_strv, 0, offsetof(Network, dns)
-Network.LLMNR, config_parse_llmnr, 0, offsetof(Network, llmnr)
+Network.LLMNR, config_parse_resolve, 0, offsetof(Network, llmnr)
Network.NTP, config_parse_strv, 0, offsetof(Network, ntp)
Network.IPForward, config_parse_address_family_boolean_with_kernel,0, offsetof(Network, ip_forward)
Network.IPMasquerade, config_parse_bool, 0, offsetof(Network, ip_masquerade)
diff --git a/src/network/networkd-network.c b/src/network/networkd-network.c
index 3f7e77da3e..6587ea994c 100644
--- a/src/network/networkd-network.c
+++ b/src/network/networkd-network.c
@@ -111,7 +111,7 @@ static int network_load_one(Manager *manager, const char *filename) {
network->allow_port_to_be_root = true;
network->unicast_flood = true;
- network->llmnr = LLMNR_SUPPORT_YES;
+ network->llmnr = RESOLVE_SUPPORT_YES;
network->link_local = ADDRESS_FAMILY_IPV6;
@@ -632,15 +632,15 @@ static const char* const dhcp_client_identifier_table[_DHCP_CLIENT_ID_MAX] = {
DEFINE_PRIVATE_STRING_TABLE_LOOKUP_FROM_STRING(dhcp_client_identifier, DCHPClientIdentifier);
DEFINE_CONFIG_PARSE_ENUM(config_parse_dhcp_client_identifier, dhcp_client_identifier, DCHPClientIdentifier, "Failed to parse client identifier type");
-static const char* const llmnr_support_table[_LLMNR_SUPPORT_MAX] = {
- [LLMNR_SUPPORT_NO] = "no",
- [LLMNR_SUPPORT_YES] = "yes",
- [LLMNR_SUPPORT_RESOLVE] = "resolve",
+static const char* const resolve_support_table[_RESOLVE_SUPPORT_MAX] = {
+ [RESOLVE_SUPPORT_NO] = "no",
+ [RESOLVE_SUPPORT_YES] = "yes",
+ [RESOLVE_SUPPORT_RESOLVE] = "resolve",
};
-DEFINE_STRING_TABLE_LOOKUP(llmnr_support, LLMNRSupport);
+DEFINE_STRING_TABLE_LOOKUP(resolve_support, ResolveSupport);
-int config_parse_llmnr(
+int config_parse_resolve(
const char* unit,
const char *filename,
unsigned line,
@@ -652,32 +652,32 @@ int config_parse_llmnr(
void *data,
void *userdata) {
- LLMNRSupport *llmnr = data;
+ ResolveSupport *resolve = data;
int k;
assert(filename);
assert(lvalue);
assert(rvalue);
- assert(llmnr);
+ assert(resolve);
/* Our enum shall be a superset of booleans, hence first try
* to parse as boolean, and then as enum */
k = parse_boolean(rvalue);
if (k > 0)
- *llmnr = LLMNR_SUPPORT_YES;
+ *resolve = RESOLVE_SUPPORT_YES;
else if (k == 0)
- *llmnr = LLMNR_SUPPORT_NO;
+ *resolve = RESOLVE_SUPPORT_NO;
else {
- LLMNRSupport s;
+ ResolveSupport s;
- s = llmnr_support_from_string(rvalue);
+ s = resolve_support_from_string(rvalue);
if (s < 0){
- log_syntax(unit, LOG_ERR, filename, line, -s, "Failed to parse LLMNR option, ignoring: %s", rvalue);
+ log_syntax(unit, LOG_ERR, filename, line, -s, "Failed to parse %s option, ignoring: %s", lvalue, rvalue);
return 0;
}
- *llmnr = s;
+ *resolve = s;
}
return 0;
diff --git a/src/network/networkd.h b/src/network/networkd.h
index a285a4b08f..5340922bf1 100644
--- a/src/network/networkd.h
+++ b/src/network/networkd.h
@@ -64,13 +64,13 @@ typedef enum AddressFamilyBoolean {
_ADDRESS_FAMILY_BOOLEAN_INVALID = -1,
} AddressFamilyBoolean;
-typedef enum LLMNRSupport {
- LLMNR_SUPPORT_NO,
- LLMNR_SUPPORT_YES,
- LLMNR_SUPPORT_RESOLVE,
- _LLMNR_SUPPORT_MAX,
- _LLMNR_SUPPORT_INVALID = -1,
-} LLMNRSupport;
+typedef enum ResolveSupport {
+ RESOLVE_SUPPORT_NO,
+ RESOLVE_SUPPORT_YES,
+ RESOLVE_SUPPORT_RESOLVE,
+ _RESOLVE_SUPPORT_MAX,
+ _RESOLVE_SUPPORT_INVALID = -1,
+} ResolveSupport;
typedef enum LinkOperationalState {
LINK_OPERSTATE_OFF,
@@ -178,7 +178,7 @@ struct Network {
bool wildcard_domain;
char **domains, **dns, **ntp, **bind_carrier;
- LLMNRSupport llmnr;
+ ResolveSupport llmnr;
LIST_FIELDS(Network, networks);
};
@@ -421,14 +421,14 @@ int config_parse_ipv6token(const char *unit, const char *filename, unsigned line
const char *section, unsigned section_line, const char *lvalue,
int ltype, const char *rvalue, void *data, void *userdata);
-/* LLMNR support */
+/* Resolve protocols support */
-const char* llmnr_support_to_string(LLMNRSupport i) _const_;
-LLMNRSupport llmnr_support_from_string(const char *s) _pure_;
+const char* resolve_support_to_string(ResolveSupport i) _const_;
+ResolveSupport resolve_support_from_string(const char *s) _pure_;
-int config_parse_llmnr(const char *unit, const char *filename, unsigned line,
- const char *section, unsigned section_line, const char *lvalue,
- int ltype, const char *rvalue, void *data, void *userdata);
+int config_parse_resolve(const char *unit, const char *filename, unsigned line,
+ const char *section, unsigned section_line, const char *lvalue,
+ int ltype, const char *rvalue, void *data, void *userdata);
/* Address Pool */
diff --git a/src/resolve-host/resolve-host.c b/src/resolve-host/resolve-host.c
index 4a7d1e3173..9847effb53 100644
--- a/src/resolve-host/resolve-host.c
+++ b/src/resolve-host/resolve-host.c
@@ -490,7 +490,7 @@ static int parse_argv(int argc, char *argv[]) {
{ "version", no_argument, NULL, ARG_VERSION },
{ "type", required_argument, NULL, 't' },
{ "class", required_argument, NULL, 'c' },
- { "legend", optional_argument, NULL, ARG_LEGEND },
+ { "legend", optional_argument, NULL, ARG_LEGEND },
{ "protocol", required_argument, NULL, 'p' },
{}
};
@@ -520,11 +520,21 @@ static int parse_argv(int argc, char *argv[]) {
arg_family = AF_INET6;
break;
- case 'i':
- arg_ifindex = if_nametoindex(optarg);
- if (arg_ifindex <= 0)
- return log_error_errno(errno, "Unknown interfaces %s: %m", optarg);
+ case 'i': {
+ int ifi;
+
+ if (safe_atoi(optarg, &ifi) >= 0 && ifi > 0)
+ arg_ifindex = ifi;
+ else {
+ ifi = if_nametoindex(optarg);
+ if (ifi <= 0)
+ return log_error_errno(errno, "Unknown interface %s: %m", optarg);
+
+ arg_ifindex = ifi;
+ }
+
break;
+ }
case 't':
if (streq(optarg, "help")) {
diff --git a/src/resolve/resolved-bus.c b/src/resolve/resolved-bus.c
index 1f23834ce3..12c17003e9 100644
--- a/src/resolve/resolved-bus.c
+++ b/src/resolve/resolved-bus.c
@@ -226,10 +226,6 @@ static void bus_method_resolve_hostname_complete(DnsQuery *q) {
* query, this time with the cname */
if (added <= 0) {
r = dns_query_go(q);
- if (r == -ESRCH) {
- r = sd_bus_reply_method_errorf(q->request, BUS_ERROR_NO_NAME_SERVERS, "No appropriate name servers or networks for name found");
- goto finish;
- }
if (r < 0) {
r = sd_bus_reply_method_errno(q->request, -r, NULL);
goto finish;
@@ -346,10 +342,6 @@ static int bus_method_resolve_hostname(sd_bus_message *message, void *userdata,
r = dns_query_go(q);
if (r < 0) {
dns_query_free(q);
-
- if (r == -ESRCH)
- sd_bus_error_setf(error, BUS_ERROR_NO_NAME_SERVERS, "No appropriate name servers or networks for name found");
-
return r;
}
@@ -494,10 +486,6 @@ static int bus_method_resolve_address(sd_bus_message *message, void *userdata, s
r = dns_query_go(q);
if (r < 0) {
dns_query_free(q);
-
- if (r == -ESRCH)
- sd_bus_error_setf(error, BUS_ERROR_NO_NAME_SERVERS, "No appropriate name servers or networks for name found");
-
return r;
}
@@ -647,10 +635,6 @@ static int bus_method_resolve_record(sd_bus_message *message, void *userdata, sd
r = dns_query_go(q);
if (r < 0) {
dns_query_free(q);
-
- if (r == -ESRCH)
- sd_bus_error_setf(error, BUS_ERROR_NO_NAME_SERVERS, "No appropriate name servers or networks for name found");
-
return r;
}
diff --git a/src/resolve/resolved-dns-cache.c b/src/resolve/resolved-dns-cache.c
index efc407dbc6..7ee098397c 100644
--- a/src/resolve/resolved-dns-cache.c
+++ b/src/resolve/resolved-dns-cache.c
@@ -411,16 +411,17 @@ int dns_cache_put(
int owner_family,
const union in_addr_union *owner_address) {
- unsigned i;
+ unsigned cache_keys, i;
int r;
assert(c);
- assert(q);
- /* First, delete all matching old RRs, so that we only keep
- * complete by_key in place. */
- for (i = 0; i < q->n_keys; i++)
- dns_cache_remove(c, q->keys[i]);
+ if (q) {
+ /* First, if we were passed a question, delete all matching old RRs,
+ * so that we only keep complete by_key in place. */
+ for (i = 0; i < q->n_keys; i++)
+ dns_cache_remove(c, q->keys[i]);
+ }
if (!answer)
return 0;
@@ -435,8 +436,13 @@ int dns_cache_put(
if (!IN_SET(rcode, DNS_RCODE_SUCCESS, DNS_RCODE_NXDOMAIN))
return 0;
+ cache_keys = answer->n_rrs;
+
+ if (q)
+ cache_keys += q->n_keys;
+
/* Make some space for our new entries */
- dns_cache_make_space(c, answer->n_rrs + q->n_keys);
+ dns_cache_make_space(c, cache_keys);
if (timestamp <= 0)
timestamp = now(clock_boottime_or_monotonic());
@@ -448,6 +454,9 @@ int dns_cache_put(
goto fail;
}
+ if (!q)
+ return 0;
+
/* Third, add in negative entries for all keys with no RR */
for (i = 0; i < q->n_keys; i++) {
DnsResourceRecord *soa = NULL;
@@ -479,8 +488,11 @@ fail:
/* Adding all RRs failed. Let's clean up what we already
* added, just in case */
- for (i = 0; i < q->n_keys; i++)
- dns_cache_remove(c, q->keys[i]);
+ if (q) {
+ for (i = 0; i < q->n_keys; i++)
+ dns_cache_remove(c, q->keys[i]);
+ }
+
for (i = 0; i < answer->n_rrs; i++)
dns_cache_remove(c, answer->items[i].rr->key);
diff --git a/src/resolve/resolved-dns-packet.c b/src/resolve/resolved-dns-packet.c
index bebd1ee4a6..784d949cce 100644
--- a/src/resolve/resolved-dns-packet.c
+++ b/src/resolve/resolved-dns-packet.c
@@ -64,7 +64,7 @@ int dns_packet_new(DnsPacket **ret, DnsProtocol protocol, size_t mtu) {
int dns_packet_new_query(DnsPacket **ret, DnsProtocol protocol, size_t mtu) {
DnsPacket *p;
DnsPacketHeader *h;
- int r;
+ int r, rd;
assert(ret);
@@ -74,26 +74,27 @@ int dns_packet_new_query(DnsPacket **ret, DnsProtocol protocol, size_t mtu) {
h = DNS_PACKET_HEADER(p);
- if (protocol == DNS_PROTOCOL_LLMNR)
- h->flags = htobe16(DNS_PACKET_MAKE_FLAGS(0 /* qr */,
- 0 /* opcode */,
- 0 /* c */,
- 0 /* tc */,
- 0 /* t */,
- 0 /* ra */,
- 0 /* ad */,
- 0 /* cd */,
- 0 /* rcode */));
- else
- h->flags = htobe16(DNS_PACKET_MAKE_FLAGS(0 /* qr */,
- 0 /* opcode */,
- 0 /* aa */,
- 0 /* tc */,
- 1 /* rd (ask for recursion) */,
- 0 /* ra */,
- 0 /* ad */,
- 0 /* cd */,
- 0 /* rcode */));
+ switch (protocol) {
+ case DNS_PROTOCOL_LLMNR:
+ /* no recursion for link-local resolving protocols */
+ rd = 0;
+ break;
+
+ default:
+ /* ask for recursion */
+ rd = 1;
+ break;
+ }
+
+ h->flags = htobe16(DNS_PACKET_MAKE_FLAGS(0 /* qr */,
+ 0 /* opcode */,
+ 0 /* aa */,
+ 0 /* tc */,
+ rd /* rd */,
+ 0 /* ra */,
+ 0 /* ad */,
+ 0 /* cd */,
+ 0 /* rcode */));
*ret = p;
return 0;
diff --git a/src/resolve/resolved-dns-packet.h b/src/resolve/resolved-dns-packet.h
index e81f8a8202..8a72b898da 100644
--- a/src/resolve/resolved-dns-packet.h
+++ b/src/resolve/resolved-dns-packet.h
@@ -239,11 +239,16 @@ static inline uint64_t SD_RESOLVED_FLAGS_MAKE(DnsProtocol protocol, int family)
/* Converts a protocol + family into a flags field as used in queries */
- if (protocol == DNS_PROTOCOL_DNS)
+ switch (protocol) {
+ case DNS_PROTOCOL_DNS:
return SD_RESOLVED_DNS;
- if (protocol == DNS_PROTOCOL_LLMNR)
+ case DNS_PROTOCOL_LLMNR:
return family == AF_INET6 ? SD_RESOLVED_LLMNR_IPV6 : SD_RESOLVED_LLMNR_IPV4;
+ default:
+ break;
+ }
+
return 0;
}
diff --git a/src/resolve/resolved-dns-query.c b/src/resolve/resolved-dns-query.c
index d9f5b342b2..c0b4c8ba81 100644
--- a/src/resolve/resolved-dns-query.c
+++ b/src/resolve/resolved-dns-query.c
@@ -651,12 +651,8 @@ int dns_query_go(DnsQuery *q) {
DnsTransactionState state = DNS_TRANSACTION_NO_SERVERS;
dns_query_synthesize_reply(q, &state);
- if (state != DNS_TRANSACTION_NO_SERVERS) {
- dns_query_complete(q, state);
- return 1;
- }
-
- return -ESRCH;
+ dns_query_complete(q, state);
+ return 1;
}
r = dns_query_add_transaction_split(q, first);
diff --git a/src/resolve/resolved-dns-scope.c b/src/resolve/resolved-dns-scope.c
index 57a2c7d6c1..77034a0be8 100644
--- a/src/resolve/resolved-dns-scope.c
+++ b/src/resolve/resolved-dns-scope.c
@@ -78,8 +78,7 @@ DnsScope* dns_scope_free(DnsScope *s) {
dns_scope_llmnr_membership(s, false);
- while ((t = s->transactions)) {
-
+ while ((t = hashmap_steal_first(s->transactions))) {
/* Abort the transaction, but make sure it is not
* freed while we still look at it */
@@ -90,6 +89,8 @@ DnsScope* dns_scope_free(DnsScope *s) {
dns_transaction_free(t);
}
+ hashmap_free(s->transactions);
+
while ((rr = ordered_hashmap_steal_first(s->conflict_queue)))
dns_resource_record_unref(rr);
@@ -165,7 +166,8 @@ int dns_scope_emit(DnsScope *s, int fd, DnsPacket *p) {
} else
mtu = manager_find_mtu(s->manager);
- if (s->protocol == DNS_PROTOCOL_DNS) {
+ switch (s->protocol) {
+ case DNS_PROTOCOL_DNS:
if (DNS_PACKET_QDCOUNT(p) > 1)
return -EOPNOTSUPP;
@@ -179,8 +181,9 @@ int dns_scope_emit(DnsScope *s, int fd, DnsPacket *p) {
if (r < 0)
return r;
- } else if (s->protocol == DNS_PROTOCOL_LLMNR) {
+ break;
+ case DNS_PROTOCOL_LLMNR:
if (DNS_PACKET_QDCOUNT(p) > 1)
return -EOPNOTSUPP;
@@ -204,8 +207,12 @@ int dns_scope_emit(DnsScope *s, int fd, DnsPacket *p) {
r = manager_send(s->manager, fd, ifindex, family, &addr, port, p);
if (r < 0)
return r;
- } else
+
+ break;
+
+ default:
return -EAFNOSUPPORT;
+ }
return 1;
}
@@ -340,27 +347,25 @@ DnsScopeMatch dns_scope_good_domain(DnsScope *s, int ifindex, uint64_t flags, co
if (dns_name_endswith(domain, *i) > 0)
return DNS_SCOPE_YES;
- if (s->protocol == DNS_PROTOCOL_DNS) {
+ switch (s->protocol) {
+ case DNS_PROTOCOL_DNS:
if (dns_name_endswith(domain, "254.169.in-addr.arpa") == 0 &&
dns_name_endswith(domain, "0.8.e.f.ip6.arpa") == 0 &&
dns_name_single_label(domain) == 0)
return DNS_SCOPE_MAYBE;
return DNS_SCOPE_NO;
- }
- if (s->protocol == DNS_PROTOCOL_MDNS) {
+ case DNS_PROTOCOL_MDNS:
if ((s->family == AF_INET && dns_name_endswith(domain, "in-addr.arpa") > 0) ||
(s->family == AF_INET6 && dns_name_endswith(domain, "ip6.arpa") > 0) ||
(dns_name_endswith(domain, "local") > 0 && /* only resolve names ending in .local via mDNS */
dns_name_equal(domain, "local") == 0 && /* but not the single-label "local" name itself */
manager_is_own_hostname(s->manager, domain) <= 0)) /* never resolve the local hostname via mDNS */
- return DNS_SCOPE_MAYBE;
return DNS_SCOPE_NO;
- }
- if (s->protocol == DNS_PROTOCOL_LLMNR) {
+ case DNS_PROTOCOL_LLMNR:
if ((s->family == AF_INET && dns_name_endswith(domain, "in-addr.arpa") > 0) ||
(s->family == AF_INET6 && dns_name_endswith(domain, "ip6.arpa") > 0) ||
(dns_name_single_label(domain) > 0 && /* only resolve single label names via LLMNR */
@@ -369,9 +374,10 @@ DnsScopeMatch dns_scope_good_domain(DnsScope *s, int ifindex, uint64_t flags, co
return DNS_SCOPE_MAYBE;
return DNS_SCOPE_NO;
- }
- assert_not_reached("Unknown scope protocol");
+ default:
+ assert_not_reached("Unknown scope protocol");
+ }
}
int dns_scope_good_key(DnsScope *s, DnsResourceKey *key) {
@@ -623,24 +629,20 @@ DnsTransaction *dns_scope_find_transaction(DnsScope *scope, DnsResourceKey *key,
assert(scope);
assert(key);
- /* Try to find an ongoing transaction that is a equal or a
- * superset of the specified question */
-
- LIST_FOREACH(transactions_by_scope, t, scope->transactions) {
-
- /* Refuse reusing transactions that completed based on
- * cached data instead of a real packet, if that's
- * requested. */
- if (!cache_ok &&
- IN_SET(t->state, DNS_TRANSACTION_SUCCESS, DNS_TRANSACTION_FAILURE) &&
- !t->received)
- continue;
+ /* Try to find an ongoing transaction that is a equal to the
+ * specified question */
+ t = hashmap_get(scope->transactions, key);
+ if (!t)
+ return NULL;
- if (dns_resource_key_equal(t->key, key) > 0)
- return t;
- }
+ /* Refuse reusing transactions that completed based on cached
+ * data instead of a real packet, if that's requested. */
+ if (!cache_ok &&
+ IN_SET(t->state, DNS_TRANSACTION_SUCCESS, DNS_TRANSACTION_FAILURE) &&
+ !t->received)
+ return NULL;
- return NULL;
+ return t;
}
static int dns_scope_make_conflict_packet(
diff --git a/src/resolve/resolved-dns-scope.h b/src/resolve/resolved-dns-scope.h
index 47f285db47..88fb8224e2 100644
--- a/src/resolve/resolved-dns-scope.h
+++ b/src/resolve/resolved-dns-scope.h
@@ -60,7 +60,7 @@ struct DnsScope {
usec_t resend_timeout;
usec_t max_rtt;
- LIST_HEAD(DnsTransaction, transactions);
+ Hashmap *transactions;
LIST_FIELDS(DnsScope, scopes);
};
diff --git a/src/resolve/resolved-dns-transaction.c b/src/resolve/resolved-dns-transaction.c
index 81156dfa45..7b84c1bab8 100644
--- a/src/resolve/resolved-dns-transaction.c
+++ b/src/resolve/resolved-dns-transaction.c
@@ -35,7 +35,6 @@ DnsTransaction* dns_transaction_free(DnsTransaction *t) {
sd_event_source_unref(t->timeout_event_source);
- dns_resource_key_unref(t->key);
dns_packet_unref(t->sent);
dns_packet_unref(t->received);
dns_answer_unref(t->cached);
@@ -47,12 +46,14 @@ DnsTransaction* dns_transaction_free(DnsTransaction *t) {
dns_stream_free(t->stream);
if (t->scope) {
- LIST_REMOVE(transactions_by_scope, t->scope->transactions, t);
+ hashmap_remove(t->scope->transactions, t->key);
if (t->id != 0)
hashmap_remove(t->scope->manager->dns_transactions, UINT_TO_PTR(t->id));
}
+ dns_resource_key_unref(t->key);
+
while ((q = set_steal_first(t->queries)))
set_remove(q->transactions, t);
set_free(t->queries);
@@ -89,14 +90,18 @@ int dns_transaction_new(DnsTransaction **ret, DnsScope *s, DnsResourceKey *key)
if (r < 0)
return r;
+ r = hashmap_ensure_allocated(&s->transactions, &dns_resource_key_hash_ops);
+ if (r < 0)
+ return r;
+
t = new0(DnsTransaction, 1);
if (!t)
return -ENOMEM;
t->dns_fd = -1;
-
t->key = dns_resource_key_ref(key);
+ /* Find a fresh, unused transaction id */
do
random_bytes(&t->id, sizeof(t->id));
while (t->id == 0 ||
@@ -108,7 +113,12 @@ int dns_transaction_new(DnsTransaction **ret, DnsScope *s, DnsResourceKey *key)
return r;
}
- LIST_PREPEND(transactions_by_scope, s->transactions, t);
+ r = hashmap_put(s->transactions, t->key, t);
+ if (r < 0) {
+ hashmap_remove(s->manager->dns_transactions, UINT_TO_PTR(t->id));
+ return r;
+ }
+
t->scope = s;
if (ret)
@@ -176,9 +186,6 @@ void dns_transaction_complete(DnsTransaction *t, DnsTransactionState state) {
assert(t);
assert(!IN_SET(state, DNS_TRANSACTION_NULL, DNS_TRANSACTION_PENDING));
- if (!IN_SET(t->state, DNS_TRANSACTION_NULL, DNS_TRANSACTION_PENDING))
- return;
-
/* Note that this call might invalidate the query. Callers
* should hence not attempt to access the query or transaction
* after calling this function. */
@@ -253,10 +260,12 @@ static int dns_transaction_open_tcp(DnsTransaction *t) {
if (t->stream)
return 0;
- if (t->scope->protocol == DNS_PROTOCOL_DNS)
+ switch (t->scope->protocol) {
+ case DNS_PROTOCOL_DNS:
fd = dns_scope_tcp_socket(t->scope, AF_UNSPEC, NULL, 53, &server);
- else if (t->scope->protocol == DNS_PROTOCOL_LLMNR) {
+ break;
+ case DNS_PROTOCOL_LLMNR:
/* When we already received a reply to this (but it was truncated), send to its sender address */
if (t->received)
fd = dns_scope_tcp_socket(t->scope, t->received->family, &t->received->sender, t->received->sender_port, NULL);
@@ -274,12 +283,16 @@ static int dns_transaction_open_tcp(DnsTransaction *t) {
if (r == 0)
return -EINVAL;
if (family != t->scope->family)
- return -EAFNOSUPPORT;
+ return -ESRCH;
fd = dns_scope_tcp_socket(t->scope, family, &address, LLMNR_PORT, NULL);
}
- } else
+
+ break;
+
+ default:
return -EAFNOSUPPORT;
+ }
if (fd < 0)
return fd;
@@ -335,7 +348,8 @@ void dns_transaction_process_reply(DnsTransaction *t, DnsPacket *p) {
* should hence not attempt to access the query or transaction
* after calling this function. */
- if (t->scope->protocol == DNS_PROTOCOL_LLMNR) {
+ switch (t->scope->protocol) {
+ case DNS_PROTOCOL_LLMNR:
assert(t->scope->link);
/* For LLMNR we will not accept any packets from other
@@ -354,6 +368,14 @@ void dns_transaction_process_reply(DnsTransaction *t, DnsPacket *p) {
dns_transaction_tentative(t, p);
return;
}
+
+ break;
+
+ case DNS_PROTOCOL_DNS:
+ break;
+
+ default:
+ assert_not_reached("Invalid DNS protocol.");
}
if (t->received != p) {
@@ -390,7 +412,7 @@ void dns_transaction_process_reply(DnsTransaction *t, DnsPacket *p) {
break;
default:
- assert_not_reached("Invalid DNS protocol.");
+ break;
}
if (DNS_PACKET_TC(p)) {
diff --git a/src/systemctl/systemctl.c b/src/systemctl/systemctl.c
index 3cd267ec5a..587793fb17 100644
--- a/src/systemctl/systemctl.c
+++ b/src/systemctl/systemctl.c
@@ -2794,6 +2794,33 @@ static int reboot_with_logind(sd_bus *bus, enum action a) {
return -EINVAL;
}
+ if (!strv_isempty(arg_wall)) {
+ _cleanup_free_ char *m;
+
+ m = strv_join(arg_wall, " ");
+ if (!m)
+ return log_oom();
+
+ r = sd_bus_call_method(
+ bus,
+ "org.freedesktop.login1",
+ "/org/freedesktop/login1",
+ "org.freedesktop.login1.Manager",
+ "SetWallMessage",
+ &error,
+ NULL,
+ "sb",
+ m,
+ !arg_no_wall);
+
+ if (r < 0) {
+ log_warning_errno(r, "Failed to set wall message, ignoring: %s",
+ bus_error_message(&error, r));
+ sd_bus_error_free(&error);
+ }
+ }
+
+
r = sd_bus_call_method(
bus,
"org.freedesktop.login1",
@@ -6265,6 +6292,7 @@ static int systemctl_parse_argv(int argc, char *argv[]) {
ARG_PRESET_MODE,
ARG_FIRMWARE_SETUP,
ARG_NOW,
+ ARG_MESSAGE,
};
static const struct option options[] = {
@@ -6309,6 +6337,7 @@ static int systemctl_parse_argv(int argc, char *argv[]) {
{ "preset-mode", required_argument, NULL, ARG_PRESET_MODE },
{ "firmware-setup", no_argument, NULL, ARG_FIRMWARE_SETUP },
{ "now", no_argument, NULL, ARG_NOW },
+ { "message", required_argument, NULL, ARG_MESSAGE },
{}
};
@@ -6593,6 +6622,11 @@ static int systemctl_parse_argv(int argc, char *argv[]) {
arg_now = true;
break;
+ case ARG_MESSAGE:
+ if (strv_extend(&arg_wall, optarg) < 0)
+ return log_oom();
+ break;
+
case '?':
return -EINVAL;
@@ -7361,30 +7395,20 @@ static int halt_main(sd_bus *bus) {
if (!m)
return log_oom();
- r = sd_bus_set_property(
- b,
- "org.freedesktop.login1",
- "/org/freedesktop/login1",
- "org.freedesktop.login1.Manager",
- "WallMessage",
- &error,
- "s", m);
- if (r < 0) {
- log_warning_errno(r, "Failed to set WallMessage property in logind: %s",
- bus_error_message(&error, r));
- sd_bus_error_free(&error);
- }
+ r = sd_bus_call_method(
+ b,
+ "org.freedesktop.login1",
+ "/org/freedesktop/login1",
+ "org.freedesktop.login1.Manager",
+ "SetWallMessage",
+ &error,
+ NULL,
+ "sb",
+ m,
+ !arg_no_wall);
- r = sd_bus_set_property(
- b,
- "org.freedesktop.login1",
- "/org/freedesktop/login1",
- "org.freedesktop.login1.Manager",
- "EnableWallMessages",
- &error,
- "b", !arg_no_wall);
if (r < 0) {
- log_warning_errno(r, "Failed to set EnableWallMessages property in logind: %s",
+ log_warning_errno(r, "Failed to set wall message, ignoring: %s",
bus_error_message(&error, r));
sd_bus_error_free(&error);
}
@@ -7542,30 +7566,20 @@ int main(int argc, char*argv[]) {
}
}
- r = sd_bus_set_property(
- b,
- "org.freedesktop.login1",
- "/org/freedesktop/login1",
- "org.freedesktop.login1.Manager",
- "WallMessage",
- &error,
- "s", arg_wall);
- if (r < 0) {
- log_warning_errno(r, "Failed to set WallMessage property in logind: %s",
- bus_error_message(&error, r));
- sd_bus_error_free(&error);
- }
+ r = sd_bus_call_method(
+ b,
+ "org.freedesktop.login1",
+ "/org/freedesktop/login1",
+ "org.freedesktop.login1.Manager",
+ "SetWallMessage",
+ &error,
+ NULL,
+ "sb",
+ m,
+ !arg_no_wall);
- r = sd_bus_set_property(
- b,
- "org.freedesktop.login1",
- "/org/freedesktop/login1",
- "org.freedesktop.login1.Manager",
- "EnableWallMessages",
- &error,
- "b", !arg_no_wall);
if (r < 0) {
- log_warning_errno(r, "Failed to set EnableWallMessages property in logind: %s",
+ log_warning_errno(r, "Failed to set wall message, ignoring: %s",
bus_error_message(&error, r));
sd_bus_error_free(&error);
}